| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | use docopt::Docopt;
 | 
					
						
							|  |  |  | use hbb_common::env_logger::{init_from_env, Env, DEFAULT_FILTER_ENV};
 | 
					
						
							|  |  |  | use scrap::{
 | 
					
						
							|  |  |  |     codec::{EncoderApi, EncoderCfg},
 | 
					
						
							|  |  |  |     Capturer, Display, TraitCapturer, VpxDecoder, VpxDecoderConfig, VpxEncoder, VpxEncoderConfig,
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     VpxVideoCodecId::{self, *},
 | 
					
						
							|  |  |  |     STRIDE_ALIGN,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | };
 | 
					
						
							|  |  |  | use std::{io::Write, time::Instant};
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // cargo run --package scrap --example benchmark --release --features hwcodec
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const USAGE: &'static str = "
 | 
					
						
							|  |  |  | Codec benchmark.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Usage: | 
					
						
							|  |  |  |   benchmark [--count=COUNT] [--bitrate=KBS] [--hw-pixfmt=PIXFMT]
 | 
					
						
							|  |  |  |   benchmark (-h | --help)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Options: | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |   -h --help             Show this screen.
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |   --count=COUNT         Capture frame count [default: 100].
 | 
					
						
							|  |  |  |   --bitrate=KBS         Video bitrate in kilobits per second [default: 5000].
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |   --hw-pixfmt=PIXFMT    Hardware codec pixfmt. [default: i420]
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |                         Valid values: i420, nv12.
 | 
					
						
							|  |  |  | ";
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[derive(Debug, serde::Deserialize)]
 | 
					
						
							|  |  |  | struct Args {
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |     flag_count: usize,
 | 
					
						
							|  |  |  |     flag_bitrate: usize,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     flag_hw_pixfmt: Pixfmt,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[derive(Debug, serde::Deserialize)]
 | 
					
						
							|  |  |  | enum Pixfmt {
 | 
					
						
							|  |  |  |     I420,
 | 
					
						
							|  |  |  |     NV12,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | fn main() {
 | 
					
						
							|  |  |  |     init_from_env(Env::default().filter_or(DEFAULT_FILTER_ENV, "info"));
 | 
					
						
							|  |  |  |     let args: Args = Docopt::new(USAGE)
 | 
					
						
							|  |  |  |         .and_then(|d| d.deserialize())
 | 
					
						
							|  |  |  |         .unwrap_or_else(|e| e.exit());
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |     let bitrate_k = args.flag_bitrate;
 | 
					
						
							|  |  |  |     let yuv_count = args.flag_count;
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     let (yuvs, width, height) = capture_yuv(yuv_count);
 | 
					
						
							|  |  |  |     println!(
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |         "benchmark {}x{} bitrate:{}k hw_pixfmt:{:?}",
 | 
					
						
							|  |  |  |         width, height, bitrate_k, args.flag_hw_pixfmt
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     );
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     [VP8, VP9].map(|c| test_vpx(c, &yuvs, width, height, bitrate_k, yuv_count));
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     #[cfg(feature = "hwcodec")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |         use hwcodec::AVPixelFormat;
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         let hw_pixfmt = match args.flag_hw_pixfmt {
 | 
					
						
							|  |  |  |             Pixfmt::I420 => AVPixelFormat::AV_PIX_FMT_YUV420P,
 | 
					
						
							|  |  |  |             Pixfmt::NV12 => AVPixelFormat::AV_PIX_FMT_NV12,
 | 
					
						
							|  |  |  |         };
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |         let yuvs = hw::vpx_yuv_to_hw_yuv(yuvs, width, height, hw_pixfmt);
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         hw::test(&yuvs, width, height, bitrate_k, yuv_count, hw_pixfmt);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | fn capture_yuv(yuv_count: usize) -> (Vec<Vec<u8>>, usize, usize) {
 | 
					
						
							|  |  |  |     let mut index = 0;
 | 
					
						
							|  |  |  |     let mut displays = Display::all().unwrap();
 | 
					
						
							|  |  |  |     for i in 0..displays.len() {
 | 
					
						
							|  |  |  |         if displays[i].is_primary() {
 | 
					
						
							|  |  |  |             index = i;
 | 
					
						
							|  |  |  |             break;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     let d = displays.remove(index);
 | 
					
						
							|  |  |  |     let mut c = Capturer::new(d, true).unwrap();
 | 
					
						
							|  |  |  |     let mut v = vec![];
 | 
					
						
							|  |  |  |     loop {
 | 
					
						
							|  |  |  |         if let Ok(frame) = c.frame(std::time::Duration::from_millis(30)) {
 | 
					
						
							|  |  |  |             v.push(frame.0.to_vec());
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |             print!("\rcapture {}/{}", v.len(), yuv_count);
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |             std::io::stdout().flush().ok();
 | 
					
						
							|  |  |  |             if v.len() == yuv_count {
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |                 println!();
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |                 return (v, c.width(), c.height());
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  | fn test_vpx(
 | 
					
						
							|  |  |  |     codec_id: VpxVideoCodecId,
 | 
					
						
							|  |  |  |     yuvs: &Vec<Vec<u8>>,
 | 
					
						
							|  |  |  |     width: usize,
 | 
					
						
							|  |  |  |     height: usize,
 | 
					
						
							|  |  |  |     bitrate_k: usize,
 | 
					
						
							|  |  |  |     yuv_count: usize,
 | 
					
						
							|  |  |  | ) {
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     let config = EncoderCfg::VPX(VpxEncoderConfig {
 | 
					
						
							|  |  |  |         width: width as _,
 | 
					
						
							|  |  |  |         height: height as _,
 | 
					
						
							|  |  |  |         timebase: [1, 1000],
 | 
					
						
							|  |  |  |         bitrate: bitrate_k as _,
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |         codec: codec_id,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         num_threads: (num_cpus::get() / 2) as _,
 | 
					
						
							|  |  |  |     });
 | 
					
						
							|  |  |  |     let mut encoder = VpxEncoder::new(config).unwrap();
 | 
					
						
							|  |  |  |     let start = Instant::now();
 | 
					
						
							|  |  |  |     for yuv in yuvs {
 | 
					
						
							|  |  |  |         let _ = encoder
 | 
					
						
							|  |  |  |             .encode(start.elapsed().as_millis() as _, yuv, STRIDE_ALIGN)
 | 
					
						
							|  |  |  |             .unwrap();
 | 
					
						
							|  |  |  |         let _ = encoder.flush().unwrap();
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     println!(
 | 
					
						
							|  |  |  |         "{:?} encode: {:?}",
 | 
					
						
							|  |  |  |         codec_id,
 | 
					
						
							|  |  |  |         start.elapsed() / yuv_count as _
 | 
					
						
							|  |  |  |     );
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // prepare data separately
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     let mut vpxs = vec![];
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     let start = Instant::now();
 | 
					
						
							|  |  |  |     for yuv in yuvs {
 | 
					
						
							|  |  |  |         for ref frame in encoder
 | 
					
						
							|  |  |  |             .encode(start.elapsed().as_millis() as _, yuv, STRIDE_ALIGN)
 | 
					
						
							|  |  |  |             .unwrap()
 | 
					
						
							|  |  |  |         {
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |             vpxs.push(frame.data.to_vec());
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |         for ref frame in encoder.flush().unwrap() {
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |             vpxs.push(frame.data.to_vec());
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     assert_eq!(vpxs.len(), yuv_count);
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     let mut decoder = VpxDecoder::new(VpxDecoderConfig {
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |         codec: codec_id,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         num_threads: (num_cpus::get() / 2) as _,
 | 
					
						
							|  |  |  |     })
 | 
					
						
							|  |  |  |     .unwrap();
 | 
					
						
							|  |  |  |     let start = Instant::now();
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     for vpx in vpxs {
 | 
					
						
							|  |  |  |         let _ = decoder.decode(&vpx);
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         let _ = decoder.flush();
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     println!(
 | 
					
						
							|  |  |  |         "{:?} decode: {:?}",
 | 
					
						
							|  |  |  |         codec_id,
 | 
					
						
							|  |  |  |         start.elapsed() / yuv_count as _
 | 
					
						
							|  |  |  |     );
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[cfg(feature = "hwcodec")]
 | 
					
						
							|  |  |  | mod hw {
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |     use super::*;
 | 
					
						
							|  |  |  |     use hwcodec::{
 | 
					
						
							|  |  |  |         decode::{DecodeContext, Decoder},
 | 
					
						
							|  |  |  |         encode::{EncodeContext, Encoder},
 | 
					
						
							|  |  |  |         ffmpeg::{ffmpeg_linesize_offset_length, CodecInfo, CodecInfos},
 | 
					
						
							|  |  |  |         AVPixelFormat,
 | 
					
						
							|  |  |  |         Quality::*,
 | 
					
						
							|  |  |  |         RateControl::*,
 | 
					
						
							|  |  |  |     };
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     use scrap::{
 | 
					
						
							|  |  |  |         convert::{
 | 
					
						
							|  |  |  |             hw::{hw_bgra_to_i420, hw_bgra_to_nv12},
 | 
					
						
							|  |  |  |             i420_to_bgra,
 | 
					
						
							|  |  |  |         },
 | 
					
						
							|  |  |  |         HW_STRIDE_ALIGN,
 | 
					
						
							|  |  |  |     };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn test(
 | 
					
						
							|  |  |  |         yuvs: &Vec<Vec<u8>>,
 | 
					
						
							|  |  |  |         width: usize,
 | 
					
						
							|  |  |  |         height: usize,
 | 
					
						
							|  |  |  |         bitrate_k: usize,
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |         yuv_count: usize,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         pixfmt: AVPixelFormat,
 | 
					
						
							|  |  |  |     ) {
 | 
					
						
							|  |  |  |         let ctx = EncodeContext {
 | 
					
						
							|  |  |  |             name: String::from(""),
 | 
					
						
							|  |  |  |             width: width as _,
 | 
					
						
							|  |  |  |             height: height as _,
 | 
					
						
							|  |  |  |             pixfmt,
 | 
					
						
							|  |  |  |             align: 0,
 | 
					
						
							|  |  |  |             bitrate: (bitrate_k * 1000) as _,
 | 
					
						
							|  |  |  |             timebase: [1, 30],
 | 
					
						
							|  |  |  |             gop: 60,
 | 
					
						
							|  |  |  |             quality: Quality_Default,
 | 
					
						
							|  |  |  |             rc: RC_DEFAULT,
 | 
					
						
							|  |  |  |         };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let encoders = Encoder::available_encoders(ctx.clone());
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |         println!("hw encoders: {}", encoders.len());
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         let best = CodecInfo::score(encoders.clone());
 | 
					
						
							|  |  |  |         for info in encoders {
 | 
					
						
							|  |  |  |             test_encoder(info.clone(), ctx.clone(), yuvs, is_best(&best, &info));
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let (h264s, h265s) = prepare_h26x(best, ctx.clone(), yuvs);
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |         assert!(h264s.is_empty() || h264s.len() == yuv_count);
 | 
					
						
							|  |  |  |         assert!(h265s.is_empty() || h265s.len() == yuv_count);
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         let decoders = Decoder::available_decoders();
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |         println!("hw decoders: {}", decoders.len());
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         let best = CodecInfo::score(decoders.clone());
 | 
					
						
							|  |  |  |         for info in decoders {
 | 
					
						
							|  |  |  |             let h26xs = if info.name.contains("h264") {
 | 
					
						
							|  |  |  |                 &h264s
 | 
					
						
							|  |  |  |             } else {
 | 
					
						
							|  |  |  |                 &h265s
 | 
					
						
							|  |  |  |             };
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |             if h26xs.len() == yuvs.len() {
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |                 test_decoder(info.clone(), h26xs, is_best(&best, &info));
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn test_encoder(info: CodecInfo, ctx: EncodeContext, yuvs: &Vec<Vec<u8>>, best: bool) {
 | 
					
						
							|  |  |  |         let mut ctx = ctx;
 | 
					
						
							|  |  |  |         ctx.name = info.name;
 | 
					
						
							|  |  |  |         let mut encoder = Encoder::new(ctx.clone()).unwrap();
 | 
					
						
							|  |  |  |         let start = Instant::now();
 | 
					
						
							|  |  |  |         for yuv in yuvs {
 | 
					
						
							|  |  |  |             let _ = encoder.encode(yuv).unwrap();
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         println!(
 | 
					
						
							|  |  |  |             "{}{}: {:?}",
 | 
					
						
							|  |  |  |             if best { "*" } else { "" },
 | 
					
						
							|  |  |  |             ctx.name,
 | 
					
						
							|  |  |  |             start.elapsed() / yuvs.len() as _
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn test_decoder(info: CodecInfo, h26xs: &Vec<Vec<u8>>, best: bool) {
 | 
					
						
							|  |  |  |         let ctx = DecodeContext {
 | 
					
						
							|  |  |  |             name: info.name,
 | 
					
						
							|  |  |  |             device_type: info.hwdevice,
 | 
					
						
							|  |  |  |         };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let mut decoder = Decoder::new(ctx.clone()).unwrap();
 | 
					
						
							|  |  |  |         let start = Instant::now();
 | 
					
						
							|  |  |  |         let mut cnt = 0;
 | 
					
						
							|  |  |  |         for h26x in h26xs {
 | 
					
						
							|  |  |  |             let _ = decoder.decode(h26x).unwrap();
 | 
					
						
							|  |  |  |             cnt += 1;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |         let device = format!("{:?}", ctx.device_type).to_lowercase();
 | 
					
						
							|  |  |  |         let device = device.split("_").last().unwrap();
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         println!(
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |             "{}{} {}: {:?}",
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |             if best { "*" } else { "" },
 | 
					
						
							|  |  |  |             ctx.name,
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |             device,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |             start.elapsed() / cnt
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn prepare_h26x(
 | 
					
						
							|  |  |  |         best: CodecInfos,
 | 
					
						
							|  |  |  |         ctx: EncodeContext,
 | 
					
						
							|  |  |  |         yuvs: &Vec<Vec<u8>>,
 | 
					
						
							|  |  |  |     ) -> (Vec<Vec<u8>>, Vec<Vec<u8>>) {
 | 
					
						
							|  |  |  |         let f = |info: Option<CodecInfo>| {
 | 
					
						
							|  |  |  |             let mut h26xs = vec![];
 | 
					
						
							|  |  |  |             if let Some(info) = info {
 | 
					
						
							|  |  |  |                 let mut ctx = ctx.clone();
 | 
					
						
							|  |  |  |                 ctx.name = info.name;
 | 
					
						
							|  |  |  |                 let mut encoder = Encoder::new(ctx).unwrap();
 | 
					
						
							|  |  |  |                 for yuv in yuvs {
 | 
					
						
							|  |  |  |                     let h26x = encoder.encode(yuv).unwrap();
 | 
					
						
							|  |  |  |                     for frame in h26x {
 | 
					
						
							|  |  |  |                         h26xs.push(frame.data.to_vec());
 | 
					
						
							|  |  |  |                     }
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |             h26xs
 | 
					
						
							|  |  |  |         };
 | 
					
						
							|  |  |  |         (f(best.h264), f(best.h265))
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn is_best(best: &CodecInfos, info: &CodecInfo) -> bool {
 | 
					
						
							|  |  |  |         Some(info.clone()) == best.h264 || Some(info.clone()) == best.h265
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     pub fn vpx_yuv_to_hw_yuv(
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         yuvs: Vec<Vec<u8>>,
 | 
					
						
							|  |  |  |         width: usize,
 | 
					
						
							|  |  |  |         height: usize,
 | 
					
						
							|  |  |  |         pixfmt: AVPixelFormat,
 | 
					
						
							|  |  |  |     ) -> Vec<Vec<u8>> {
 | 
					
						
							|  |  |  |         let yuvs = yuvs;
 | 
					
						
							|  |  |  |         let mut bgra = vec![];
 | 
					
						
							|  |  |  |         let mut v = vec![];
 | 
					
						
							|  |  |  |         let (linesize, offset, length) =
 | 
					
						
							|  |  |  |             ffmpeg_linesize_offset_length(pixfmt, width, height, HW_STRIDE_ALIGN).unwrap();
 | 
					
						
							|  |  |  |         for mut yuv in yuvs {
 | 
					
						
							|  |  |  |             i420_to_bgra(width, height, &yuv, &mut bgra);
 | 
					
						
							|  |  |  |             if pixfmt == AVPixelFormat::AV_PIX_FMT_YUV420P {
 | 
					
						
							|  |  |  |                 hw_bgra_to_i420(width, height, &linesize, &offset, length, &bgra, &mut yuv);
 | 
					
						
							|  |  |  |             } else {
 | 
					
						
							|  |  |  |                 hw_bgra_to_nv12(width, height, &linesize, &offset, length, &bgra, &mut yuv);
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |             v.push(yuv);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         v
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 |