| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | use docopt::Docopt;
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  | use hbb_common::{
 | 
					
						
							|  |  |  |     env_logger::{init_from_env, Env, DEFAULT_FILTER_ENV},
 | 
					
						
							|  |  |  |     log,
 | 
					
						
							|  |  |  | };
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | use scrap::{
 | 
					
						
							| 
									
										
										
										
											2023-07-20 21:16:38 +08:00
										 |  |  |     aom::{AomDecoder, AomEncoder, AomEncoderConfig},
 | 
					
						
							| 
									
										
										
										
											2023-12-11 23:46:32 +09:00
										 |  |  |     codec::{EncoderApi, EncoderCfg, Quality as Q},
 | 
					
						
							| 
									
										
										
										
											2024-01-02 16:58:10 +08:00
										 |  |  |     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
										 |  |  | };
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  | use std::{
 | 
					
						
							|  |  |  |     io::Write,
 | 
					
						
							|  |  |  |     time::{Duration, Instant},
 | 
					
						
							|  |  |  | };
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // cargo run --package scrap --example benchmark --release --features hwcodec
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const USAGE: &'static str = "
 | 
					
						
							|  |  |  | Codec benchmark.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Usage: | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |   benchmark [--count=COUNT] [--quality=QUALITY] [--i444]
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |   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].
 | 
					
						
							| 
									
										
										
										
											2023-07-19 13:11:24 +08:00
										 |  |  |   --quality=QUALITY     Video quality [default: Balanced].
 | 
					
						
							|  |  |  |                         Valid values: Best, Balanced, Low.
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |   --i444                I444.
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | ";
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  | #[derive(Debug, serde::Deserialize, Clone, Copy)]
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | struct Args {
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |     flag_count: usize,
 | 
					
						
							| 
									
										
										
										
											2023-07-19 13:11:24 +08:00
										 |  |  |     flag_quality: Quality,
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |     flag_i444: bool,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  | #[derive(Debug, serde::Deserialize, Clone, Copy)]
 | 
					
						
							| 
									
										
										
										
											2023-07-19 13:11:24 +08:00
										 |  |  | enum Quality {
 | 
					
						
							|  |  |  |     Best,
 | 
					
						
							|  |  |  |     Balanced,
 | 
					
						
							|  |  |  |     Low,
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | 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-07-19 13:11:24 +08:00
										 |  |  |     let quality = args.flag_quality;
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |     let yuv_count = args.flag_count;
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     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);
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |     let mut c = Capturer::new(d).unwrap();
 | 
					
						
							|  |  |  |     let width = c.width();
 | 
					
						
							|  |  |  |     let height = c.height();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     println!(
 | 
					
						
							|  |  |  |         "benchmark {}x{} quality:{:?}, i444:{:?}",
 | 
					
						
							|  |  |  |         width, height, quality, args.flag_i444
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  |     let quality = match quality {
 | 
					
						
							|  |  |  |         Quality::Best => Q::Best,
 | 
					
						
							|  |  |  |         Quality::Balanced => Q::Balanced,
 | 
					
						
							|  |  |  |         Quality::Low => Q::Low,
 | 
					
						
							|  |  |  |     };
 | 
					
						
							|  |  |  |     [VP8, VP9].map(|codec| {
 | 
					
						
							|  |  |  |         test_vpx(
 | 
					
						
							|  |  |  |             &mut c,
 | 
					
						
							|  |  |  |             codec,
 | 
					
						
							|  |  |  |             width,
 | 
					
						
							|  |  |  |             height,
 | 
					
						
							|  |  |  |             quality,
 | 
					
						
							|  |  |  |             yuv_count,
 | 
					
						
							|  |  |  |             if codec == VP8 { false } else { args.flag_i444 },
 | 
					
						
							|  |  |  |         )
 | 
					
						
							|  |  |  |     });
 | 
					
						
							|  |  |  |     test_av1(&mut c, width, height, quality, yuv_count, args.flag_i444);
 | 
					
						
							|  |  |  |     #[cfg(feature = "hwcodec")]
 | 
					
						
							|  |  |  |     {
 | 
					
						
							|  |  |  |         hw::test(&mut c, width, height, quality, yuv_count);
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  | fn test_vpx(
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |     c: &mut Capturer,
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     codec_id: VpxVideoCodecId,
 | 
					
						
							|  |  |  |     width: usize,
 | 
					
						
							|  |  |  |     height: usize,
 | 
					
						
							| 
									
										
										
										
											2023-07-19 13:11:24 +08:00
										 |  |  |     quality: Q,
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     yuv_count: usize,
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |     i444: bool,
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  | ) {
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     let config = EncoderCfg::VPX(VpxEncoderConfig {
 | 
					
						
							|  |  |  |         width: width as _,
 | 
					
						
							|  |  |  |         height: height as _,
 | 
					
						
							| 
									
										
										
										
											2023-07-19 13:11:24 +08:00
										 |  |  |         quality,
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |         codec: codec_id,
 | 
					
						
							| 
									
										
										
										
											2023-08-07 21:32:36 +08:00
										 |  |  |         keyframe_interval: None,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     });
 | 
					
						
							| 
									
										
										
										
											2023-12-11 23:46:32 +09:00
										 |  |  |     let mut encoder = VpxEncoder::new(config, i444).unwrap();
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     let mut vpxs = vec![];
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     let start = Instant::now();
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |     let mut size = 0;
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |     let mut yuv = Vec::new();
 | 
					
						
							|  |  |  |     let mut mid_data = Vec::new();
 | 
					
						
							|  |  |  |     let mut counter = 0;
 | 
					
						
							|  |  |  |     let mut time_sum = Duration::ZERO;
 | 
					
						
							|  |  |  |     loop {
 | 
					
						
							|  |  |  |         match c.frame(std::time::Duration::from_millis(30)) {
 | 
					
						
							|  |  |  |             Ok(frame) => {
 | 
					
						
							|  |  |  |                 let tmp_timer = Instant::now();
 | 
					
						
							| 
									
										
										
										
											2024-01-02 16:58:10 +08:00
										 |  |  |                 let frame = frame.to(encoder.yuvfmt(), &mut yuv, &mut mid_data).unwrap();
 | 
					
						
							|  |  |  |                 let yuv = frame.yuv().unwrap();
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |                 for ref frame in encoder
 | 
					
						
							|  |  |  |                     .encode(start.elapsed().as_millis() as _, &yuv, STRIDE_ALIGN)
 | 
					
						
							|  |  |  |                     .unwrap()
 | 
					
						
							|  |  |  |                 {
 | 
					
						
							|  |  |  |                     size += frame.data.len();
 | 
					
						
							|  |  |  |                     vpxs.push(frame.data.to_vec());
 | 
					
						
							|  |  |  |                     counter += 1;
 | 
					
						
							|  |  |  |                     print!("\r{codec_id:?} {}/{}", counter, yuv_count);
 | 
					
						
							|  |  |  |                     std::io::stdout().flush().ok();
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							|  |  |  |                 for ref frame in encoder.flush().unwrap() {
 | 
					
						
							|  |  |  |                     size += frame.data.len();
 | 
					
						
							|  |  |  |                     vpxs.push(frame.data.to_vec());
 | 
					
						
							|  |  |  |                     counter += 1;
 | 
					
						
							|  |  |  |                     print!("\r{codec_id:?} {}/{}", counter, yuv_count);
 | 
					
						
							|  |  |  |                     std::io::stdout().flush().ok();
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							|  |  |  |                 time_sum += tmp_timer.elapsed();
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |             Err(e) => {
 | 
					
						
							|  |  |  |                 log::error!("{e:?}");
 | 
					
						
							|  |  |  |             }
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |         if counter >= yuv_count {
 | 
					
						
							|  |  |  |             println!();
 | 
					
						
							|  |  |  |             break;
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-31 16:10:52 +08:00
										 |  |  |     assert_eq!(vpxs.len(), yuv_count);
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |     println!(
 | 
					
						
							|  |  |  |         "{:?} encode: {:?}, {} byte",
 | 
					
						
							|  |  |  |         codec_id,
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |         time_sum / yuv_count as _,
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |         size / yuv_count
 | 
					
						
							|  |  |  |     );
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 21:16:38 +08:00
										 |  |  |     let mut decoder = VpxDecoder::new(VpxDecoderConfig { codec: codec_id }).unwrap();
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     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
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  | fn test_av1(
 | 
					
						
							|  |  |  |     c: &mut Capturer,
 | 
					
						
							|  |  |  |     width: usize,
 | 
					
						
							|  |  |  |     height: usize,
 | 
					
						
							|  |  |  |     quality: Q,
 | 
					
						
							|  |  |  |     yuv_count: usize,
 | 
					
						
							|  |  |  |     i444: bool,
 | 
					
						
							|  |  |  | ) {
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |     let config = EncoderCfg::AOM(AomEncoderConfig {
 | 
					
						
							|  |  |  |         width: width as _,
 | 
					
						
							|  |  |  |         height: height as _,
 | 
					
						
							| 
									
										
										
										
											2023-07-19 13:11:24 +08:00
										 |  |  |         quality,
 | 
					
						
							| 
									
										
										
										
											2023-08-07 21:32:36 +08:00
										 |  |  |         keyframe_interval: None,
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |     });
 | 
					
						
							| 
									
										
										
										
											2023-12-11 23:46:32 +09:00
										 |  |  |     let mut encoder = AomEncoder::new(config, i444).unwrap();
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |     let start = Instant::now();
 | 
					
						
							|  |  |  |     let mut size = 0;
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |     let mut av1s: Vec<Vec<u8>> = vec![];
 | 
					
						
							|  |  |  |     let mut yuv = Vec::new();
 | 
					
						
							|  |  |  |     let mut mid_data = Vec::new();
 | 
					
						
							|  |  |  |     let mut counter = 0;
 | 
					
						
							|  |  |  |     let mut time_sum = Duration::ZERO;
 | 
					
						
							|  |  |  |     loop {
 | 
					
						
							|  |  |  |         match c.frame(std::time::Duration::from_millis(30)) {
 | 
					
						
							|  |  |  |             Ok(frame) => {
 | 
					
						
							|  |  |  |                 let tmp_timer = Instant::now();
 | 
					
						
							| 
									
										
										
										
											2024-01-02 16:58:10 +08:00
										 |  |  |                 let frame = frame.to(encoder.yuvfmt(), &mut yuv, &mut mid_data).unwrap();
 | 
					
						
							|  |  |  |                 let yuv = frame.yuv().unwrap();
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |                 for ref frame in encoder
 | 
					
						
							|  |  |  |                     .encode(start.elapsed().as_millis() as _, &yuv, STRIDE_ALIGN)
 | 
					
						
							|  |  |  |                     .unwrap()
 | 
					
						
							|  |  |  |                 {
 | 
					
						
							|  |  |  |                     size += frame.data.len();
 | 
					
						
							|  |  |  |                     av1s.push(frame.data.to_vec());
 | 
					
						
							|  |  |  |                     counter += 1;
 | 
					
						
							|  |  |  |                     print!("\rAV1 {}/{}", counter, yuv_count);
 | 
					
						
							|  |  |  |                     std::io::stdout().flush().ok();
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							|  |  |  |                 time_sum += tmp_timer.elapsed();
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |             Err(e) => {
 | 
					
						
							|  |  |  |                 log::error!("{e:?}");
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         if counter >= yuv_count {
 | 
					
						
							|  |  |  |             println!();
 | 
					
						
							|  |  |  |             break;
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     assert_eq!(av1s.len(), yuv_count);
 | 
					
						
							|  |  |  |     println!(
 | 
					
						
							|  |  |  |         "AV1 encode: {:?}, {} byte",
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |         time_sum / yuv_count as _,
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |         size / yuv_count
 | 
					
						
							|  |  |  |     );
 | 
					
						
							| 
									
										
										
										
											2023-07-20 21:16:38 +08:00
										 |  |  |     let mut decoder = AomDecoder::new().unwrap();
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |     let start = Instant::now();
 | 
					
						
							|  |  |  |     for av1 in av1s {
 | 
					
						
							|  |  |  |         let _ = decoder.decode(&av1);
 | 
					
						
							|  |  |  |         let _ = decoder.flush();
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     println!("AV1 decode: {:?}", start.elapsed() / yuv_count as _);
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | #[cfg(feature = "hwcodec")]
 | 
					
						
							|  |  |  | mod hw {
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |     use hwcodec::ffmpeg::CodecInfo;
 | 
					
						
							| 
									
										
										
										
											2024-01-22 20:01:17 +08:00
										 |  |  |     use scrap::{
 | 
					
						
							|  |  |  |         hwcodec::{HwDecoder, HwEncoder, HwEncoderConfig},
 | 
					
						
							|  |  |  |         CodecFormat,
 | 
					
						
							|  |  |  |     };
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |     use super::*;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn test(c: &mut Capturer, width: usize, height: usize, quality: Q, yuv_count: usize) {
 | 
					
						
							|  |  |  |         let best = HwEncoder::best();
 | 
					
						
							|  |  |  |         let mut h264s = Vec::new();
 | 
					
						
							|  |  |  |         let mut h265s = Vec::new();
 | 
					
						
							|  |  |  |         if let Some(info) = best.h264 {
 | 
					
						
							|  |  |  |             test_encoder(width, height, quality, info, c, yuv_count, &mut h264s);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  |         if let Some(info) = best.h265 {
 | 
					
						
							|  |  |  |             test_encoder(width, height, quality, info, c, yuv_count, &mut h265s);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2024-01-22 20:01:17 +08:00
										 |  |  |         test_decoder(CodecFormat::H264, &h264s);
 | 
					
						
							|  |  |  |         test_decoder(CodecFormat::H265, &h265s);
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fn test_encoder(
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         width: usize,
 | 
					
						
							|  |  |  |         height: usize,
 | 
					
						
							| 
									
										
										
										
											2023-07-19 13:11:24 +08:00
										 |  |  |         quality: Q,
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |         info: CodecInfo,
 | 
					
						
							|  |  |  |         c: &mut Capturer,
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |         yuv_count: usize,
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |         h26xs: &mut Vec<Vec<u8>>,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     ) {
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |         let mut encoder = HwEncoder::new(
 | 
					
						
							|  |  |  |             EncoderCfg::HW(HwEncoderConfig {
 | 
					
						
							|  |  |  |                 name: info.name.clone(),
 | 
					
						
							|  |  |  |                 width,
 | 
					
						
							|  |  |  |                 height,
 | 
					
						
							|  |  |  |                 quality,
 | 
					
						
							|  |  |  |                 keyframe_interval: None,
 | 
					
						
							|  |  |  |             }),
 | 
					
						
							| 
									
										
										
										
											2023-12-11 23:46:32 +09:00
										 |  |  |             false,
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |         )
 | 
					
						
							|  |  |  |         .unwrap();
 | 
					
						
							|  |  |  |         let mut size = 0;
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |         let mut yuv = Vec::new();
 | 
					
						
							|  |  |  |         let mut mid_data = Vec::new();
 | 
					
						
							|  |  |  |         let mut counter = 0;
 | 
					
						
							|  |  |  |         let mut time_sum = Duration::ZERO;
 | 
					
						
							|  |  |  |         loop {
 | 
					
						
							|  |  |  |             match c.frame(std::time::Duration::from_millis(30)) {
 | 
					
						
							|  |  |  |                 Ok(frame) => {
 | 
					
						
							|  |  |  |                     let tmp_timer = Instant::now();
 | 
					
						
							| 
									
										
										
										
											2024-01-02 16:58:10 +08:00
										 |  |  |                     let frame = frame.to(encoder.yuvfmt(), &mut yuv, &mut mid_data).unwrap();
 | 
					
						
							|  |  |  |                     let yuv = frame.yuv().unwrap();
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |                     for ref frame in encoder.encode(&yuv).unwrap() {
 | 
					
						
							|  |  |  |                         size += frame.data.len();
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |                         h26xs.push(frame.data.to_vec());
 | 
					
						
							|  |  |  |                         counter += 1;
 | 
					
						
							|  |  |  |                         print!("\r{:?} {}/{}", info.name, counter, yuv_count);
 | 
					
						
							|  |  |  |                         std::io::stdout().flush().ok();
 | 
					
						
							|  |  |  |                     }
 | 
					
						
							|  |  |  |                     time_sum += tmp_timer.elapsed();
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							|  |  |  |                 Err(e) => {
 | 
					
						
							|  |  |  |                     log::error!("{e:?}");
 | 
					
						
							|  |  |  |                 }
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |             }
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |             if counter >= yuv_count {
 | 
					
						
							|  |  |  |                 println!();
 | 
					
						
							|  |  |  |                 break;
 | 
					
						
							| 
									
										
										
										
											2023-05-08 20:35:24 +08:00
										 |  |  |             }
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |         println!(
 | 
					
						
							| 
									
										
										
										
											2023-10-27 15:44:07 +08:00
										 |  |  |             "{}: {:?}, {} byte",
 | 
					
						
							|  |  |  |             info.name,
 | 
					
						
							|  |  |  |             time_sum / yuv_count as u32,
 | 
					
						
							|  |  |  |             size / yuv_count,
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         );
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-22 20:01:17 +08:00
										 |  |  |     fn test_decoder(format: CodecFormat, h26xs: &Vec<Vec<u8>>) {
 | 
					
						
							|  |  |  |         let mut decoder = HwDecoder::new(format).unwrap();
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |         let start = Instant::now();
 | 
					
						
							|  |  |  |         let mut cnt = 0;
 | 
					
						
							|  |  |  |         for h26x in h26xs {
 | 
					
						
							|  |  |  |             let _ = decoder.decode(h26x).unwrap();
 | 
					
						
							|  |  |  |             cnt += 1;
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2024-01-22 20:01:17 +08:00
										 |  |  |         let device = format!("{:?}", decoder.info.hwdevice).to_lowercase();
 | 
					
						
							| 
									
										
										
										
											2023-03-04 11:06:22 +08:00
										 |  |  |         let device = device.split("_").last().unwrap();
 | 
					
						
							| 
									
										
										
										
											2024-01-22 20:01:17 +08:00
										 |  |  |         println!(
 | 
					
						
							|  |  |  |             "{} {}: {:?}",
 | 
					
						
							|  |  |  |             decoder.info.name,
 | 
					
						
							|  |  |  |             device,
 | 
					
						
							|  |  |  |             start.elapsed() / cnt
 | 
					
						
							|  |  |  |         );
 | 
					
						
							| 
									
										
										
										
											2023-03-03 16:07:30 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | }
 |