#![allow(unused_imports)] #![allow(unused_variables)] use clap::{App, Arg}; use himpp::{ hifb, himipi::{ComboDevAttrBuilder, DataType as MipiDataType, LaneDivideMode, MipiReceiver}, mpi::hdmi::{HdmiCore, HdmiId, HdmiPortBuilder}, mpi::sys::{SysBinder, SysManager, ViVpssMode}, mpi::types::{DynamicRange, PixelFormat, Rect, Size, VideoInterface, VideoStandard, WdrMode}, mpi::vb::{VbConfigBuilder, VbManager, VbRemapMode}, mpi::vi::{ ViChn, ViChnAttrBuilder, ViDev, ViDevAttrBuilder, ViDumpType, ViPipe, ViPipeAttrBuilder, ViRephaseMode, }, mpi::vo::{VoChn, VoChnAttrBuilder, VoDev, VoLayer, VoPubAttrBuilder, VoVideoLayerAttrBuilder}, mpi::vpss::{ VpssChn, VpssChnAttrBuilder, VpssChnMode, VpssCropInfo, VpssGrp, VpssGrpAttrBuilder, }, mpi::{sys, vb}, }; use pavo_traits::AlignUpwards; use poller::{EventContext, Events, Poller}; use std::fs::File; use std::io::prelude::*; use std::sync::Arc; fn main() -> Result<(), Box> { let matches = App::new("vi-vpss-vo") .version("1.0") .author("Varphone Wong ") .about("The example of pipeline: VI -> VPSS -> VO") .arg( Arg::with_name("framerate") .short("f") .long("framerate") .help("Set the Video Framerate") .takes_value(true), ) .arg( Arg::with_name("vi-size") .short("i") .long("vi-size") .help("Set the Video Input Size") .takes_value(true), ) .get_matches(); let fps: u32 = matches .value_of("framerate") .unwrap_or("25") .parse() .unwrap(); let vi_size = Size::from(matches.value_of("vi-size").unwrap_or("1280x720")); let vb_pool1 = (vi_size.width * vi_size.height * 3 / 2).align_upwards(64); let vb_pool2 = (vi_size.width * vi_size.height * 2).align_upwards(64); let vb_pool3: u32 = (1920 * 1080 * 3 / 2).align_upwards(64); let vb_conf = VbConfigBuilder::new() .pool(vb_pool1.into(), 8, VbRemapMode::None, "") .pool(vb_pool2.into(), 16, VbRemapMode::None, "") .pool(vb_pool3.into(), 3, VbRemapMode::None, "") .build(); let _vb_mgr = VbManager::new(&vb_conf, &[]); let _sys_mgr = SysManager::with_align(64, Some(_vb_mgr)); let vi_vpss_modes = [ ViVpssMode::BothOffline, // OnlineOffline ViVpssMode::BothOffline, ViVpssMode::BothOffline, ViVpssMode::BothOffline, ViVpssMode::BothOffline, ViVpssMode::BothOffline, ViVpssMode::BothOffline, ViVpssMode::BothOffline, ]; _sys_mgr.set_vi_vpss_mode(&vi_vpss_modes).unwrap(); let vo_attr = VoPubAttrBuilder::new() .with_bg_color(0x0000ffff) .with_video_interface(VideoInterface::Hdmi) .with_video_standard(VideoStandard::Hd1080p60) .build(); let vo_dev0 = Arc::new(VoDev::new(0, &vo_attr)); let vo_vl_attr = VoVideoLayerAttrBuilder::with_current(0) .with_disp_rect(Rect::new(0, 0, 1920, 1080)) .with_image_size(Size::new(1920, 1080)) .with_disp_framerate(60) .with_pixel_format(PixelFormat::YvuSemiPlanar420) .with_double_frame(false) .with_cluster_mode(false) .with_dynamic_range(DynamicRange::Sdr8) .build(); let vo_vl0 = Arc::new(VoLayer::new(0, &vo_vl_attr, Arc::clone(&vo_dev0))); vo_vl0.set_buf_len(3).unwrap(); vo_vl0.enable().unwrap(); let vo_chn0_attr = VoChnAttrBuilder::with_current(0, &vo_vl0) .with_priority(0) .with_disp_rect(Rect::new(0, 0, 960, 540)) .build(); let vo_chn0 = Arc::new(VoChn::new(0, &vo_chn0_attr, Arc::clone(&vo_vl0))); vo_chn0.show()?; let vo_chn1_attr = VoChnAttrBuilder::with_current(1, &vo_vl0) .with_priority(0) .with_disp_rect(Rect::new(960, 0, 960, 540)) .build(); let vo_chn1 = Arc::new(VoChn::new(1, &vo_chn1_attr, Arc::clone(&vo_vl0))); vo_chn1.show()?; let vo_chn2_attr = VoChnAttrBuilder::with_current(2, &vo_vl0) .with_priority(0) .with_disp_rect(Rect::new(0, 540, 960, 540)) .build(); let vo_chn2 = Arc::new(VoChn::new(2, &vo_chn2_attr, Arc::clone(&vo_vl0))); vo_chn2.show()?; let vo_chn3_attr = VoChnAttrBuilder::with_current(3, &vo_vl0) .with_priority(0) .with_disp_rect(Rect::new(960, 540, 960, 540)) .build(); let vo_chn3 = Arc::new(VoChn::new(3, &vo_chn3_attr, Arc::clone(&vo_vl0))); vo_chn3.show()?; let hdmi_core = Arc::new(HdmiCore::new()); let hdmi_port = HdmiPortBuilder::with_dvi_1080p60(HdmiId::Hdmi0, Arc::clone(&hdmi_core)).build(); hdmi_port.start().unwrap(); assert_eq!(Arc::strong_count(&hdmi_core), 2); let mut fb = hifb::FrameBuffer::new("/dev/fb0").unwrap(); assert_eq!( fb.set_pixel_format(hifb::PixelFormat::Argb8888).is_ok(), true ); assert_eq!(fb.set_resolution(1920, 1080).is_ok(), true); assert_eq!(fb.resolution(), (1920, 1080)); assert_eq!(fb.set_num_buffers(2).is_ok(), true); assert_eq!(fb.num_buffers(), 2); assert_eq!(fb.show().is_ok(), true); let mipi_rx = MipiReceiver::new(); assert!(mipi_rx.clear_all()); assert!(mipi_rx.set_hs_mode(LaneDivideMode::Mode7)); // 4+4+4+2+2 // AHD0 assert!(mipi_rx.enable_mipi_clock(0)); assert!(mipi_rx.reset_mipi(0)); // assert!(mipi_rx.enable_sensor_clock(0)); // assert!(mipi_rx.reset_sensor(0)); let mipi_attr = ComboDevAttrBuilder::new(0) .with_mipi() .with_size(vi_size.width, vi_size.height) .with_data_type(MipiDataType::Yuv4228Bit) .with_lanes([0, 1, 2, 3, -1, -1, -1, -1]) .build(); assert!(mipi_rx.set_dev_attr(&mipi_attr)); assert!(mipi_rx.unreset_mipi(0)); // assert!(mipi_rx.unreset_sensor(0)); // AHD4 assert!(mipi_rx.enable_mipi_clock(4)); assert!(mipi_rx.reset_mipi(4)); // assert!(mipi_rx.enable_sensor_clock(2)); // assert!(mipi_rx.reset_sensor(2)); let mipi_attr = ComboDevAttrBuilder::new(4) .with_mipi() .with_size(vi_size.width, vi_size.height) .with_data_type(MipiDataType::Yuv4228Bit) .with_lanes([8, 9, 10, 11, -1, -1, -1, -1]) .build(); assert!(mipi_rx.set_dev_attr(&mipi_attr)); assert!(mipi_rx.unreset_mipi(4)); // assert!(mipi_rx.unreset_sensor(2)); let vi_dev_attr = ViDevAttrBuilder::new() .with_mipi_yuv422() .with_multiplex(1) .with_component_mask([0xff000000, 0x00ff0000]) .with_progressive() .with_yuv() .with_yuv_uyvy() .with_size(vi_size) .with_bas_scale(vi_size) .with_bas_rephase(ViRephaseMode::None, ViRephaseMode::None) .with_wdr(WdrMode::None, vi_size.height) .build(); let vi_dev0 = Arc::new(ViDev::new(0, Some(&vi_dev_attr))); #[cfg(not(feature = "hi3559av100"))] vi_dev0.bind_mipi(0).unwrap(); vi_dev0.bind_pipes(&[0, 1, 2, 3]).unwrap(); let vi_dev4 = Arc::new(ViDev::new(4, Some(&vi_dev_attr))); #[cfg(not(feature = "hi3559av100"))] vi_dev4.bind_mipi(4).unwrap(); vi_dev4.bind_pipes(&[4, 5, 6, 7]).unwrap(); let vi_pipe_attr = ViPipeAttrBuilder::new_yuv422_3dnr_rfr() .with_max_size(vi_size) .build(); let vi_pipe0 = Arc::new(ViPipe::new(0, &vi_pipe_attr)); let vi_pipe1 = Arc::new(ViPipe::new(1, &vi_pipe_attr)); let vi_pipe2 = Arc::new(ViPipe::new(2, &vi_pipe_attr)); let vi_pipe3 = Arc::new(ViPipe::new(3, &vi_pipe_attr)); let vi_pipe4 = Arc::new(ViPipe::new(4, &vi_pipe_attr)); let vi_pipe5 = Arc::new(ViPipe::new(5, &vi_pipe_attr)); let vi_pipe6 = Arc::new(ViPipe::new(6, &vi_pipe_attr)); let vi_pipe7 = Arc::new(ViPipe::new(7, &vi_pipe_attr)); let vi_chn_attr = ViChnAttrBuilder::new_yuv422_sdr8_linear() .with_size(vi_size) .build(); let vi_chn0 = ViChn::new(0, Some(&vi_chn_attr), Arc::clone(&vi_pipe0)); let vi_chn1 = ViChn::new(0, Some(&vi_chn_attr), Arc::clone(&vi_pipe1)); let vi_chn2 = ViChn::new(0, Some(&vi_chn_attr), Arc::clone(&vi_pipe2)); let vi_chn3 = ViChn::new(0, Some(&vi_chn_attr), Arc::clone(&vi_pipe3)); let vi_chn4 = ViChn::new(0, Some(&vi_chn_attr), Arc::clone(&vi_pipe4)); let vi_chn5 = ViChn::new(0, Some(&vi_chn_attr), Arc::clone(&vi_pipe5)); let vi_chn6 = ViChn::new(0, Some(&vi_chn_attr), Arc::clone(&vi_pipe6)); let vi_chn7 = ViChn::new(0, Some(&vi_chn_attr), Arc::clone(&vi_pipe7)); // vi_pipe0.set_dump_attr(true, 3, ViDumpType::Yuv); vi_pipe0.set_vc_number(0).unwrap(); vi_pipe0.start().unwrap(); // vi_pipe1.set_dump_attr(true, 3, ViDumpType::Yuv); vi_pipe1.set_vc_number(1).unwrap(); vi_pipe1.start().unwrap(); // vi_pipe2.set_dump_attr(true, 3, ViDumpType::Yuv); vi_pipe2.set_vc_number(2).unwrap(); vi_pipe2.start().unwrap(); // vi_pipe3.set_dump_attr(true, 3, ViDumpType::Yuv); vi_pipe3.set_vc_number(3).unwrap(); vi_pipe3.start().unwrap(); // vi_pipe4.set_dump_attr(true, 3, ViDumpType::Yuv); vi_pipe4.set_vc_number(0).unwrap(); vi_pipe4.start().unwrap(); // vi_pipe5.set_dump_attr(true, 3, ViDumpType::Yuv); vi_pipe5.set_vc_number(1).unwrap(); vi_pipe5.start().unwrap(); // vi_pipe6.set_dump_attr(true, 3, ViDumpType::Yuv); vi_pipe6.set_vc_number(2).unwrap(); vi_pipe6.start().unwrap(); // vi_pipe7.set_dump_attr(true, 3, ViDumpType::Yuv); vi_pipe7.set_vc_number(3).unwrap(); vi_pipe7.start().unwrap(); let vpss_grp_attr = VpssGrpAttrBuilder::new().with_max_size(vi_size).build(); let vpss_grp0 = Arc::new(VpssGrp::new(0, &vpss_grp_attr)); let vpss_grp1 = Arc::new(VpssGrp::new(1, &vpss_grp_attr)); let vpss_grp2 = Arc::new(VpssGrp::new(2, &vpss_grp_attr)); let vpss_grp3 = Arc::new(VpssGrp::new(3, &vpss_grp_attr)); let vpss_grp4 = Arc::new(VpssGrp::new(4, &vpss_grp_attr)); let vpss_grp5 = Arc::new(VpssGrp::new(5, &vpss_grp_attr)); let vpss_grp6 = Arc::new(VpssGrp::new(6, &vpss_grp_attr)); let vpss_grp7 = Arc::new(VpssGrp::new(7, &vpss_grp_attr)); let vpss_crop = VpssCropInfo::with_abs(Rect::with_size(vi_size)); vpss_grp0.set_crop(&vpss_crop).unwrap(); vpss_grp1.set_crop(&vpss_crop).unwrap(); vpss_grp2.set_crop(&vpss_crop).unwrap(); vpss_grp3.set_crop(&vpss_crop).unwrap(); vpss_grp4.set_crop(&vpss_crop).unwrap(); vpss_grp5.set_crop(&vpss_crop).unwrap(); vpss_grp6.set_crop(&vpss_crop).unwrap(); vpss_grp7.set_crop(&vpss_crop).unwrap(); let vpss_chn_attr = VpssChnAttrBuilder::new() .with_mode(VpssChnMode::User) .with_size(vi_size) .build(); let vpss_chn0 = Arc::new(VpssChn::new(0, &vpss_chn_attr, Arc::clone(&vpss_grp0))); let vpss_chn1 = Arc::new(VpssChn::new(0, &vpss_chn_attr, Arc::clone(&vpss_grp1))); let vpss_chn2 = Arc::new(VpssChn::new(0, &vpss_chn_attr, Arc::clone(&vpss_grp2))); let vpss_chn3 = Arc::new(VpssChn::new(0, &vpss_chn_attr, Arc::clone(&vpss_grp3))); let vpss_chn4 = Arc::new(VpssChn::new(0, &vpss_chn_attr, Arc::clone(&vpss_grp4))); let vpss_chn5 = Arc::new(VpssChn::new(0, &vpss_chn_attr, Arc::clone(&vpss_grp5))); let vpss_chn6 = Arc::new(VpssChn::new(0, &vpss_chn_attr, Arc::clone(&vpss_grp6))); let vpss_chn7 = Arc::new(VpssChn::new(0, &vpss_chn_attr, Arc::clone(&vpss_grp7))); vpss_grp0.start().unwrap(); vpss_grp1.start().unwrap(); vpss_grp2.start().unwrap(); vpss_grp3.start().unwrap(); vpss_grp4.start().unwrap(); vpss_grp5.start().unwrap(); vpss_grp6.start().unwrap(); vpss_grp7.start().unwrap(); let _b10 = SysBinder::new(&vi_pipe0, &vpss_chn0); let _b11 = SysBinder::new(&vi_pipe1, &vpss_chn1); let _b12 = SysBinder::new(&vi_pipe4, &vpss_chn2); let _b13 = SysBinder::new(&vi_pipe5, &vpss_chn3); let _b20 = SysBinder::new(&vpss_chn0, &vo_chn0); let _b21 = SysBinder::new(&vpss_chn1, &vo_chn1); let _b22 = SysBinder::new(&vpss_chn2, &vo_chn2); let _b23 = SysBinder::new(&vpss_chn3, &vo_chn3); let mut poller = Poller::new()?; poller.add(0, Events::new().read(), None).unwrap(); poller .add( vpss_chn0.get_fd().unwrap(), Events::new().read(), Some(Arc::clone(&vpss_chn0) as EventContext), ) .unwrap(); poller .add( vpss_chn1.get_fd().unwrap(), Events::new().read(), Some(Arc::clone(&vpss_chn1) as EventContext), ) .unwrap(); poller .add( vpss_chn2.get_fd().unwrap(), Events::new().read(), Some(Arc::clone(&vpss_chn2) as EventContext), ) .unwrap(); poller .add( vpss_chn3.get_fd().unwrap(), Events::new().read(), Some(Arc::clone(&vpss_chn3) as EventContext), ) .unwrap(); println!("Press enter to exit ..."); 'outer: loop { let events = poller.pull_events(1000).unwrap(); for (_fd, _events, ctx) in events.iter() { match ctx { Some(v) => { if let Some(chn) = v.downcast_ref::() { let info = chn.get_frame(0).unwrap(); let vf = info.video_frame(); // let mut file = File::create("/tmp/foo.yuv").unwrap(); let planes = vf.plane_memories(); println!( "New Frame: chn={}, size={}, pts={}", chn, vf.size(), vf.pts() ); for a in 0..planes.len() { // file.write(planes[a].as_bytes()).unwrap(); } } } None => { if _fd == &0 { break 'outer; } } } } } // let vpc = Arc::clone(&vpss_chn0); // let th = std::thread::spawn(move || { // for a in 1..=300 { // match vpc.get_frame(1000) { // Ok(info) => { // let vf = info.video_frame(); // let mut file = File::create("/tmp/foo.yuv").unwrap(); // let planes = vf.plane_memories(); // println!("New Frame: size={}, pts={}", vf.size(), vf.pts()); // for a in 0..planes.len() { // file.write(planes[a].as_bytes()).unwrap(); // } // vpc.release_frame(&info).unwrap(); // } // Err(x) => println!("Fetch frame from VPSS failed: {:?}", x), // } // } // println!("Frame fetch thread exited!"); // }); // println!("Press enter to exit ..."); // let stdin = std::io::stdin(); // for b in stdin.lock().bytes() { // if b.unwrap() == 0x0A { // break; // } // } // th.join().unwrap(); Ok(()) }