#![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::{PixelFormat, Rect, Size, VideoInterface, VideoStandard, WdrMode}, mpi::vb::{VbConfigBuilder, VbManager, VbRemapMode}, mpi::venc::{VencChn, VencChnAttrBuilder, VencStreamPacks}, 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-venc") .version("1.0") .author("Varphone Wong ") .about("The example of pipeline: VI -> VPSS -> VENC") .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_conf = VbConfigBuilder::new() .pool(vb_pool1.into(), 3, VbRemapMode::None, "") .pool(vb_pool2.into(), 8, 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::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 mipi_rx = MipiReceiver::new(); assert!(mipi_rx.set_hs_mode(LaneDivideMode::Mode8)); // 4+4+4+2+2 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)); 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]).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_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)); // 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(); 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_crop = VpssCropInfo::with_abs(Rect::with_size(vi_size)); vpss_grp0.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(1, &vpss_chn_attr, Arc::clone(&vpss_grp0))); vpss_grp0.start().unwrap(); let venc_chn_attr = VencChnAttrBuilder::with_h265_720p(25).build(); let venc_chn0 = Arc::new(VencChn::new(0, &venc_chn_attr)); venc_chn0.start_recv_frame(-1)?; let _b1 = SysBinder::new(&vi_pipe0, &vpss_chn0); let _b2 = SysBinder::new(&vpss_chn0, &venc_chn0); 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( venc_chn0.get_fd().unwrap(), Events::new().read(), Some(Arc::clone(&venc_chn0) as EventContext), ) .unwrap(); println!("Press enter to exit ..."); let mut file = File::create("/tmp/example.265").unwrap(); let mut bytes_written: usize = 0; 'outer: loop { // Limit the dump file size to 20MB if bytes_written >= 1024 * 1024 * 20 { println!("The dump file size is exceed to 20MB, exit now!"); break 'outer; } let events = poller.pull_events(1000).unwrap(); for (_fd, _events, ctx) in events.iter() { match ctx { Some(ref 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(); } } else if let Some(chn) = v.downcast_ref::() { let (stream, packs) = chn.get_stream(0, None).unwrap(); println!("New Byte Stream: {:#?}, {:#?}", stream, packs); let sp = VencStreamPacks::new( Arc::clone(v).downcast::().unwrap(), stream, packs, ); for p in sp.packs() { bytes_written += file.write(&p.as_bytes()[p.offset()..])?; } //chn.release_stream(&stream).unwrap(); } } None => { if _fd == &0 { break 'outer; } } } } } Ok(()) }