diff --git a/xcoder/xcoder-quadra/.gitattributes b/xcoder/xcoder-quadra/.gitattributes new file mode 100644 index 00000000..bf94b1fd --- /dev/null +++ b/xcoder/xcoder-quadra/.gitattributes @@ -0,0 +1 @@ +src/testdata/8k-high-bitrate.h265 filter=lfs diff=lfs merge=lfs -text diff --git a/xcoder/xcoder-quadra/.gitignore b/xcoder/xcoder-quadra/.gitignore new file mode 100644 index 00000000..fe709903 --- /dev/null +++ b/xcoder/xcoder-quadra/.gitignore @@ -0,0 +1 @@ +out* diff --git a/xcoder/xcoder-quadra/Cargo.toml b/xcoder/xcoder-quadra/Cargo.toml index d08422cf..f13c312e 100644 --- a/xcoder/xcoder-quadra/Cargo.toml +++ b/xcoder/xcoder-quadra/Cargo.toml @@ -10,6 +10,7 @@ scopeguard = "1.1.0" [dev-dependencies] h264 = { path = "../../h264" } +h265 = { path = "../../h265" } snafu = { version = "0.7.0", features = ["std"] } [target.'cfg(target_os = "linux")'.dependencies] diff --git a/xcoder/xcoder-quadra/src/common.rs b/xcoder/xcoder-quadra/src/common.rs deleted file mode 100644 index 0d970b12..00000000 --- a/xcoder/xcoder-quadra/src/common.rs +++ /dev/null @@ -1,35 +0,0 @@ -use snafu::Snafu; -use xcoder_quadra_sys as sys; - -#[derive(Debug, Snafu)] -pub enum XcoderInitError { - #[snafu(display("error (code = {code})"))] - Unknown { code: sys::ni_retcode_t }, -} - -#[derive(Debug, Clone)] -pub struct XcoderHardware { - pub id: i32, - pub device_handle: i32, -} - -#[cfg(target_os = "linux")] -pub fn init(should_match_rev: bool, timeout_seconds: u32) -> Result<(), XcoderInitError> { - let code = unsafe { sys::ni_rsrc_init(if should_match_rev { 1 } else { 0 }, timeout_seconds as _) }; - if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { - return Err(XcoderInitError::Unknown { code }); - } - Ok(()) -} - -pub(crate) fn fps_to_rational(fps: f64) -> (i32, i32) { - let den = if fps.fract() == 0.0 { - 1000 - } else { - // a denominator of 1001 for 29.97 or 59.94 is more - // conventional - 1001 - }; - let num = (fps * den as f64).round() as _; - (den, num) -} diff --git a/xcoder/xcoder-quadra/src/cropper.rs b/xcoder/xcoder-quadra/src/cropper.rs new file mode 100644 index 00000000..b87a9cb8 --- /dev/null +++ b/xcoder/xcoder-quadra/src/cropper.rs @@ -0,0 +1,220 @@ +use super::{XcoderHardware, XcoderHardwareFrame}; +use scopeguard::{guard, ScopeGuard}; +use snafu::Snafu; +use std::mem; +use xcoder_quadra_sys as sys; + +#[derive(Clone, Debug)] +pub struct XcoderCropperConfig { + pub hardware: XcoderHardware, +} + +#[derive(Debug, Snafu)] +pub enum XcoderCropperError { + #[snafu(display("unable to allocate device session context"))] + UnableToAllocateDeviceSessionContext, + #[snafu(display("error {operation} (code = {code})"))] + Unknown { code: sys::ni_retcode_t, operation: &'static str }, +} + +type Result = std::result::Result; + +pub struct XcoderCropper { + session: *mut sys::ni_session_context_t, + did_initialize: bool, +} + +#[derive(Clone, Debug)] +pub struct XcoderCrop { + pub x: i32, + pub y: i32, + pub width: i32, + pub height: i32, +} + +impl XcoderCropper { + pub fn new(config: XcoderCropperConfig) -> Result { + unsafe { + let session = sys::ni_device_session_context_alloc_init(); + if session.is_null() { + return Err(XcoderCropperError::UnableToAllocateDeviceSessionContext); + } + let mut session = guard(session, |session| { + sys::ni_device_session_context_free(session); + }); + + (**session).hw_id = config.hardware.id; + (**session).sender_handle = config.hardware.device_handle; + (**session).device_type = sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER as _; + (**session).scaler_operation = sys::_ni_scaler_opcode_NI_SCALER_OPCODE_CROP; + + let code = sys::ni_device_session_open(*session, sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderCropperError::Unknown { + code, + operation: "opening device session", + }); + } + + Ok(Self { + session: ScopeGuard::into_inner(session), + did_initialize: false, + }) + } + } + + pub fn crop(&mut self, f: &XcoderHardwareFrame, crop: XcoderCrop) -> Result { + const PIXEL_FORMAT: i32 = sys::GC620_I420_; + unsafe { + let frame_in = **f; + let mut frame_out: sys::ni_frame_t = mem::zeroed(); + let code = sys::ni_frame_buffer_alloc_hwenc(&mut frame_out as _, crop.width, crop.height, 0); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderCropperError::Unknown { + code, + operation: "allocating frame", + }); + } + let data_io_out = sys::ni_session_data_io_t { + data: sys::_ni_session_data_io__bindgen_ty_1 { frame: frame_out }, + }; + let mut data_io_out = guard(data_io_out, |mut data_io| { + sys::ni_frame_buffer_free(&mut data_io.data.frame); + }); + + if !self.did_initialize { + // Allocate the output frame pool. + let code = sys::ni_device_alloc_frame( + self.session, + frame_in.video_width as _, + frame_in.video_height as _, + PIXEL_FORMAT, + (sys::NI_SCALER_FLAG_IO | sys::NI_SCALER_FLAG_PC) as _, + 0, + 0, + 0, + 0, + 1, // pool size + 0, + sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER, + ); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderCropperError::Unknown { + code, + operation: "allocating cropper output frame pool", + }); + } + + self.did_initialize = true; + } + + // Allocate the input frame. + let code = sys::ni_device_alloc_frame( + self.session, + frame_in.video_width as _, + frame_in.video_height as _, + PIXEL_FORMAT, + 0, + crop.width, + crop.height, + crop.x, + crop.y, + f.surface().ui32nodeAddress as _, + f.surface().ui16FrameIdx as _, + sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER, + ); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderCropperError::Unknown { + code, + operation: "allocating cropper input frame", + }); + } + + // Allocate the output frame. + let code = sys::ni_device_alloc_frame( + self.session, + crop.width as _, + crop.height as _, + PIXEL_FORMAT, + sys::NI_SCALER_FLAG_IO as _, + 0, + 0, + 0, + 0, + 0, + -1, + sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER, + ); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderCropperError::Unknown { + code, + operation: "allocating cropper output frame", + }); + } + + let code = sys::ni_device_session_read_hwdesc(self.session, &mut *data_io_out, sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderCropperError::Unknown { + code, + operation: "reading cropper frame", + }); + } + + Ok(XcoderHardwareFrame::new(ScopeGuard::into_inner(data_io_out))) + } + } +} + +impl Drop for XcoderCropper { + fn drop(&mut self) { + unsafe { + sys::ni_device_session_close(self.session, 1, sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER); + sys::ni_device_close((*self.session).device_handle); + sys::ni_device_close((*self.session).blk_io_handle); + sys::ni_device_session_context_free(self.session); + } + } +} + +#[cfg(test)] +mod test { + use super::{ + super::{decoder::test::read_frames, *}, + *, + }; + + #[test] + fn test_cropper() { + let frames = read_frames("src/testdata/smptebars.h264"); + + let mut decoder = XcoderDecoder::new( + XcoderDecoderConfig { + width: 1280, + height: 720, + codec: XcoderDecoderCodec::H264, + bit_depth: 8, + fps: 29.97, + }, + frames, + ) + .unwrap(); + + let mut cropper = XcoderCropper::new(XcoderCropperConfig { hardware: decoder.hardware() }).unwrap(); + + let mut frame_count = 0; + while let Some(frame) = decoder.read_decoded_frame().unwrap() { + cropper + .crop( + &frame.into(), + XcoderCrop { + x: 0, + y: 0, + width: 1280 - frame_count, + height: 720 - frame_count, + }, + ) + .unwrap(); + frame_count += 1; + } + } +} diff --git a/xcoder/xcoder-quadra/src/decoder.rs b/xcoder/xcoder-quadra/src/decoder.rs index ef06f39d..a763ea92 100644 --- a/xcoder/xcoder-quadra/src/decoder.rs +++ b/xcoder/xcoder-quadra/src/decoder.rs @@ -1,4 +1,4 @@ -use super::{fps_to_rational, XcoderHardware}; +use super::{fps_to_rational, XcoderHardware, XcoderHardwareFrame}; use scopeguard::{guard, ScopeGuard}; use snafu::{Error, Snafu}; use std::{marker::PhantomData, mem, ops::Deref}; @@ -69,7 +69,7 @@ impl XcoderDecoderInputFrame { } pub struct XcoderDecodedFrame { - data_io: sys::ni_session_data_io_t, + data_io: Option, } impl XcoderDecodedFrame { @@ -96,14 +96,20 @@ impl XcoderDecodedFrame { }); } Ok(Self { - data_io: sys::ni_session_data_io_t { + data_io: Some(sys::ni_session_data_io_t { data: sys::_ni_session_data_io__bindgen_ty_1 { frame }, - }, + }), }) } pub fn as_data_io_mut_ptr(&mut self) -> *mut sys::ni_session_data_io_t { - &mut self.data_io as _ + self.data_io.as_mut().expect("data_io should be some until we're dropped or consumed") as _ + } +} + +impl From for XcoderHardwareFrame { + fn from(mut frame: XcoderDecodedFrame) -> Self { + unsafe { Self::new(frame.data_io.take().expect("data_io should be some until we're dropped or consumed")) } } } @@ -114,15 +120,27 @@ impl Deref for XcoderDecodedFrame { type Target = sys::ni_frame_t; fn deref(&self) -> &Self::Target { - unsafe { &self.data_io.data.frame } + unsafe { + &self + .data_io + .as_ref() + .expect("data_io should be some until we're dropped or consumed") + .data + .frame + } } } impl Drop for XcoderDecodedFrame { fn drop(&mut self) { - unsafe { - sys::ni_hwframe_p2p_buffer_recycle(&mut self.data_io.data.frame as _); - sys::ni_frame_buffer_free(&mut self.data_io.data.frame as _); + if let Some(mut data_io) = self.data_io.take() { + unsafe { + let index = (*(data_io.data.frame.p_data[3] as *const sys::niFrameSurface1_t)).ui16FrameIdx; + if index > 0 { + sys::ni_hwframe_p2p_buffer_recycle(&mut data_io.data.frame as _); + } + sys::ni_frame_buffer_free(&mut data_io.data.frame as _); + } } } } @@ -182,7 +200,7 @@ impl> XcoderDecoder { where II: IntoIterator, { - let (fps_denominator, fps_numerator) = fps_to_rational(config.fps); + let (fps_numerator, fps_denominator) = fps_to_rational(config.fps); unsafe { let mut params: sys::ni_xcoder_params_t = mem::zeroed(); @@ -257,8 +275,18 @@ impl> XcoderDecoder { self.eos_received } + /// Reads a decoded frame. Returns None once the decoder is finished. + pub fn read_decoded_frame(&mut self) -> Result, XcoderDecoderError> { + while !self.is_finished() { + if let Some(frame) = self.try_read_decoded_frame()? { + return Ok(Some(frame)); + } + } + Ok(None) + } + /// Tries to read a decoded frame. If none is returned and `is_finished` returns false, the caller should try again later. - pub fn try_read_decoded_frame(&mut self) -> Result, XcoderDecoderError> { + fn try_read_decoded_frame(&mut self) -> Result, XcoderDecoderError> { if self.is_finished() { return Ok(None); } @@ -343,12 +371,12 @@ impl Drop for XcoderDecoder { } #[cfg(test)] -mod test { +pub mod test { use super::{super::*, *}; use std::io::{self, Read}; - /// Reads frames from a raw .h264 file. - fn read_frames(path: &str) -> Vec> { + /// Reads frames from a raw .h264 or .h265 file. + pub fn read_frames(path: &str) -> Vec> { let mut f = std::fs::File::open(path).unwrap(); let mut buf = Vec::new(); f.read_to_end(&mut buf).unwrap(); @@ -357,17 +385,34 @@ mod test { let mut ret = vec![]; let mut buffer = vec![]; + let mut h264_counter = h264::AccessUnitCounter::new(); + let mut h265_counter = h265::AccessUnitCounter::new(); for nalu in nalus { - buffer.extend_from_slice(&[0, 0, 0, 1]); - buffer.extend_from_slice(nalu); - let nalu_type = nalu[0] & h264::NAL_UNIT_TYPE_MASK; - if nalu_type == 5 || nalu_type == 1 { + let is_new_frame = if path.contains(".h264") { + let before = h264_counter.count(); + h264_counter.count_nalu(nalu).unwrap(); + h264_counter.count() != before + } else { + let before = h265_counter.count(); + h265_counter.count_nalu(nalu).unwrap(); + h265_counter.count() != before + }; + if is_new_frame && !buffer.is_empty() { ret.push(Ok(XcoderDecoderInputFrame { data: mem::take(&mut buffer), pts: ret.len() as _, dts: ret.len() as _, })); } + buffer.extend_from_slice(&[0, 0, 0, 1]); + buffer.extend_from_slice(nalu); + } + if !buffer.is_empty() { + ret.push(Ok(XcoderDecoderInputFrame { + data: mem::take(&mut buffer), + pts: ret.len() as _, + dts: ret.len() as _, + })); } ret } @@ -389,10 +434,8 @@ mod test { .unwrap(); let mut frame_count = 0; - while !decoder.is_finished() { - if decoder.try_read_decoded_frame().unwrap().is_some() { - frame_count += 1; - } + while decoder.read_decoded_frame().unwrap().is_some() { + frame_count += 1; } assert_eq!(frame_count, expected_frame_count); } @@ -427,12 +470,10 @@ mod test { let mut encoded_frames = 0; let mut encoded = vec![]; - while !decoder.is_finished() { - if let Some(mut frame) = decoder.try_read_decoded_frame().unwrap() { - if let Some(mut output) = unsafe { encoder.encode_data_io((), frame.as_data_io_mut_ptr()).unwrap() } { - encoded.append(&mut output.encoded_frame.data); - encoded_frames += 1; - } + while let Some(frame) = decoder.read_decoded_frame().unwrap() { + if let Some(mut output) = encoder.encode_hardware_frame((), frame.into()).unwrap() { + encoded.append(&mut output.encoded_frame.data); + encoded_frames += 1; } } while let Some(mut output) = encoder.flush().unwrap() { diff --git a/xcoder/xcoder-quadra/src/encoder.rs b/xcoder/xcoder-quadra/src/encoder.rs index e8f07faf..e585dcd6 100644 --- a/xcoder/xcoder-quadra/src/encoder.rs +++ b/xcoder/xcoder-quadra/src/encoder.rs @@ -1,4 +1,4 @@ -use super::{fps_to_rational, XcoderHardware}; +use super::{fps_to_rational, XcoderHardware, XcoderHardwareFrame}; use av_traits::{EncodedFrameType, EncodedVideoFrame, RawVideoFrame, VideoEncoder, VideoEncoderOutput}; use scopeguard::{guard, ScopeGuard}; use snafu::Snafu; @@ -88,6 +88,9 @@ pub struct XcoderEncoder { frame_data_heights: [i32; sys::NI_MAX_NUM_DATA_POINTERS as usize], input_frames: VecDeque, output_frames: VecDeque>, + + // We have to keep hardware frames alive until the encoder says we can recycle them. + hardware_frames: Vec>, } #[derive(Clone, Debug)] @@ -110,7 +113,7 @@ pub struct XcoderEncoderConfig { impl XcoderEncoder { pub fn new(config: XcoderEncoderConfig) -> Result { - let (fps_denominator, fps_numerator) = fps_to_rational(config.fps); + let (fps_numerator, fps_denominator) = fps_to_rational(config.fps); unsafe { let mut params: sys::ni_xcoder_params_t = mem::zeroed(); @@ -238,6 +241,12 @@ impl XcoderEncoder { frames_copied: 0, input_frames: VecDeque::new(), output_frames: VecDeque::new(), + hardware_frames: { + let size = 1 + sys::NI_MAX_DR_HWDESC_FRAME_INDEX.max(sys::NI_MAX_SR_HWDESC_FRAME_INDEX) as usize; + let mut frames = Vec::with_capacity(size); + frames.resize_with(size, || None); + frames + }, }) } } @@ -256,6 +265,9 @@ impl XcoderEncoder { let packet = self.encoded_frame.packet(); self.did_finish = packet.end_of_stream != 0; if code > 0 { + if packet.recycle_index > 0 && (packet.recycle_index as usize) < self.hardware_frames.len() { + self.hardware_frames[packet.recycle_index as usize] = None; + } if packet.pts == 0 && packet.avg_frame_qp == 0 { self.encoded_frame.parameter_sets = Some(self.encoded_frame.as_slice().to_vec()); } else { @@ -304,14 +316,8 @@ impl XcoderEncoder { } } - /// Can be used to encode using a native NETINT data IO pointer (e.g. to encode using a hardware handle). - /// - /// # Safety - /// - /// `data_io` must be a valid data_io pointer for a hardware frame on the device the encoder - /// was configured for. - pub unsafe fn encode_data_io(&mut self, mut input: F, data_io: *mut sys::ni_session_data_io_t) -> Result>> { - let mut frame = &mut (*data_io).data.frame; + pub fn encode_hardware_frame(&mut self, mut input: F, mut hw_frame: XcoderHardwareFrame) -> Result>> { + let mut frame = *hw_frame; frame.start_of_stream = if self.did_start { 0 } else { 1 }; frame.extra_data_len = sys::NI_APP_ENC_FRAME_META_DATA_SIZE as _; frame.force_key_frame = 0; @@ -319,9 +325,13 @@ impl XcoderEncoder { loop { self.try_reading_encoded_frames()?; - match self.try_write_frame_data_io(input, data_io)? { + match unsafe { self.try_write_frame_data_io(input, hw_frame.as_data_io_mut_ptr())? } { Some(frame) => input = frame, - None => break, + None => { + let idx = hw_frame.surface().ui16FrameIdx as usize; + self.hardware_frames[idx] = Some(hw_frame); + break; + } } } Ok(self.output_frames.pop_front()) diff --git a/xcoder/xcoder-quadra/src/lib.rs b/xcoder/xcoder-quadra/src/lib.rs index c0284e13..b32aae54 100644 --- a/xcoder/xcoder-quadra/src/lib.rs +++ b/xcoder/xcoder-quadra/src/lib.rs @@ -1,17 +1,270 @@ #[cfg(target_os = "linux")] -mod common; +#[path = ""] +mod linux_impl { + use snafu::Snafu; + use std::ops::Deref; + use xcoder_quadra_sys as sys; -#[cfg(target_os = "linux")] -mod decoder; + pub mod cropper; + pub mod decoder; + pub mod encoder; + pub mod scaler; -#[cfg(target_os = "linux")] -mod encoder; + pub use cropper::*; + pub use decoder::*; + pub use encoder::*; + pub use scaler::*; -#[cfg(target_os = "linux")] -pub use common::*; + #[derive(Debug, Snafu)] + pub enum XcoderInitError { + #[snafu(display("error (code = {code})"))] + Unknown { code: sys::ni_retcode_t }, + } -#[cfg(target_os = "linux")] -pub use decoder::*; + #[derive(Debug, Clone)] + pub struct XcoderHardware { + pub id: i32, + pub device_handle: i32, + } + + pub struct XcoderHardwareFrame { + data_io: sys::ni_session_data_io_t, + } + + impl XcoderHardwareFrame { + pub(crate) unsafe fn new(data_io: sys::ni_session_data_io_t) -> Self { + Self { data_io } + } + + pub fn as_data_io_mut_ptr(&mut self) -> *mut sys::ni_session_data_io_t { + &mut self.data_io as _ + } + + pub fn surface(&self) -> &sys::niFrameSurface1_t { + unsafe { &*((*self).p_data[3] as *const sys::niFrameSurface1_t) } + } + } + + unsafe impl Send for XcoderHardwareFrame {} + unsafe impl Sync for XcoderHardwareFrame {} + + impl Deref for XcoderHardwareFrame { + type Target = sys::ni_frame_t; + + fn deref(&self) -> &Self::Target { + unsafe { &self.data_io.data.frame } + } + } + + impl Drop for XcoderHardwareFrame { + fn drop(&mut self) { + unsafe { + if self.surface().ui16FrameIdx > 0 { + sys::ni_hwframe_p2p_buffer_recycle(&mut self.data_io.data.frame as _); + } + sys::ni_frame_buffer_free(&mut self.data_io.data.frame as _); + } + } + } + + pub fn init(should_match_rev: bool, timeout_seconds: u32) -> Result<(), XcoderInitError> { + let code = unsafe { sys::ni_rsrc_init(if should_match_rev { 1 } else { 0 }, timeout_seconds as _) }; + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderInitError::Unknown { code }); + } + Ok(()) + } + + pub(crate) fn fps_to_rational(fps: f64) -> (i32, i32) { + let den = if fps.fract() == 0.0 { + 1000 + } else { + // a denominator of 1001 for 29.97 or 59.94 is more + // conventional + 1001 + }; + let num = (fps * den as f64).round() as _; + (num, den) + } +} #[cfg(target_os = "linux")] -pub use encoder::*; +pub use linux_impl::*; + +#[cfg(all(test, target_os = "linux"))] +mod test { + use super::{decoder::test::read_frames, *}; + + #[test] + fn test_fps_to_rational() { + assert_eq!(fps_to_rational(29.97), (30000, 1001)); + assert_eq!(fps_to_rational(30.0), (30000, 1000)); + assert_eq!(fps_to_rational(59.94), (60000, 1001)); + assert_eq!(fps_to_rational(60.0), (60000, 1000)); + } + + #[test] + fn test_transcoding() { + let frames = read_frames("src/testdata/smptebars.h264"); + let expected_frame_count = frames.len(); + + let mut decoder = XcoderDecoder::new( + XcoderDecoderConfig { + width: 1280, + height: 720, + codec: XcoderDecoderCodec::H264, + bit_depth: 8, + fps: 29.97, + }, + frames, + ) + .unwrap(); + + let mut cropper = XcoderCropper::new(XcoderCropperConfig { hardware: decoder.hardware() }).unwrap(); + let mut scaler = XcoderScaler::new(XcoderScalerConfig { + hardware: decoder.hardware(), + width: 640, + height: 360, + }) + .unwrap(); + + let mut encoder = XcoderEncoder::new(XcoderEncoderConfig { + width: 640, + height: 360, + fps: 29.97, + bitrate: None, + codec: XcoderEncoderCodec::H264, + hardware: Some(decoder.hardware()), + }) + .unwrap(); + + let mut encoded_frames = 0; + let mut encoded = vec![]; + + while let Some(frame) = decoder.read_decoded_frame().unwrap() { + let frame = cropper + .crop( + &frame.into(), + XcoderCrop { + x: 0, + y: 0, + width: 960, + height: 540, + }, + ) + .unwrap(); + let frame = scaler.scale(&frame).unwrap(); + if let Some(mut output) = encoder.encode_hardware_frame((), frame).unwrap() { + encoded.append(&mut output.encoded_frame.data); + encoded_frames += 1; + } + } + while let Some(mut output) = encoder.flush().unwrap() { + encoded.append(&mut output.encoded_frame.data); + encoded_frames += 1; + } + + assert_eq!(encoded_frames, expected_frame_count); + assert!(encoded.len() > 5000); + + // If you want to inspect the output, uncomment these lines: + //use std::io::Write; + //std::fs::File::create("out.h264").unwrap().write_all(&encoded).unwrap() + } + + #[test] + fn test_8k_ladder() { + let frames = read_frames("src/testdata/8k-high-bitrate.h265"); + + let mut decoder = XcoderDecoder::new( + XcoderDecoderConfig { + width: 7680, + height: 4320, + codec: XcoderDecoderCodec::H265, + bit_depth: 8, + fps: 24.0, + }, + frames, + ) + .unwrap(); + + struct Encoding { + cropper: XcoderCropper, + scaler: XcoderScaler, + encoder: XcoderEncoder<()>, + output: Vec, + } + + const OUTPUTS: usize = 10; + + let mut encodings = vec![]; + encodings.resize_with(OUTPUTS, || { + let cropper = XcoderCropper::new(XcoderCropperConfig { hardware: decoder.hardware() }).unwrap(); + + let scaler = XcoderScaler::new(XcoderScalerConfig { + hardware: decoder.hardware(), + width: 640, + height: 360, + }) + .unwrap(); + + let encoder = XcoderEncoder::new(XcoderEncoderConfig { + width: 640, + height: 360, + fps: 24.0, + bitrate: None, + codec: XcoderEncoderCodec::H264, + hardware: Some(decoder.hardware()), + }) + .unwrap(); + + Encoding { + cropper, + scaler, + encoder, + output: vec![], + } + }); + + let mut frame_number = 0; + while let Some(frame) = decoder.read_decoded_frame().unwrap() { + let frame = frame.into(); + for enc in encodings.iter_mut() { + let frame = enc + .cropper + .crop( + &frame, + XcoderCrop { + x: frame_number * 16, + y: frame_number * 16, + width: (1920.0 + 20.0 * frame_number as f64) as _, + height: (1080.0 + 20.0 * frame_number as f64) as _, + }, + ) + .unwrap(); + let frame = enc.scaler.scale(&frame).unwrap(); + if let Some(mut output) = enc.encoder.encode_hardware_frame((), frame).unwrap() { + enc.output.append(&mut output.encoded_frame.data); + } + } + frame_number += 1; + } + for enc in encodings.iter_mut() { + while let Some(mut output) = enc.encoder.flush().unwrap() { + enc.output.append(&mut output.encoded_frame.data); + } + assert!(!enc.output.is_empty()); + } + + // If you want to inspect the output, uncomment these lines: + /* + for i in 0..OUTPUTS { + use std::io::Write; + std::fs::File::create(format!("out{:02}.h264", i)) + .unwrap() + .write_all(&encodings[i].output) + .unwrap() + } + */ + } +} diff --git a/xcoder/xcoder-quadra/src/scaler.rs b/xcoder/xcoder-quadra/src/scaler.rs new file mode 100644 index 00000000..d5e84041 --- /dev/null +++ b/xcoder/xcoder-quadra/src/scaler.rs @@ -0,0 +1,211 @@ +use super::{XcoderHardware, XcoderHardwareFrame}; +use scopeguard::{guard, ScopeGuard}; +use snafu::Snafu; +use std::mem; +use xcoder_quadra_sys as sys; + +#[derive(Clone, Debug)] +pub struct XcoderScalerConfig { + pub hardware: XcoderHardware, + pub width: i32, + pub height: i32, +} + +#[derive(Debug, Snafu)] +pub enum XcoderScalerError { + #[snafu(display("unable to allocate device session context"))] + UnableToAllocateDeviceSessionContext, + #[snafu(display("error {operation} (code = {code})"))] + Unknown { code: sys::ni_retcode_t, operation: &'static str }, +} + +type Result = std::result::Result; + +pub struct XcoderScaler { + session: *mut sys::ni_session_context_t, + did_initialize: bool, + config: XcoderScalerConfig, +} + +impl XcoderScaler { + pub fn new(config: XcoderScalerConfig) -> Result { + unsafe { + let session = sys::ni_device_session_context_alloc_init(); + if session.is_null() { + return Err(XcoderScalerError::UnableToAllocateDeviceSessionContext); + } + let mut session = guard(session, |session| { + sys::ni_device_session_context_free(session); + }); + + (**session).hw_id = config.hardware.id; + (**session).sender_handle = config.hardware.device_handle; + (**session).device_type = sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER as _; + (**session).scaler_operation = sys::_ni_scaler_opcode_NI_SCALER_OPCODE_SCALE; + + let code = sys::ni_device_session_open(*session, sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderScalerError::Unknown { + code, + operation: "opening device session", + }); + } + + Ok(Self { + session: ScopeGuard::into_inner(session), + did_initialize: false, + config, + }) + } + } + + pub fn scale(&mut self, f: &XcoderHardwareFrame) -> Result { + const PIXEL_FORMAT: i32 = sys::GC620_I420_; + unsafe { + let frame_in = **f; + let mut frame_out: sys::ni_frame_t = mem::zeroed(); + frame_out.pts = frame_in.pts; + + let code = sys::ni_frame_buffer_alloc_hwenc(&mut frame_out as _, self.config.width, self.config.height, 0); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderScalerError::Unknown { + code, + operation: "allocating frame", + }); + } + let data_io_out = sys::ni_session_data_io_t { + data: sys::_ni_session_data_io__bindgen_ty_1 { frame: frame_out }, + }; + let mut data_io_out = guard(data_io_out, |mut data_io| { + sys::ni_frame_buffer_free(&mut data_io.data.frame); + }); + + if !self.did_initialize { + // Allocate the output frame pool. + let code = sys::ni_device_alloc_frame( + self.session, + self.config.width as _, + self.config.height as _, + PIXEL_FORMAT, + (sys::NI_SCALER_FLAG_IO | sys::NI_SCALER_FLAG_PC) as _, + 0, + 0, + 0, + 0, + 1, // pool size + 0, + sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER, + ); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderScalerError::Unknown { + code, + operation: "allocating scaler output frame pool", + }); + } + + self.did_initialize = true; + } + + // Allocate the input frame. + let code = sys::ni_device_alloc_frame( + self.session, + frame_in.video_width as _, + frame_in.video_height as _, + PIXEL_FORMAT, + 0, + 0, + 0, + 0, + 0, + f.surface().ui32nodeAddress as _, + f.surface().ui16FrameIdx as _, + sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER, + ); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderScalerError::Unknown { + code, + operation: "allocating scaler input frame", + }); + } + + // Allocate the output frame. + let code = sys::ni_device_alloc_frame( + self.session, + self.config.width as _, + self.config.height as _, + PIXEL_FORMAT, + sys::NI_SCALER_FLAG_IO as _, + 0, + 0, + 0, + 0, + 0, + -1, + sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER, + ); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderScalerError::Unknown { + code, + operation: "allocating scaler output frame", + }); + } + + let code = sys::ni_device_session_read_hwdesc(self.session, &mut *data_io_out, sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER); + if code != sys::ni_retcode_t_NI_RETCODE_SUCCESS { + return Err(XcoderScalerError::Unknown { + code, + operation: "reading scaler frame", + }); + } + + Ok(XcoderHardwareFrame::new(ScopeGuard::into_inner(data_io_out))) + } + } +} + +impl Drop for XcoderScaler { + fn drop(&mut self) { + unsafe { + sys::ni_device_session_close(self.session, 1, sys::ni_device_type_t_NI_DEVICE_TYPE_SCALER); + sys::ni_device_close((*self.session).device_handle); + sys::ni_device_close((*self.session).blk_io_handle); + sys::ni_device_session_context_free(self.session); + } + } +} + +#[cfg(test)] +mod test { + use super::{ + super::{decoder::test::read_frames, *}, + *, + }; + + #[test] + fn test_scaler() { + let frames = read_frames("src/testdata/smptebars.h264"); + + let mut decoder = XcoderDecoder::new( + XcoderDecoderConfig { + width: 1280, + height: 720, + codec: XcoderDecoderCodec::H264, + bit_depth: 8, + fps: 29.97, + }, + frames, + ) + .unwrap(); + + let mut scaler = XcoderScaler::new(XcoderScalerConfig { + hardware: decoder.hardware(), + width: 640, + height: 360, + }) + .unwrap(); + + while let Some(frame) = decoder.read_decoded_frame().unwrap() { + scaler.scale(&frame.into()).unwrap(); + } + } +} diff --git a/xcoder/xcoder-quadra/src/testdata/8k-high-bitrate.h265 b/xcoder/xcoder-quadra/src/testdata/8k-high-bitrate.h265 new file mode 100644 index 00000000..daf742ac --- /dev/null +++ b/xcoder/xcoder-quadra/src/testdata/8k-high-bitrate.h265 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6999a50023224f7764f004b0d5fe9b2d97f550f94dda4a541262882cfdeb878 +size 93891783 diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/build.rs b/xcoder/xcoder-quadra/xcoder-quadra-sys/build.rs index 4ce2e93b..96bf366c 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/build.rs +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/build.rs @@ -68,6 +68,7 @@ fn main() { .whitelist_function("ni_.+") .whitelist_type("ni_.+") .whitelist_var("NI_.+") + .whitelist_var("GC620_.+") // bindgen 0.60.0 broke layout tests: https://github.com/rust-lang/rust-bindgen/issues/2218 // 0.60.1 claims to have fixed the issue, but does not. .layout_tests(false) diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/src/lib.hpp b/xcoder/xcoder-quadra/xcoder-quadra-sys/src/lib.hpp index fdb8ae9e..d9f60264 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/src/lib.hpp +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/src/lib.hpp @@ -1,3 +1,5 @@ #include #include #include + +const int GC620_I420_ = GC620_I420; diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/src/lib.rs b/xcoder/xcoder-quadra/xcoder-quadra-sys/src/lib.rs index e00b53a6..d5681471 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/src/lib.rs +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/src/lib.rs @@ -11,15 +11,3 @@ #[cfg(target_os = "linux")] include!(concat!(env!("OUT_DIR"), "/bindings.rs")); - -#[cfg(all(test, target_os = "linux"))] -mod tests { - use super::*; - - #[test] - fn it_works() { - unsafe { - ni_rsrc_print_all_devices_capability(); - } - } -} diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/auto/auto_headers.sh b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/auto/auto_headers.sh index f1e5fd1b..cd144c63 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/auto/auto_headers.sh +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/auto/auto_headers.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # output variables: # XCODER_AUTO_HEADERS_H: the auto generated header file. diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/auto/options.sh b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/auto/options.sh index cfe94ccf..bbeac199 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/auto/options.sh +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/auto/options.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # variables, parent script must set it: @@ -57,6 +57,8 @@ Options: --with-latency-display enable latency-display feature --without-latency-display disable latency-display feature (default) + --prefix Set custom install location preix + (default: /usr/local/) --libdir Set custom install location for libxcoder.so and pkgconfig files (default: /usr/local/lib/) --bindir Set custom install location for binary utilities (ni_rsrc_mon, etc.) @@ -112,6 +114,11 @@ function parse_user_option() { --without-tracelog-timestamps) XCODER_TRACELOG_TIMESTAMPS=NO;; --with-data-dump) XCODER_DUMP_DATA=YES;; --without-data-dump) XCODER_DUMP_DATA=NO;; + --prefix*) extract_arg "\-\-prefix" $1 $2; eprc=$?; + if [ "$eprc" -eq 1 ]; then + shift; + fi + XCODER_PREFIX=$extract_arg_ret;; --libdir*) extract_arg "\-\-libdir" $1 $2; eprc=$?; if [ "$eprc" -eq 1 ]; then shift; diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/Android.bp b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/Android.bp index 852b77ae..e517e8fd 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/Android.bp +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/Android.bp @@ -3,6 +3,7 @@ cc_library_shared { name: "libxcoder", srcs: [ + "ni_lat_meas.c", "ni_log.c", "ni_nvme.c", "ni_device_api_priv.c", @@ -43,7 +44,6 @@ cc_library_shared { "-Wno-macro-redefined", ] + [ "-D_ANDROID", - "-DXCODER_IO_RW_ENABLED", "-D_FILE_OFFSET_BITS=64", ], @@ -105,7 +105,6 @@ cc_binary { "-Wno-unused-variable", ] + [ "-D_ANDROID", - "-DXCODER_IO_RW_ENABLED", "-pie", "-fPIE", ], @@ -150,7 +149,6 @@ cc_binary { "-Wno-sometimes-uninitialized", ] + [ "-D_ANDROID", - "-DXCODER_IO_RW_ENABLED", "-D_FILE_OFFSET_BITS=64", ], @@ -169,3 +167,46 @@ cc_binary { } //############################################################################### + +cc_binary { + proprietary: true, + srcs: ["ni_rsrc_list.c"], + + local_include_dirs: [""], + + cflags: [ + "-Werror", + "-Wno-missing-field-initializers", + "-Wno-missing-braces", + "-Wno-sign-compare", + "-Wno-return-type", + "-Wno-pointer-arith", + "-Wno-pointer-sign", + "-Wno-enum-conversion", + "-Wno-unused-parameter", + "-Wno-pointer-bool-conversion", + "-Wno-tautological-pointer-compare", + "-Wno-parentheses", + "-Wno-tautological-compare", + "-Wno-absolute-value", + "-Wno-sometimes-uninitialized", + ] + [ + "-D_ANDROID", + "-D_FILE_OFFSET_BITS=64", + ], + + shared_libs: [ + "libutils", + "libbinder", + "libcutils", + "liblog", + "libxcoder", + ], + + name: "ni_rsrc_list", + + clang: true, + +} + +//############################################################################### diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/Android.bp b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/Android.bp new file mode 100755 index 00000000..fa489a9a --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/Android.bp @@ -0,0 +1,42 @@ +cc_library_static { + name: "libxcdec", + vendor_available: true, + shared_libs: ["liblog", "libcutils","libutils","libxcoder"], + + cflags: [ + "-fPIC", + "-Wall", + "-Werror", + "-Wno-unused-parameter", + "-Wno-unused-variable", + "-Wno-macro-redefined", + "-Wno-unused-function", + ] + [ + "-D_ANDROID", + "-D_FILE_OFFSET_BITS=64", + ], + + include_dirs: [ + "external/libxcoder/source", + ], + + + srcs: [ + "decoder/ifwh264d_api.c", + ], + + local_include_dirs: [ + "decoder", + "common", + ], + + sanitize: { + cfi: true, + diag: { + cfi: true, + }, + blacklist: "cfi_blacklist.txt", + }, +} + +subdirs = ["test"] diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/cfi_blacklist.txt b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/cfi_blacklist.txt new file mode 100755 index 00000000..7a8feae9 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/cfi_blacklist.txt @@ -0,0 +1 @@ +src:*vendor/netint/libxcoder/source/android/* diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwh264_defs.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwh264_defs.h new file mode 100755 index 00000000..a7830bc1 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwh264_defs.h @@ -0,0 +1,671 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +/** +******************************************************************************* +* @file +* ih264_defs.h +* +* @brief +* Definitions used in the codec +* +* @author +* Ittiam +* +* +* @remarks +* None +* +******************************************************************************* +*/ + +#ifndef IH264_DEFS_H_ +#define IH264_DEFS_H_ + +/*****************************************************************************/ +/* Enums */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Profile and Levels */ +/*****************************************************************************/ + +/** +****************************************************************************** + * @enum PROFILE_IDC + * @brief Defines the set of possible profiles +****************************************************************************** +*/ +enum +{ + IH264_PROFILE_BASELINE = 66, + IH264_PROFILE_MAIN = 77, + IH264_PROFILE_EXTENDED = 88, + IH264_PROFILE_HIGH = 100, + IH264_PROFILE_HIGH10 = 110, + IH264_PROFILE_HIGH422 = 122, + IH264_PROFILE_HIGH444 = 144, +}; + +/** +****************************************************************************** + * @enum LEVEL_IDC + * @brief Defines the set of possible levels +****************************************************************************** +*/ +typedef enum +{ + IH264_LEVEL_10 = 10, + IH264_LEVEL_1B = 9, + IH264_LEVEL_11 = 11, + IH264_LEVEL_12 = 12, + IH264_LEVEL_13 = 13, + IH264_LEVEL_20 = 20, + IH264_LEVEL_21 = 21, + IH264_LEVEL_22 = 22, + IH264_LEVEL_30 = 30, + IH264_LEVEL_31 = 31, + IH264_LEVEL_32 = 32, + IH264_LEVEL_40 = 40, + IH264_LEVEL_41 = 41, + IH264_LEVEL_42 = 42, + IH264_LEVEL_50 = 50, + IH264_LEVEL_51 = 51, +} IH264_LEVEL_T; + +/** +****************************************************************************** + * @enum PIC TYPES + * @brief Defines the set of possible picture type - not signaled in bitstream +****************************************************************************** +*/ +typedef enum +{ + PIC_NA = 0x7FFFFFFF, + PIC_IDR = 0, + PIC_I = 1, + PIC_P = 2, + PIC_B = 3, + PIC_P_NONREF = 4, + PIC_B_NONREF = 5, + PIC_MAX, +} PIC_TYPE_T; + +/** +****************************************************************************** + * @enum FRAME-FIELD types + * @brief Defines the set of possible field types. +****************************************************************************** +*/ +enum +{ + TOP_FIELD, + BOTTOM_FIELD, + FRAME, +}; + +/** +****************************************************************************** + * @enum SLICE TYPES + * @brief Defines the set of possible SLICE TYPES +****************************************************************************** +*/ +enum +{ + PSLICE = 0, + BSLICE = 1, + ISLICE = 2, + SPSLICE = 3, + SISLICE = 4, + MAXSLICE_TYPE, +}; + +/** +****************************************************************************** + * @enum NAL_UNIT_TYPE + * @brief Defines the set of possible nal unit types +****************************************************************************** +*/ +enum +{ + NAL_UNSPEC_0 = 0, + NAL_SLICE_NON_IDR = 1, + NAL_SLICE_DPA = 2, + NAL_SLICE_DPB = 3, + NAL_SLICE_DPC = 4, + NAL_SLICE_IDR = 5, + NAL_SEI = 6, + NAL_SPS = 7, + NAL_PPS = 8, + NAL_AUD = 9, + NAL_EOSEQ = 10, + NAL_EOSTR = 11, + NAL_FILLER = 12, + NAL_SPSE = 13, + NAL_RES_18 = 14, + NAL_AUX_PIC = 19, + NAL_RES_23 = 20, + NAL_UNSPEC_31 = 24, +}; + +/** +****************************************************************************** + * @enum CHROMA_FORMAT_IDC + * @brief Defines the set of possible chroma formats + * Note Chorma format Do not change enum values +****************************************************************************** +*/ +enum +{ + CHROMA_FMT_IDC_MONOCHROME = 0, + CHROMA_FMT_IDC_YUV420 = 1, + CHROMA_FMT_IDC_YUV422 = 2, + CHROMA_FMT_IDC_YUV444 = 3, + CHROMA_FMT_IDC_YUV444_PLANES = 4, +}; + +/** +****************************************************************************** + * @enum MBMODES_I16x16 + * @brief Defines the set of possible intra 16x16 mb modes +****************************************************************************** +*/ +typedef enum +{ + VERT_I16x16 = 0, + HORZ_I16x16 = 1, + DC_I16x16 = 2, + PLANE_I16x16 = 3, + MAX_I16x16 = 4, +} MBMODES_I16x16; + +/** +****************************************************************************** + * @enum MBMODES_I4x4 + * @brief Defines the set of possible intra 4x4 mb modes +****************************************************************************** +*/ +typedef enum +{ + VERT_I4x4 = 0, + HORZ_I4x4 = 1, + DC_I4x4 = 2, + DIAG_DL_I4x4 = 3, + DIAG_DR_I4x4 = 4, + VERT_R_I4x4 = 5, + HORZ_D_I4x4 = 6, + VERT_L_I4x4 = 7, + HORZ_U_I4x4 = 8, + MAX_I4x4 = 9, +} MBMODES_I4x4; + +/** +****************************************************************************** + * @enum MBMODES_I8x8 + * @brief Defines the set of possible intra 8x8 mb modes +****************************************************************************** +*/ +typedef enum +{ + VERT_I8x8 = 0, + HORZ_I8x8 = 1, + DC_I8x8 = 2, + DIAG_DL_I8x8 = 3, + DIAG_DR_I8x8 = 4, + VERT_R_I8x8 = 5, + HORZ_D_I8x8 = 6, + VERT_L_I8x8 = 7, + HORZ_U_I8x8 = 8, + MAX_I8x8 = 9, +} MBMODES_I8x8; + +/** +****************************************************************************** + * @enum MBMODES_CHROMA_I8x8 (Chroma) + * @brief Defines the set of possible intra 8x8 mb modes for chroma +****************************************************************************** +*/ +typedef enum +{ + DC_CH_I8x8 = 0, + HORZ_CH_I8x8 = 1, + VERT_CH_I8x8 = 2, + PLANE_CH_I8x8 = 3, + MAX_CH_I8x8 = 4, +} MBMODES_CHROMA_I8x8; + +/** +****************************************************************************** + * @enum MBTYPES + * @brief Defines the set of possible macro block types +****************************************************************************** +*/ +typedef enum +{ + I16x16 = 0, + I4x4 = 1, + I8x8 = 2, + P16x16 = 3, + P16x8 = 4, + P8x16 = 5, + P8x8 = 6, + PSKIP = 7, + IPCM = 8, + B16x16 = 9, + BSKIP = 10, + BDIRECT = 11, + MAX_MBTYPES, +} MBTYPES_T; + +/* Prediction list */ +/* Do not change enum values */ +enum +{ + PRED_L0 = 0, + PRED_L1 = 1, + PRED_BI = 2 +}; + +/** +****************************************************************************** + * @enum ENTROPY_BLK_TYPE + * @brief Defines the nature of blocks employed in entropy coding +****************************************************************************** +*/ +typedef enum +{ + ENTROPY_BLK_INVALID = -1, + CAVLC_LUMA_4x4_DC = 0, + CAVLC_LUMA_4x4_AC = 1, + CAVLC_LUMA_4x4 = 2, + CAVLC_CHROMA_4x4_DC = 3, + CAVLC_CHROMA_4x4_AC = 4, +} ENTROPY_BLK_TYPE; + +/** +****************************************************************************** + * @enum ENTROPY_MODE + * @brief Entropy coding modes +****************************************************************************** +*/ +typedef enum +{ + CAVLC = 0, + CABAC = 1, +} ENTROPY_MODE; + +/** +****************************************************************************** + * @enum COMPONENT_TYPE + * @brief components Y, U & V +****************************************************************************** +*/ +typedef enum +{ + Y, + U, + V, +} COMPONENT_TYPE; + +/** +****************************************************************************** + * @enum MBPART_PREDMODE_T + * @brief MbPartps_pred_mode_ctxt Table 7-11 to 7-14 +****************************************************************************** +*/ +typedef enum +{ + MBPART_NA, + MBPART_I4x4, + MBPART_I8x8, + MBPART_I16x16, + MBPART_L0, + MBPART_L1, + MBPART_BI, + MBPART_DIRECT, + MBPART_IPCM, +} MBPART_PREDMODE_T; + +typedef enum +{ + I_NxN, + I_16x16_0_0_0, + I_16x16_1_0_0, + I_16x16_2_0_0, + I_16x16_3_0_0, + I_16x16_0_1_0, + I_16x16_1_1_0, + I_16x16_2_1_0, + I_16x16_3_1_0, + I_16x16_0_2_0, + I_16x16_1_2_0, + I_16x16_2_2_0, + I_16x16_3_2_0, + I_16x16_0_0_1, + I_16x16_1_0_1, + I_16x16_2_0_1, + I_16x16_3_0_1, + I_16x16_0_1_1, + I_16x16_1_1_1, + I_16x16_2_1_1, + I_16x16_3_1_1, + I_16x16_0_2_1, + I_16x16_1_2_1, + I_16x16_2_2_1, + I_16x16_3_2_1, + I_PCM, +} MBTYPE_ISLICE_T; + +typedef enum +{ + P_L0_16x16, + P_L0_L0_16x8, + P_L0_L0_8x16, + P_8x8, + P_8x8REF0, + P_SKIP +} MBTYPE_PSLICE_T; + +typedef enum +{ + B_DIRECT_16x16, + B_L0_16x16, + B_L1_16x16, + B_BI_16x16, + B_L0_L0_16x8, + B_L0_L0_8x16, + B_L1_L1_16x8, + B_L1_L1_8x16, + B_L0_L1_16x8, + B_L0_L1_8x16, + B_L1_L0_16x8, + B_L1_L0_8x16, + B_L0_BI_16x8, + B_L0_BI_8x16, + B_L1_BI_16x8, + B_L1_BI_8x16, + B_BI_L0_16x8, + B_BI_L0_8x16, + B_BI_L1_16x8, + B_BI_L1_8x16, + B_BI_BI_16x8, + B_BI_BI_8x16, + B_8x8, + B_SKIP, +} MBTYPE_BSLICE_T; + +typedef enum +{ + P_L0_8x8, + P_L0_8x4, + P_L0_4x8, + P_L0_4x4, +} SUBMBTYPE_PSLICE_T; + +typedef enum +{ + B_DIRECT_8x8, + B_L0_8x8, + B_L1_8x8, + B_BI_8x8, + B_L0_8x4, + B_L0_4x8, + B_L1_8x4, + B_L1_4x8, + B_BI_8x4, + B_BI_4x8, + B_L0_4x4, + B_L1_4x4, + B_BI_4x4, +} SUBMBTYPE_BSLICE_T; + +/** + * DC Mode pattern for 4 4x4 sub blocks in an MB row + */ +#define DC_I16X16_MB_ROW \ + (DC_I16x16 << 24) | (DC_I16x16 << 16) | (DC_I16x16 << 8) | DC_I16x16 + +/*****************************************************************************/ +/* Constant Macros */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Reference frame defs */ +/*****************************************************************************/ +/* Maximum DPB size */ +#define MAX_DPB_SIZE 16 + +/* Maximum mmco commands in slice header */ +#define MAX_MMCO_COMMANDS 32 + +/* Maximum reference reorder idc */ +#define MAX_MODICATION_IDC 32 + +/*****************************************************************************/ +/* SPS restrictions */ +/*****************************************************************************/ + +/* Number of SPS allowed */ +/* An extra buffer is allocated to write the parsed data + * It is copied to the appropriate location later */ +#define MAX_SPS_CNT (32 + 1) + +/* Maximum long term reference pics */ +#define MAX_LTREF_PICS_SPS 16 + +/* Maximum short term reference pics */ +#define MAX_STREF_PICS_SPS 64 + +/*****************************************************************************/ +/* PPS restrictions */ +/*****************************************************************************/ + +/* Number of PPS allowed */ +/* An extra buffer is allocated to write the parsed data + * It is copied to the appropriate location later */ +#define MAX_PPS_CNT (256 + 1) + +/*****************************************************************************/ +/* Macro definitions for sizes of MB, PU, TU, CU */ +/*****************************************************************************/ +#define MB_SIZE 16 +#define BLK8x8SIZE 8 +#define BLK_SIZE 4 + +/* TU Size Range */ +#define MAX_TU_SIZE 8 +#define MIN_TU_SIZE 4 + +/* Max Transform Size */ +#define MAX_TRANS_SIZE (MAX_TU_SIZE * MAX_TU_SIZE) + +/* PU Size Range */ +#define MAX_PU_SIZE 16 +#define MIN_PU_SIZE 4 + +/* Number of max TU in a MB row */ +#define MAX_TU_IN_MB_ROW ((MB_SIZE / MIN_TU_SIZE)) + +/* Number of max PU in a CTb row */ +#define MAX_PU_IN_MB_ROW ((MB_SIZE / MIN_PU_SIZE)) + +/* Number of max PU in a MB */ +/*****************************************************************************/ +/* Note though for 64 x 64 MB, Max PU in MB is 128, in order to store */ +/* intra pred info, 256 entries are needed */ +/*****************************************************************************/ +#define MAX_PU_IN_MB ((MB_SIZE / MIN_PU_SIZE) * (MB_SIZE / MIN_PU_SIZE)) + +/* Number of max TU in a MB */ +#define MAX_TU_IN_MB ((MB_SIZE / MIN_TU_SIZE) * (MB_SIZE / MIN_TU_SIZE)) + +/** + * Maximum transform depths + */ +#define MAX_TRAFO_DEPTH 5 + +#define MAX_DC_4x4_SUBBLK_LUMA 1 +#define MAX_AC_4x4_SUBBLK_LUMA 16 +#define MAX_DC_4x4_SUBBLK_CHROMA 2 +#define MAX_AC_4x4_SUBBLK_CHROMA 8 + +#define MAX_4x4_SUBBLKS \ + (MAX_DC_4x4_SUBBLK_LUMA + MAX_DC_4x4_SUBBLK_CHROMA + \ + MAX_AC_4x4_SUBBLK_LUMA + MAX_AC_4x4_SUBBLK_CHROMA) + +/* Max number of deblocking edges */ +#define MAX_VERT_DEBLK_EDGES ((MB_SIZE / 8) * (MB_SIZE / 4)) +#define MAX_HORZ_DEBLK_EDGES ((MB_SIZE / 4) * (MB_SIZE / 8)) + +/* Qp can not change below 8x8 level */ +#define MAX_DEBLK_QP_CNT ((MB_SIZE / 8) * (MB_SIZE / 8)) + +/*****************************************************************************/ +/* Parsing related macros */ +/*****************************************************************************/ +#define SUBBLK_COEFF_CNT 16 + +/* Quant and Trans defs */ + +/*****************************************************************************/ +/* Sizes for Transform functions */ +/*****************************************************************************/ +#define TRANS_SIZE_4 4 +#define TRANS_SIZE_8 8 +#define TRANS_SIZE_16 16 +#define TRANS_SIZE_32 32 + +#define IT_SHIFT_STAGE_1 7 +#define IT_SHIFT_STAGE_2 12 + +/** + * @breif Maximum transform dynamic range (excluding sign bit) + */ +#define MAX_TR_DYNAMIC_RANGE 15 + +/** + * @brief Q(QP%6) * IQ(QP%6) = 2^20 + */ +#define QUANT_IQUANT_SHIFT 20 + +/** + * @breif Q factor for Qp%6 multiplication + */ +#define QUANT_SHIFT 14 + +/** + * @breif Q shift factor for flat rescale matrix weights + */ +#define FLAT_RESCALE_MAT_Q_SHIFT 11 + +/** + * @breif Scaling matrix is represented in Q15 format + */ +#define SCALING_Q_SHIFT 15 + +/** + * @brief rounding factor for quantization represented in Q9 format + */ +#define QUANT_ROUND_FACTOR_Q 9 + +/** + * @brief Minimum qp supported in H264 spec + */ +#define MIN_H264_QP 0 + +/** + * @brief Maximum qp supported in H264 spec + */ +#define MAX_H264_QP 51 + +/** + * @breif Total number of transform sizes + * used for sizeID while getting scale matrix + */ +#define NUM_UNIQUE_TRANS_SIZE 4 + +/** + * @breif Maximum number of bits in frameNumber signaling + */ +#define MAX_BITS_IN_FRAME_NUM 16 + +/** + * @breif Maximum number of bits in POC LSB signaling + */ +#define MAX_BITS_IN_POC_LSB 16 + +/** + * @breif Maximum PIC Order Count type + */ +#define MAX_PIC_ORDER_COUNT_TYPE 2 + +/** + * @breif Maximum Weighted bipred idc + */ +#define MAX_WEIGHT_BIPRED_IDC 2 + +/*****************************************************************************/ +/* Number of scaling matrices for each transform size */ +/*****************************************************************************/ +#define SCALE_MAT_CNT_TRANS_SIZE_4 6 +#define SCALE_MAT_CNT_TRANS_SIZE_8 6 +#define SCALE_MAT_CNT_TRANS_SIZE_16 6 +#define SCALE_MAT_CNT_TRANS_SIZE_32 2 + +/* Maximum number of scale matrices for a given transform size */ +#define SCALE_MAT_CNT_MAX_PER_TRANS_SIZE 6 + +/* Total number of scale matrices */ +#define TOTAL_SCALE_MAT_COUNT \ + (SCALE_MAT_CNT_TRANS_SIZE_4 + SCALE_MAT_CNT_TRANS_SIZE_8 + \ + SCALE_MAT_CNT_TRANS_SIZE_16 + SCALE_MAT_CNT_TRANS_SIZE_32) + +/*****************************************************************************/ +/* Intra pred Macros */ +/*****************************************************************************/ +/** Planar Intra prediction mode */ +#define INTRA_PLANAR 0 + +/** DC Intra prediction mode */ +#define INTRA_DC 1 + +/** Gives angular mode for intra prediction */ +#define INTRA_ANGULAR(x) (x) + +/** Following is used to signal no intra prediction in case of pcm blocks + */ +#define INTRA_PRED_NONE 63 + +/** Following is used to signal no intra prediction is needed for first three + * 4x4 luma blocks in case of 4x4 TU sizes + * Also used in pcm cases + */ +#define INTRA_PRED_CHROMA_IDX_NONE 7 + +/** +****************************************************************************** + * @brief neighbor availability masks +****************************************************************************** + */ +#define LEFT_MB_AVAILABLE_MASK 0x01 +#define TOP_LEFT_MB_AVAILABLE_MASK 0x02 +#define TOP_MB_AVAILABLE_MASK 0x04 +#define TOP_RIGHT_MB_AVAILABLE_MASK 0x08 + +#endif /* IH264_DEFS_H_ */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwh264_macros.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwh264_macros.h new file mode 100755 index 00000000..8767cf5b --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwh264_macros.h @@ -0,0 +1,119 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ + +/********************************************************************************* +* @file +* ih264_macros.h +* +* @brief +* Macro definitions used in the codec +* +* @author +* Ittiam +* +* @remarks +* None +* +******************************************************************************* +*/ +#ifndef _IH264_MACROS_H_ +#define _IH264_MACROS_H_ + +/*****************************************************************************/ +/* Function Macros */ +/*****************************************************************************/ +#define RETURN_IF(cond, retval) \ + if (cond) \ + { \ + return (retval); \ + } +#define UNUSED(x) ((void)(x)) + +#define ALIGN128(x) ((((x) + 127) >> 7) << 7) +#define ALIGN64(x) ((((x) + 63) >> 6) << 6) +#define ALIGN32(x) ((((x) + 31) >> 5) << 5) +#define ALIGN16(x) ((((x) + 15) >> 4) << 4) +#define ALIGN8(x) ((((x) + 7) >> 3) << 3) +#define ALIGN4(x) ((((x) + 3) >> 2) << 2) +#define ALIGN2(x) ((((x) + 1) >> 1) << 1) + +/** +****************************************************************************** + * @brief Min, Max +****************************************************************************** + */ +#define MAX(a, b) ((a > b) ? (a) : (b)) +#define MIN(a, b) ((a < b) ? (a) : (b)) +#define MIN3(a, b, c) \ + ((a) < (b)) ? (((a) < (c)) ? (a) : (c)) : (((b) < (c)) ? (b) : (c)) +#define MAX3(a, b, c) \ + ((a) > (b)) ? (((a) > (c)) ? (a) : (c)) : (((b) > (c)) ? (b) : (c)) +/** +****************************************************************************** + * @brief Div, Mod +****************************************************************************** + */ +#define MOD(x, y) ((x) % (y)) +#define DIV(x, y) ((x) / (y)) + +/** +****************************************************************************** + * @brief Clip +****************************************************************************** + */ +#define CLIP3(miny, maxy, y) \ + (((y) < (miny)) ? (miny) : (((y) > (maxy)) ? (maxy) : (y))) + +/** +****************************************************************************** + * @brief True, False +****************************************************************************** + */ +#define BOOLEAN(x) (!!(x)) + +/** +****************************************************************************** + * @brief Frequently used multiplications x2. x3, and x4 +****************************************************************************** + */ +#define X2(a) ((a) << 1) +#define X3(a) (((a) << 1) + (a)) +#define X4(a) ((a) << 2) + +/** +****************************************************************************** + * @brief Misc +****************************************************************************** + */ +#define ABS(x) ((x) < 0 ? (-(x)) : (x)) +#define SIGNXY(x, y) (((y) < 0) ? (-1 * (x)) : (x)) + +#define SIGN(x) (((x) >= 0) ? (((x) > 0) ? 1 : 0) : -1) + +#define RESET_BIT(x, pos) (x) = (x) & ~(1 << pos); +#define SET_BIT(x, pos) (x) = (x) | (1 << pos); +#define GET_BIT(x, pos) ((x) >> (pos)) & 0x1 + +#define INSERT_BIT(x, pos, bit) \ + { \ + RESET_BIT(x, pos); \ + (x) = (x) | (bit << pos); \ + } +#endif /*_IH264_MACROS_H_*/ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwh264_typedefs.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwh264_typedefs.h new file mode 100755 index 00000000..6516ff44 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwh264_typedefs.h @@ -0,0 +1,61 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +/** +******************************************************************************* +* @file +* ih264_typedefs.h +* +* @brief +* Type definitions used in the code +* +* @author +* Ittiam +* +* @remarks +* None +* +******************************************************************************* +*/ + +#ifndef _IH264_TYPEDEFS_H_ +#define _IH264_TYPEDEFS_H_ + +/*****************************************************************************/ +/* Unsigned data types */ +/*****************************************************************************/ +typedef unsigned char UWORD8; +typedef unsigned short UWORD16; +typedef unsigned int UWORD32; +typedef unsigned long long UWORD64; + +/*****************************************************************************/ +/* Signed data types */ +/*****************************************************************************/ +typedef signed char WORD8; +typedef short WORD16; +typedef int WORD32; + +/*****************************************************************************/ +/* Miscellaneous data types */ +/*****************************************************************************/ +typedef char CHAR; +typedef double DOUBLE; + +#endif /* _IH264_TYPEDEFS_H_ */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwthread.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwthread.c new file mode 100755 index 00000000..f3458c7d --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwthread.c @@ -0,0 +1,202 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +/*****************************************************************************/ +/* */ +/* File Name : ithread.c */ +/* */ +/* Description : Contains abstraction for threads, mutex and semaphores*/ +/* */ +/* List of Functions : */ +/* */ +/* Issues / Problems : None */ +/* */ +/* Revision History : */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 Harish Initial Version */ +/*****************************************************************************/ +/*****************************************************************************/ +/* File Includes */ +/*****************************************************************************/ +#include +#include "ifwh264_typedefs.h" + +#include "ifwthread.h" +#include + +#define UNUSED(x) ((void)(x)) + +//#define PTHREAD_AFFINITY +//#define SYSCALL_AFFINITY + +#ifdef PTHREAD_AFFINITY +#define _GNU_SOURCE +#define __USE_GNU +#endif + +#include +#include +#include +#include +#ifdef PTHREAD_AFFINITY +#include +#endif + +UWORD32 ithread_get_handle_size(void) +{ + return sizeof(pthread_t); +} + +UWORD32 ithread_get_mutex_lock_size(void) +{ + return sizeof(pthread_mutex_t); +} + +WORD32 ithread_create(void *thread_handle, void *attribute, void *strt, + void *argument) +{ + UNUSED(attribute); + return pthread_create((pthread_t *)thread_handle, NULL, + (void *(*)(void *))strt, argument); +} + +WORD32 ithread_join(void *thread_handle, void **val_ptr) +{ + UNUSED(val_ptr); + pthread_t *pthread_handle = (pthread_t *)thread_handle; + return pthread_join(*pthread_handle, NULL); +} + +WORD32 ithread_get_mutex_struct_size(void) +{ + return (sizeof(pthread_mutex_t)); +} +WORD32 ithread_mutex_init(void *mutex) +{ + return pthread_mutex_init((pthread_mutex_t *)mutex, NULL); +} + +WORD32 ithread_mutex_destroy(void *mutex) +{ + return pthread_mutex_destroy((pthread_mutex_t *)mutex); +} + +WORD32 ithread_mutex_lock(void *mutex) +{ + return pthread_mutex_lock((pthread_mutex_t *)mutex); +} + +WORD32 ithread_mutex_unlock(void *mutex) +{ + return pthread_mutex_unlock((pthread_mutex_t *)mutex); +} + +void ithread_yield(void) +{ + sched_yield(); +} + +void ithread_sleep(UWORD32 u4_time) +{ + usleep(u4_time * 1000 * 1000); +} + +void ithread_msleep(UWORD32 u4_time_ms) +{ + usleep(u4_time_ms * 1000); +} + +void ithread_usleep(UWORD32 u4_time_us) +{ + usleep(u4_time_us); +} + +UWORD32 ithread_get_sem_struct_size(void) +{ + return (sizeof(sem_t)); +} + +WORD32 ithread_sem_init(void *sem, WORD32 pshared, UWORD32 value) +{ + return sem_init((sem_t *)sem, pshared, value); +} + +WORD32 ithread_sem_post(void *sem) +{ + return sem_post((sem_t *)sem); +} + +WORD32 ithread_sem_wait(void *sem) +{ + return sem_wait((sem_t *)sem); +} + +WORD32 ithread_sem_destroy(void *sem) +{ + return sem_destroy((sem_t *)sem); +} + +void ithread_set_name(CHAR *pc_thread_name) +{ +#ifndef WIN32 +#ifndef QNX +#ifndef IOS + UNUSED(pc_thread_name); +//prctl(PR_SET_NAME, (unsigned long)pu1_thread_name, 0, 0, 0); +#endif +#endif +#endif +} +WORD32 ithread_set_affinity(WORD32 core_id) +{ +#ifdef PTHREAD_AFFINITY + cpu_set_t cpuset; + int num_cores = sysconf(_SC_NPROCESSORS_ONLN); + pthread_t cur_thread = pthread_self(); + + if (core_id >= num_cores) + return -1; + + CPU_ZERO(&cpuset); + CPU_SET(core_id, &cpuset); + + return pthread_setaffinity_np(cur_thread, sizeof(cpu_set_t), &cpuset); + +#elif SYSCALL_AFFINITY + WORD32 i4_sys_res; + UNUSED(core_id); + + pid_t pid = gettid(); + + i4_sys_res = + syscall(__NR_sched_setaffinity, pid, sizeof(i4_mask), &i4_mask); + if (i4_sys_res) + { + //WORD32 err; + //err = errno; + //perror("Error in setaffinity syscall PERROR : "); + //LOG_ERROR("Error in the syscall setaffinity: mask=0x%x err=0x%x", i4_mask, i4_sys_res); + return -1; + } +#else + UNUSED(core_id); +#endif + return 1; +} diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwthread.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwthread.h new file mode 100755 index 00000000..75c9f90a --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/common/ifwthread.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +/*****************************************************************************/ +/* */ +/* File Name : ithread.h */ +/* */ +/* Description : This file contains all the necessary structure and */ +/* enumeration definitions needed for the Application */ +/* Program Interface(API) of the */ +/* Thread Abstraction Layer */ +/* */ +/* List of Functions : ithread_get_handle_size */ +/* ithread_get_mutex_lock_size */ +/* ithread_create */ +/* ithread_join */ +/* ithread_get_mutex_struct_size */ +/* ithread_mutex_init */ +/* ithread_mutex_destroy */ +/* ithread_mutex_lock */ +/* ithread_mutex_unlock */ +/* ithread_yield */ +/* ithread_sleep */ +/* ithread_msleep */ +/* ithread_usleep */ +/* ithread_get_sem_struct_size */ +/* ithread_sem_init */ +/* ithread_sem_post */ +/* ithread_sem_wait */ +/* ithread_sem_destroy */ +/* ithread_set_affinity */ +/* */ +/* Issues / Problems : None */ +/* */ +/* Revision History : */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 06 09 2012 Harish Initial Version */ +/* */ +/*****************************************************************************/ + +#ifndef _ITHREAD_H_ +#define _ITHREAD_H_ + +UWORD32 ithread_get_handle_size(void); + +UWORD32 ithread_get_mutex_lock_size(void); + +WORD32 ithread_create(void *thread_handle, void *attribute, void *strt, + void *argument); + +WORD32 ithread_join(void *thread_id, void **val_ptr); + +WORD32 ithread_get_mutex_struct_size(void); + +WORD32 ithread_mutex_init(void *mutex); + +WORD32 ithread_mutex_destroy(void *mutex); + +WORD32 ithread_mutex_lock(void *mutex); + +WORD32 ithread_mutex_unlock(void *mutex); + +void ithread_yield(void); + +void ithread_sleep(UWORD32 u4_time); + +void ithread_msleep(UWORD32 u4_time_ms); + +void ithread_usleep(UWORD32 u4_time_us); + +UWORD32 ithread_get_sem_struct_size(void); + +WORD32 ithread_sem_init(void *sem, WORD32 pshared, UWORD32 value); + +WORD32 ithread_sem_post(void *sem); + +WORD32 ithread_sem_wait(void *sem); + +WORD32 ithread_sem_destroy(void *sem); + +WORD32 ithread_set_affinity(WORD32 core_id); + +void ithread_set_name(CHAR *pc_thread_name); + +#endif /* _ITHREAD_H_ */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d.h new file mode 100755 index 00000000..577adb10 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d.h @@ -0,0 +1,523 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +/*****************************************************************************/ +/* */ +/* File Name : ih264d.h */ +/* */ +/* Description : This file contains all the necessary structure and */ +/* enumeration definitions needed for the Application */ +/* Program Interface(API) of the Ittiam H264 ASP */ +/* Decoder on Cortex A8 - Neon platform */ +/* */ +/* List of Functions : ifwh264d_api_function */ +/* */ +/* Issues / Problems : None */ +/* */ +/* Revision History : */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 26 08 2010 100239(RCY) Draft */ +/* */ +/*****************************************************************************/ + +#ifndef _IH264D_H_ +#define _IH264D_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#include "ifwv.h" +#include "ifwvd.h" + +/*****************************************************************************/ +/* Constant Macros */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Function Macros */ +/*****************************************************************************/ +#define IS_IVD_CONCEALMENT_APPLIED(x) (x & (1 << IVD_APPLIEDCONCEALMENT)) +#define IS_IVD_INSUFFICIENTDATA_ERROR(x) (x & (1 << IVD_INSUFFICIENTDATA)) +#define IS_IVD_CORRUPTEDDATA_ERROR(x) (x & (1 << IVD_CORRUPTEDDATA)) +#define IS_IVD_CORRUPTEDHEADER_ERROR(x) (x & (1 << IVD_CORRUPTEDHEADER)) +#define IS_IVD_UNSUPPORTEDINPUT_ERROR(x) (x & (1 << IVD_UNSUPPORTEDINPUT)) +#define IS_IVD_UNSUPPORTEDPARAM_ERROR(x) (x & (1 << IVD_UNSUPPORTEDPARAM)) +#define IS_IVD_FATAL_ERROR(x) (x & (1 << IVD_FATALERROR)) +#define IS_IVD_INVALID_BITSTREAM_ERROR(x) (x & (1 << IVD_INVALID_BITSTREAM)) +#define IS_IVD_INCOMPLETE_BITSTREAM_ERROR(x) \ + (x & (1 << IVD_INCOMPLETE_BITSTREAM)) + +#define FW_CREATE_DUMP_FILE(m_filename) \ + { \ + FILE *fp = fopen(m_filename, "wb+"); \ + if (fp != NULL) \ + { \ + fclose(fp); \ + } else \ + { \ + printf("Could not open file %s", m_filename); \ + printf("open fail errno = %d reason = %s \n", errno, \ + strerror(errno)); \ + } \ + } + +#define FW_DUMP_TO_FILE(m_filename, m_buf, m_size, m_offset) \ + { \ + FILE *fp = fopen(m_filename, "ab"); \ + if (fp != NULL && m_buf != NULL && m_offset == 0) \ + { \ + int i; \ + i = fwrite(m_buf, 1, m_size, fp); \ + printf("fwrite ret %d to write %d", i, m_size); \ + if (i != (int)m_size) \ + { \ + printf("Error in fwrite, returned %d", i); \ + perror("Error in write to file"); \ + } \ + if (fflush(fp)) \ + { \ + printf("Error in fflush, returned %d", i); \ + } \ + } else if (fp == NULL) \ + { \ + printf("Could not write to file %s", m_filename); \ + printf("write fail errno = %d reason = %s \n", errno, \ + strerror(errno)); \ + } \ + if (fp) \ + { \ + fclose(fp); \ + } \ + } + +/*****************************************************************************/ +/* API Function Prototype */ +/*****************************************************************************/ +IV_API_CALL_STATUS_T ifwh264d_api_function(iv_obj_t *ps_handle, void *pv_api_ip, + void *pv_api_op); + +/*****************************************************************************/ +/* Enums */ +/*****************************************************************************/ +/* Codec Error codes for H264 ASP Decoder */ + +typedef enum +{ + + IH264D_VID_HDR_DEC_NUM_FRM_BUF_NOT_SUFFICIENT = + IVD_DUMMY_ELEMENT_FOR_CODEC_EXTENSIONS + 1, + +} IH264D_ERROR_CODES_T; + +/*****************************************************************************/ +/* Extended Structures */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Delete Codec */ +/*****************************************************************************/ + +typedef struct +{ + ivd_delete_ip_t s_ivd_delete_ip_t; +} ifwh264d_delete_ip_t; + +typedef struct +{ + ivd_delete_op_t s_ivd_delete_op_t; +} ifwh264d_delete_op_t; + +/*****************************************************************************/ +/* Fwcheck decoder */ +/*****************************************************************************/ + +typedef struct +{ + ivd_fwcheck_ip_t s_ivd_fwcheck_ip_t; +} ifwh264d_fwcheck_ip_t; + +typedef struct +{ + ivd_fwcheck_op_t s_ivd_fwcheck_op_t; +} ifwh264d_fwcheck_op_t; + +/*****************************************************************************/ +/* Initialize decoder */ +/*****************************************************************************/ + +typedef struct +{ + ivd_create_ip_t s_ivd_create_ip_t; +} ifwh264d_create_ip_t; + +typedef struct +{ + ivd_create_op_t s_ivd_create_op_t; +} ifwh264d_create_op_t; + +/*****************************************************************************/ +/* Video Decode */ +/*****************************************************************************/ + +typedef struct +{ + ivd_video_decode_ip_t s_ivd_video_decode_ip_t; +} ifwh264d_video_decode_ip_t; + +typedef struct +{ + ivd_video_decode_op_t s_ivd_video_decode_op_t; +} ifwh264d_video_decode_op_t; + +/*****************************************************************************/ +/* Get Display Frame */ +/*****************************************************************************/ + +typedef struct +{ + ivd_get_display_frame_ip_t s_ivd_get_display_frame_ip_t; +} ih264d_get_display_frame_ip_t; + +typedef struct +{ + ivd_get_display_frame_op_t s_ivd_get_display_frame_op_t; +} ih264d_get_display_frame_op_t; + +/*****************************************************************************/ +/* Set Display Frame */ +/*****************************************************************************/ + +typedef struct +{ + ivd_set_display_frame_ip_t s_ivd_set_display_frame_ip_t; +} ih264d_set_display_frame_ip_t; + +typedef struct +{ + ivd_set_display_frame_op_t s_ivd_set_display_frame_op_t; +} ih264d_set_display_frame_op_t; + +/*****************************************************************************/ +/* Release Display Buffers */ +/*****************************************************************************/ + +typedef struct +{ + ivd_rel_display_frame_ip_t s_ivd_rel_display_frame_ip_t; +} ih264d_rel_display_frame_ip_t; + +typedef struct +{ + ivd_rel_display_frame_op_t s_ivd_rel_display_frame_op_t; +} ih264d_rel_display_frame_op_t; + +typedef enum +{ + /** Set number of cores/threads to be used */ + IFWH264D_CMD_CTL_SET_NUM_CORES = IVD_CMD_CTL_CODEC_SUBCMD_START, + + /** Set processor details */ + IH264D_CMD_CTL_SET_PROCESSOR = IVD_CMD_CTL_CODEC_SUBCMD_START + 0x001, + + /** Get display buffer dimensions */ + IH264D_CMD_CTL_GET_BUFFER_DIMENSIONS = + IVD_CMD_CTL_CODEC_SUBCMD_START + 0x100, + + /** Get VUI parameters */ + IH264D_CMD_CTL_GET_VUI_PARAMS = IVD_CMD_CTL_CODEC_SUBCMD_START + 0x101, + + /** Enable/disable GPU, supported on select platforms */ + IH264D_CMD_CTL_GPU_ENABLE_DISABLE = IVD_CMD_CTL_CODEC_SUBCMD_START + 0x200, + + /** Set degrade level */ + IH264D_CMD_CTL_DEGRADE = IVD_CMD_CTL_CODEC_SUBCMD_START + 0x300 +} IH264D_CMD_CTL_SUB_CMDS; + +/*****************************************************************************/ +/* Video control Flush */ +/*****************************************************************************/ + +typedef struct +{ + ivd_ctl_flush_ip_t s_ivd_ctl_flush_ip_t; +} ih264d_ctl_flush_ip_t; + +typedef struct +{ + ivd_ctl_flush_op_t s_ivd_ctl_flush_op_t; +} ih264d_ctl_flush_op_t; + +/*****************************************************************************/ +/* Video control reset */ +/*****************************************************************************/ + +typedef struct +{ + ivd_ctl_reset_ip_t s_ivd_ctl_reset_ip_t; +} ih264d_ctl_reset_ip_t; + +typedef struct +{ + ivd_ctl_reset_op_t s_ivd_ctl_reset_op_t; +} ih264d_ctl_reset_op_t; + +/*****************************************************************************/ +/* Video control Set Params */ +/*****************************************************************************/ + +typedef struct +{ + ivd_ctl_set_config_ip_t s_ivd_ctl_set_config_ip_t; +} ih264d_ctl_set_config_ip_t; + +typedef struct +{ + ivd_ctl_set_config_op_t s_ivd_ctl_set_config_op_t; +} ih264d_ctl_set_config_op_t; + +/*****************************************************************************/ +/* Video control:Get Buf Info */ +/*****************************************************************************/ + +typedef struct +{ + ivd_ctl_getbufinfo_ip_t s_ivd_ctl_getbufinfo_ip_t; +} ih264d_ctl_getbufinfo_ip_t; + +typedef struct +{ + ivd_ctl_getbufinfo_op_t s_ivd_ctl_getbufinfo_op_t; +} ih264d_ctl_getbufinfo_op_t; + +/*****************************************************************************/ +/* Video control:Getstatus Call */ +/*****************************************************************************/ + +typedef struct +{ + ivd_ctl_getstatus_ip_t s_ivd_ctl_getstatus_ip_t; +} ih264d_ctl_getstatus_ip_t; + +typedef struct +{ + ivd_ctl_getstatus_op_t s_ivd_ctl_getstatus_op_t; +} ih264d_ctl_getstatus_op_t; + +/*****************************************************************************/ +/* Video control:Get Version Info */ +/*****************************************************************************/ + +typedef struct +{ + ivd_ctl_getversioninfo_ip_t s_ivd_ctl_getversioninfo_ip_t; +} ih264d_ctl_getversioninfo_ip_t; + +typedef struct +{ + ivd_ctl_getversioninfo_op_t s_ivd_ctl_getversioninfo_op_t; +} ih264d_ctl_getversioninfo_op_t; + +typedef struct +{ + /** + * u4_size + */ + UWORD32 u4_size; + + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * sub_cmd + */ + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + + /** + * Pictures that are are degraded + * 0 : No degrade + * 1 : Only on non-reference frames + * 2 : Use interval specified by u4_nondegrade_interval + * 3 : All non-key frames + * 4 : All frames + */ + WORD32 i4_degrade_pics; + + /** + * Interval for pictures which are completely decoded without any degradation + */ + WORD32 i4_nondegrade_interval; + + /** + * bit position (lsb is zero): Type of degradation + * 1 : Disable deblocking + * 2 : Faster inter prediction filters + * 3 : Fastest inter prediction filters + */ + WORD32 i4_degrade_type; + +} ih264d_ctl_degrade_ip_t; + +typedef struct +{ + /** + * u4_size + */ + UWORD32 u4_size; + + /** + * error_code + */ + UWORD32 u4_error_code; +} ih264d_ctl_degrade_op_t; + +typedef struct +{ + UWORD32 u4_size; + IVD_API_COMMAND_TYPE_T e_cmd; + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + UWORD32 u4_disable_deblk_level; +} ih264d_ctl_disable_deblock_ip_t; + +typedef struct +{ + UWORD32 u4_size; + UWORD32 u4_error_code; +} ih264d_ctl_disable_deblock_op_t; + +typedef struct +{ + UWORD32 u4_size; + IVD_API_COMMAND_TYPE_T e_cmd; + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + UWORD32 u4_num_cores; +} ifwh264d_ctl_set_num_cores_ip_t; + +typedef struct +{ + UWORD32 u4_size; + UWORD32 u4_error_code; +} ifwh264d_ctl_set_num_cores_op_t; + +typedef struct +{ + /** + * i4_size + */ + UWORD32 u4_size; + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + /** + * sub cmd + */ + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + /** + * Processor type + */ + UWORD32 u4_arch; + /** + * SOC type + */ + UWORD32 u4_soc; + + /** + * num_cores + */ + UWORD32 u4_num_cores; + +} ih264d_ctl_set_processor_ip_t; + +typedef struct +{ + /** + * i4_size + */ + UWORD32 u4_size; + /** + * error_code + */ + UWORD32 u4_error_code; +} ih264d_ctl_set_processor_op_t; + +typedef struct +{ + UWORD32 u4_size; + IVD_API_COMMAND_TYPE_T e_cmd; + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; +} ih264d_ctl_get_frame_dimensions_ip_t; + +typedef struct +{ + UWORD32 u4_size; + UWORD32 u4_error_code; + UWORD32 u4_x_offset[3]; + UWORD32 u4_y_offset[3]; + UWORD32 u4_disp_wd[3]; + UWORD32 u4_disp_ht[3]; + UWORD32 u4_buffer_wd[3]; + UWORD32 u4_buffer_ht[3]; +} ih264d_ctl_get_frame_dimensions_op_t; + +typedef struct +{ + UWORD32 u4_size; + IVD_API_COMMAND_TYPE_T e_cmd; + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; +} ih264d_ctl_get_vui_params_ip_t; + +typedef struct +{ + UWORD32 u4_size; + UWORD32 u4_error_code; + UWORD8 u1_aspect_ratio_idc; + UWORD16 u2_sar_width; + UWORD16 u2_sar_height; + UWORD8 u1_overscan_appropriate_flag; + UWORD8 u1_video_format; + UWORD8 u1_video_full_range_flag; + UWORD8 u1_colour_primaries; + UWORD8 u1_tfr_chars; + UWORD8 u1_matrix_coeffs; + UWORD8 u1_cr_top_field; + UWORD8 u1_cr_bottom_field; + UWORD32 u4_num_units_in_tick; + UWORD32 u4_time_scale; + UWORD8 u1_fixed_frame_rate_flag; + UWORD8 u1_nal_hrd_params_present; + UWORD8 u1_vcl_hrd_params_present; + UWORD8 u1_low_delay_hrd_flag; + UWORD8 u1_pic_struct_present_flag; + UWORD8 u1_bitstream_restriction_flag; + UWORD8 u1_mv_over_pic_boundaries_flag; + UWORD32 u4_max_bytes_per_pic_denom; + UWORD32 u4_max_bits_per_mb_denom; + UWORD32 u4_log2_max_mv_length_horz; + UWORD32 u4_log2_max_mv_length_vert; + UWORD32 u4_num_reorder_frames; + UWORD32 u4_max_dec_frame_buffering; +} ih264d_ctl_get_vui_params_op_t; + +#ifdef __cplusplus +} /* closing brace for extern "C" */ +#endif +#endif /* _IH264D_H_ */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_api.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_api.c new file mode 100755 index 00000000..1e885f72 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_api.c @@ -0,0 +1,2277 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ + +/*****************************************************************************/ +/* */ +/* File Name : ifwh264d_api.c */ +/* */ +/* Description : Has all API related functions */ +/* */ +/* */ +/* List of Functions : api_check_struct_sanity */ +/* ih264d_set_processor */ +/* ifwh264d_create */ +/* ifwh264d_delete */ +/* ih264d_init */ +/* ih264d_map_error */ +/* ifwh264d_video_decode */ +/* ifwh264d_get_version */ +/* ih264d_get_display_frame */ +/* ih264d_set_display_frame */ +/* ifwh264d_fwcheck */ +/* ifwh264d_set_flush_mode */ +/* ih264d_get_status */ +/* ih264d_get_buf_info */ +/* ifwh264d_set_params */ +/* ifwh264d_set_default_params */ +/* ifwh264d_reset */ +/* ifwh264d_ctl */ +/* ih264d_rel_display_frame */ +/* ih264d_set_degrade */ +/* ih264d_get_frame_dimensions */ +/* ifwh264d_set_num_cores */ +/* ifwh264d_fill_output_struct_from_context */ +/* ifwh264d_api_function */ +/* */ +/* Issues / Problems : None */ +/* */ +/* Revision History : */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 14 10 2008 100356(SKV) Draft */ +/* */ +/*****************************************************************************/ + +#define LOG_NDEBUG 0 +//#undef NDEBUG + +#include + +#include "ifwh264_typedefs.h" +#include "ifwh264_macros.h" +#include "ifwv.h" +#include "ifwvd.h" +#include "ifwh264d.h" +#include "ifwh264d_defs.h" +#include "ifwh264d_debug.h" + +#include +#include +#include +#include +#include + +#include "ifwh264d_structs.h" + +#include "ifwh264d_error_handler.h" + +#include "ifwh264d_defs.h" + +#include "ifwh264d_utils.h" + +#include "ifwthread.h" +#include + +#include +#include +#include + +#include "ni_rsrc_api.h" +#include "ni_rsrc_priv.h" +#include "ni_device_api.h" +#include "ni_util.h" +#include "ni_device_test.h" + +#include +#include +#include + +#include // for close + +/*********************/ +/* Codec Versioning */ +/*********************/ + +#define LOG_TAG "ifwh264d_api!!" + +//Move this to where it is used +#define CODEC_NAME "H264VDEC" +#define CODEC_RELEASE_TYPE "production" +#define CODEC_RELEASE_VER "05.00" +#define CODEC_VENDOR "ITTIAM" +#define MAXVERSION_STRLEN 511 +#ifdef __ANDROID__ +#define VERSION(version_string, codec_name, codec_release_type, \ + codec_release_ver, codec_vendor) \ + snprintf(version_string, MAXVERSION_STRLEN, \ + "@(#)Id:%s_%s Ver:%s Released by %s", codec_name, \ + codec_release_type, codec_release_ver, codec_vendor) +#else +#define VERSION(version_string, codec_name, codec_release_type, \ + codec_release_ver, codec_vendor) \ + snprintf(version_string, MAXVERSION_STRLEN, \ + "@(#)Id:%s_%s Ver:%s Released by %s Build: %s @ %s", codec_name, \ + codec_release_type, codec_release_ver, codec_vendor, __DATE__, \ + __TIME__) +#endif + +#define MIN_IN_BUFS 1 +#define MIN_OUT_BUFS_420 3 +#define MIN_OUT_BUFS_422ILE 1 +#define MIN_OUT_BUFS_RGB565 1 +#define MIN_OUT_BUFS_420SP 2 + +#define NUM_FRAMES_LIMIT_ENABLED 0 + +#if NUM_FRAMES_LIMIT_ENABLED +#define NUM_FRAMES_LIMIT 10000 +#else +#define NUM_FRAMES_LIMIT 0x7FFFFFFF +#endif + +#include +#define PROP_DECODER_LOGLEVEL "use_decode_loglevel" +#define PROP_DECODER_HW_ID "use_decode_hw_id" + +volatile int send_fin_flag = 0, recieve_fin_flag = 0, err_flag = 0; +volatile uint32_t number_of_frames = 0; +volatile uint32_t number_of_packets = 0; +struct timeval start_time, previous_time, current_time; +time_t start_timestamp = 0, privious_timestamp = 0, current_timestamp = 0; + +// 1.8 GB file cache +volatile unsigned long total_file_size = 0; +volatile uint32_t data_left_size = 0; + +char *mInFile = "/data/misc/media/avcd_input.h264"; + +char *mdecoderFile = "/data/misc/media/avcd_decoder.yuv"; + +FILE *pIn_file = NULL; +FILE *p_file = NULL; + +int send_dump = 0; +int receive_dump = 0; + +/*!****************************************************************************** + * \brief Send decoder input data + * + * \param + * + * \return + *******************************************************************************/ +ni_retcode_t decoder_send_data_buf( + ni_session_context_t *p_dec_ctx, ni_session_data_io_t *p_in_data, + int sos_flag, int input_video_width, int input_video_height, FILE *p_file, + uint8_t *pkt_buf, int pkt_size, int file_size, + unsigned long *total_bytes_sent, int print_time, int write_to_file, + device_state_t *p_device_state) +{ + //static uint8_t tmp_buf[NI_MAX_PACKET_SZ - 32] = { 0 }; + //uint8_t *tmp_buf_ptr = pkt_buf; + int packet_size = pkt_size; + //int chunk_size = 0; + int frame_pkt_size = 0; + //int nal_size = 0; + //int nal_type = -1; + int tx_size = 0; + int send_size = 0; + int new_packet = 0; + ni_packet_t *p_in_pkt = &(p_in_data->data.packet); + ni_retcode_t retval = NI_RETCODE_SUCCESS; + + ni_log(NI_LOG_DEBUG, "===> decoder_send_data <===\n"); + + /*if(pkt_size > 0 && p_file && write_to_file) + { + if (fwrite(pkt_buf, pkt_size, 1, p_file) != 1) + { + ni_log(NI_LOG_ERROR, "decoder_send_data Writing data %d bytes error !\n", pkt_size); + ni_log(NI_LOG_ERROR, "decoder_send_data ferror rc = %d\n", ferror(p_file)); + } + if (fflush(p_file)) + { + ni_log(NI_LOG_ERROR, "decoder_receive_data_buf Writing data frame flush failed! errno %d\n", errno); + } + }*/ + + if (p_device_state->dec_eos_sent) + { + ni_log(NI_LOG_DEBUG, + "decoder_send_data: ALL data (incl. eos) sent " + "already !\n"); + LRETURN; + } + + ni_log(NI_LOG_DEBUG, + "decoder_send_data 000 size pkt_size %d, p_in_pkt->data_len %d, " + "p_dec_ctx->prev_size %d\n", + pkt_size, p_in_pkt->data_len, p_dec_ctx->prev_size); + + if (0 == p_in_pkt->data_len) + { + memset(p_in_pkt, 0, sizeof(ni_packet_t)); + /*if (NI_CODEC_FORMAT_H264 == p_dec_ctx->codec_format) + { + // send whole encoded packet which ends with a slice NAL + while ((nal_size = find_h264_next_nalu(tmp_buf_ptr, &nal_type)) > 0) + { + frame_pkt_size += nal_size; + tmp_buf_ptr += nal_size; +#if 0 + printf("nal %d nal_size %d frame_pkt_size %d\n", nal_type, nal_size, + frame_pkt_size); +#endif + if (H264_NAL_SLICE == nal_type || H264_NAL_IDR_SLICE == nal_type) + { + break; + } + } + } + else + { + frame_pkt_size = chunk_size = packet_size; + //chunk_size = read_next_chunk(tmp_buf, packet_size); + }*/ + + //frame_pkt_size = chunk_size = packet_size; + frame_pkt_size = packet_size; + + /*if(pkt_size > NI_MAX_PACKET_SZ){ + ni_log(NI_LOG_ERROR, "decoder_send_data error !!! size pkt_size %d, NI_MAX_PACKET_SZ %d\n", pkt_size, NI_MAX_PACKET_SZ); + }*/ + //memcpy(tmp_buf, pkt_buf, packet_size); + + p_in_pkt->p_data = NULL; + p_in_pkt->data_len = frame_pkt_size; + + if (frame_pkt_size + p_dec_ctx->prev_size > 0) + { + ni_packet_buffer_alloc(p_in_pkt, + frame_pkt_size + p_dec_ctx->prev_size); + } + + new_packet = 1; + send_size = frame_pkt_size + p_dec_ctx->prev_size; + } else + { + send_size = p_in_pkt->data_len; + } + + ni_log(NI_LOG_DEBUG, + "decoder_send_data 001 send_size %d, new_packet %d, " + "p_dec_ctx->prev_size %d, frame_pkt_size %d\n", + send_size, new_packet, p_dec_ctx->prev_size, frame_pkt_size); + + p_in_pkt->start_of_stream = sos_flag; + p_in_pkt->end_of_stream = 0; + p_in_pkt->video_width = input_video_width; + p_in_pkt->video_height = input_video_height; + + if (send_size == 0) + { + if (new_packet) + { + //send_size = ni_packet_copy(p_in_pkt->p_data, tmp_buf, 0, + // p_dec_ctx->p_leftover, &p_dec_ctx->prev_size); + + send_size = + ni_packet_copy(p_in_pkt->p_data, pkt_buf, 0, + p_dec_ctx->p_leftover, &p_dec_ctx->prev_size); + // todo save offset + } + + p_in_pkt->data_len = send_size; + + p_in_pkt->end_of_stream = 1; + ni_log(NI_LOG_DEBUG, "Sending p_last packet (size %d) + eos\n", + p_in_pkt->data_len); + } else + { + if (new_packet) + { + //send_size = ni_packet_copy(p_in_pkt->p_data, tmp_buf, frame_pkt_size, + // p_dec_ctx->p_leftover, &p_dec_ctx->prev_size); + + send_size = + ni_packet_copy(p_in_pkt->p_data, pkt_buf, frame_pkt_size, + p_dec_ctx->p_leftover, &p_dec_ctx->prev_size); + // todo: update offset with send_size + // p_in_pkt->data_len is the actual packet size to be sent to decoder + } + } + + ni_log(NI_LOG_DEBUG, + "decoder_send_data 002 send_size %d, p_in_pkt->data_len %d, " + "p_dec_ctx->prev_size %d, new_packet %d\n", + send_size, p_in_pkt->data_len, p_dec_ctx->prev_size, new_packet); + + if (packet_size > 0 && p_file && write_to_file) + { + if (fwrite(p_in_pkt->p_data, p_in_pkt->data_len, 1, p_file) != 1) + { + ni_log(NI_LOG_ERROR, + "decoder_send_data Writing data %d bytes error !\n", + packet_size); + ni_log(NI_LOG_ERROR, "decoder_send_data ferror rc = %d\n", + ferror(p_file)); + } + if (fflush(p_file)) + { + ni_log(NI_LOG_ERROR, + "decoder_receive_data_buf Writing data frame flush failed! " + "errno %d\n", + errno); + } + } + + tx_size = + ni_device_session_write(p_dec_ctx, p_in_data, NI_DEVICE_TYPE_DECODER); + + ni_log(NI_LOG_DEBUG, + "decoder_send_data 003 tx_size %d, p_dec_ctx->prev_size %d\n", + tx_size, p_dec_ctx->prev_size); + + if (tx_size < 0) + { + // Error + fprintf(stderr, "Sending data error. rc:%d\n", tx_size); + retval = NI_RETCODE_FAILURE; + LRETURN; + } else if (tx_size == 0) + { + ni_log(NI_LOG_DEBUG, + "0 bytes sent this time, sleep and re-try p_next time .\n"); + usleep(10000); + } else if (tx_size < send_size) + { + if (print_time) + { + ni_log( + NI_LOG_DEBUG, + "decoder_send_data 004 Sent %d < %d , re-try p_next time ?\n", + tx_size, send_size); + } + } + + *total_bytes_sent += tx_size; + + if (p_dec_ctx->ready_to_close) + { + p_device_state->dec_eos_sent = 1; + } + + if (print_time) + { + ni_log(NI_LOG_DEBUG, "decoder_send_data: success, total sent: %ld\n", + *total_bytes_sent); + } + + if (tx_size > 0) + { + ni_log(NI_LOG_DEBUG, "decoder_send_data: reset packet_buffer.\n"); + ni_packet_buffer_free(p_in_pkt); + } + +#if 0 +bytes_sent += chunk_size; +ni_log(NI_LOG_DEBUG, "[W] %d percent %d bytes sent. rc:%d result:%d\n", bytes_sent*100/file_size, chunk_size, rc, result); +sos_flag = 0; +if (NI_RETCODE_NVME_SC_WRITE_BUFFER_FULL == rc) +{ + ni_log(NI_LOG_DEBUG, "Buffer Full.\n"); +} +else if (rc != 0) +{ + // Error + fprintf(stderr, "Sending data error. rc:%d result:%d.\n", rc, result); + err_flag = 1; + return 2; +} +#endif + + //retval = NI_RETCODE_SUCCESS; + + END; + + return retval; +} + +/*!****************************************************************************** + * \brief Receive output data from decoder + * + * \param + * + * \return 0: got YUV frame; 1: end-of-stream; 2: got nothing + *******************************************************************************/ +int decoder_receive_data_buf(ni_session_context_t *p_dec_ctx, + ni_session_data_io_t *p_out_data, + int output_video_width, int output_video_height, + FILE *p_file, int *bytes_recv, + unsigned long long *total_bytes_recieved, + int print_time, int write_to_file, + device_state_t *p_device_state) +{ + int rc = NI_RETCODE_FAILURE; + int end_flag = 0; + int rx_size = 0; + ni_frame_t *p_out_frame = &(p_out_data->data.frame); + int width, height; + + ni_log(NI_LOG_DEBUG, "===> decoder_receive_data <===\n"); + + if (p_device_state->dec_eos_received) + { + ni_log(NI_LOG_DEBUG, + "decoder_receive_data: eos received already, Done !\n"); + LRETURN; + } + + // prepare memory buffer for receiving decoded frame + width = p_dec_ctx->active_video_width > 0 ? p_dec_ctx->active_video_width : + output_video_width; + height = p_dec_ctx->active_video_height > 0 ? + p_dec_ctx->active_video_height : + output_video_height; + + // allocate memory only after resolution is known (for buffer pool set up) + int alloc_mem = (p_dec_ctx->active_video_width > 0 && + p_dec_ctx->active_video_height > 0 ? + 1 : + 0); + rc = ni_decoder_frame_buffer_alloc( + p_dec_ctx->dec_fme_buf_pool, &(p_out_data->data.frame), alloc_mem, + width, height, p_dec_ctx->codec_format == NI_CODEC_FORMAT_H264, + p_dec_ctx->bit_depth_factor, 1); + + /*rc = ni_frame_buffer_alloc(p_out_frame, output_video_width, + output_video_height, + p_dec_ctx->codec_format == NI_CODEC_FORMAT_H264, 1, + 1); // default to AV_PIX_FMT_YUV420P 8bit*/ + if (NI_RETCODE_SUCCESS != rc) + { + LRETURN; + } + + ni_log(NI_LOG_DEBUG, "decoder_receive_data_buf 000\n"); + + rx_size = + ni_device_session_read(p_dec_ctx, p_out_data, NI_DEVICE_TYPE_DECODER); + + ni_log(NI_LOG_DEBUG, "decoder_receive_data_buf 001\n"); + + ni_log(NI_LOG_DEBUG, + "decoder_receive_data_buf 002 p_dec_ctx->frame_num %" PRIu64 + ", rx_size %d\n", + p_dec_ctx->frame_num, rx_size); + + end_flag = p_out_frame->end_of_stream; + + *bytes_recv = rx_size; + + if (rx_size < 0) + { + // Error + fprintf(stderr, "Receiving data error. rc:%d\n", rx_size); + ni_decoder_frame_buffer_free(&(p_out_data->data.frame)); + rc = NI_RETCODE_FAILURE; + LRETURN; + } else if (rx_size > 0) + { + number_of_frames++; + ni_log(NI_LOG_DEBUG, + "Got frame # %" PRIu64 " rx_size %d, p_out_frame->data_len[0] " + "%d, p_out_frame->data_len[1] %d, " + "p_out_frame->data_len[2] %d, sum %d\n", + p_dec_ctx->frame_num, rx_size, p_out_frame->data_len[0], + p_out_frame->data_len[1], p_out_frame->data_len[2], + p_out_frame->data_len[0] + p_out_frame->data_len[1] + + p_out_frame->data_len[2]); + } + // rx_size == 0 means no decoded frame is available now + + *total_bytes_recieved += rx_size; + + //TODO: If this a BUG?? we have already updated the *total_bytes_recieved above + if (write_to_file) + { + *total_bytes_recieved += rx_size; + } + +#if 0 + for(i=0;idata_len[i] > 0) + { + ni_log(NI_LOG_DEBUG, "decoder_receive_data: writing data size=%d, %d\n", p_out_frame->data_len[i], i); + fwrite(p_out_frame->p_data[i], p_out_frame->data_len[i], 1, p_file); + if (fflush(p_file)) + { + ni_log(NI_LOG_ERROR, "decoder_receive_data_buf Writing data frame flush failed! errno %d\n", errno); + } + *total_bytes_recieved += p_out_frame->data_len[i]; + } + } +#endif + + ni_log(NI_LOG_DEBUG, "decoder_receive_data_buf 003\n"); + + /* + if (print_time) + { + ni_log(NI_LOG_DEBUG, "[R] Got:%d Frames= %ul fps=%lu Total bytes %llu\n", + rx_size, number_of_frames, (unsigned long) (number_of_frames/(current_time.tv_sec - start_time.tv_sec)), (unsigned long long) *total_bytes_recieved); + } +*/ + if (end_flag) + { + ni_log(NI_LOG_DEBUG, "Receiving done.\n"); + p_device_state->dec_eos_received = 1; + rc = 1; + } else if (0 == rx_size) + { + rc = 2; + } + + ni_log(NI_LOG_DEBUG, "decoder_receive_data: success rc %d\n", rc); + + END; + + return rc; +} + +WORD32 ifwh264d_set_num_cores(iv_obj_t *dec_hdl, void *pv_api_ip, + void *pv_api_op); + +WORD32 ifwh264d_get_vui_params(iv_obj_t *dec_hdl, void *pv_api_ip, + void *pv_api_op); + +void ifwh264d_fill_output_struct_from_context(dec_struct_t *ps_dec, + ivd_video_decode_op_t *ps_dec_op); + +static IV_API_CALL_STATUS_T +api_check_struct_sanity(iv_obj_t *ps_handle, void *pv_api_ip, void *pv_api_op) +{ + IVD_API_COMMAND_TYPE_T e_cmd; + UWORD32 *pu4_api_ip; + UWORD32 *pu4_api_op; + + if (NULL == pv_api_op) + return (IV_FAIL); + + if (NULL == pv_api_ip) + return (IV_FAIL); + + pu4_api_ip = (UWORD32 *)pv_api_ip; + pu4_api_op = (UWORD32 *)pv_api_op; + e_cmd = *(pu4_api_ip + 1); + + /* error checks on handle */ + ni_log(NI_LOG_DEBUG, "ifwh264d: api_check_struct_sanity e_cmd: %d", e_cmd); + + switch ((WORD32)e_cmd) + { + case IVD_CMD_CREATE: + break; + case IVD_CMD_FWCHECK: + break; + + case IVD_CMD_VIDEO_DECODE: + case IVD_CMD_DELETE: + case IVD_CMD_VIDEO_CTL: + if (ps_handle == NULL) + { + *(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM; + *(pu4_api_op + 1) |= IVD_HANDLE_NULL; + return IV_FAIL; + } + + if (ps_handle->u4_size != sizeof(iv_obj_t)) + { + *(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM; + *(pu4_api_op + 1) |= IVD_HANDLE_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + + if (ps_handle->pv_fxns != ifwh264d_api_function) + { + *(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM; + *(pu4_api_op + 1) |= IVD_INVALID_HANDLE_NULL; + return IV_FAIL; + } + + if (ps_handle->pv_codec_handle == NULL) + { + *(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM; + *(pu4_api_op + 1) |= IVD_INVALID_HANDLE_NULL; + return IV_FAIL; + } + break; + default: + *(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM; + *(pu4_api_op + 1) |= IVD_INVALID_API_CMD; + return IV_FAIL; + } + + switch ((WORD32)e_cmd) + { + case IVD_CMD_CREATE: + { + ifwh264d_create_ip_t *ps_ip = (ifwh264d_create_ip_t *)pv_api_ip; + ifwh264d_create_op_t *ps_op = (ifwh264d_create_op_t *)pv_api_op; + + ps_op->s_ivd_create_op_t.u4_error_code = 0; + + if ((ps_ip->s_ivd_create_ip_t.u4_size > + sizeof(ifwh264d_create_ip_t)) || + (ps_ip->s_ivd_create_ip_t.u4_size < sizeof(ivd_create_ip_t))) + { + ps_op->s_ivd_create_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_create_op_t.u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + ni_log(NI_LOG_DEBUG, "\n"); + return (IV_FAIL); + } + + if ((ps_op->s_ivd_create_op_t.u4_size != + sizeof(ifwh264d_create_op_t)) && + (ps_op->s_ivd_create_op_t.u4_size != sizeof(ivd_create_op_t))) + { + ps_op->s_ivd_create_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_create_op_t.u4_error_code |= + IVD_OP_API_STRUCT_SIZE_INCORRECT; + ni_log(NI_LOG_DEBUG, "\n"); + return (IV_FAIL); + } + + if ((ps_ip->s_ivd_create_ip_t.e_output_format != IV_YUV_420P) && + (ps_ip->s_ivd_create_ip_t.e_output_format != IV_YUV_422ILE) && + (ps_ip->s_ivd_create_ip_t.e_output_format != IV_RGB_565) && + (ps_ip->s_ivd_create_ip_t.e_output_format != IV_YUV_420SP_UV) && + (ps_ip->s_ivd_create_ip_t.e_output_format != IV_YUV_420SP_VU)) + { + ps_op->s_ivd_create_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_create_op_t.u4_error_code |= + IVD_INIT_DEC_COL_FMT_NOT_SUPPORTED; + ni_log(NI_LOG_DEBUG, "\n"); + return (IV_FAIL); + } + } + break; + + case IVD_CMD_FWCHECK: + { + ifwh264d_fwcheck_ip_t *ps_ip = (ifwh264d_fwcheck_ip_t *)pv_api_ip; + ifwh264d_fwcheck_op_t *ps_op = (ifwh264d_fwcheck_op_t *)pv_api_op; + + ps_op->s_ivd_fwcheck_op_t.u4_error_code = 0; + + if (ps_ip->s_ivd_fwcheck_ip_t.u4_size != + sizeof(ifwh264d_fwcheck_ip_t)) + { + ps_op->s_ivd_fwcheck_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_fwcheck_op_t.u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + return (IV_FAIL); + } + + if (ps_op->s_ivd_fwcheck_op_t.u4_size != + sizeof(ifwh264d_fwcheck_op_t)) + { + ps_op->s_ivd_fwcheck_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_fwcheck_op_t.u4_error_code |= + IVD_OP_API_STRUCT_SIZE_INCORRECT; + return (IV_FAIL); + } + } + break; + + case IVD_CMD_VIDEO_DECODE: + { + ifwh264d_video_decode_ip_t *ps_ip = + (ifwh264d_video_decode_ip_t *)pv_api_ip; + ifwh264d_video_decode_op_t *ps_op = + (ifwh264d_video_decode_op_t *)pv_api_op; + + ni_log(NI_LOG_DEBUG, "The input bytes is: %d", + ps_ip->s_ivd_video_decode_ip_t.u4_num_Bytes); + ps_op->s_ivd_video_decode_op_t.u4_error_code = 0; + + if (ps_ip->s_ivd_video_decode_ip_t.u4_size != + sizeof(ifwh264d_video_decode_ip_t) && + ps_ip->s_ivd_video_decode_ip_t.u4_size != + offsetof(ivd_video_decode_ip_t, s_out_buffer)) + { + ps_op->s_ivd_video_decode_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_video_decode_op_t.u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + return (IV_FAIL); + } + + if (ps_op->s_ivd_video_decode_op_t.u4_size != + sizeof(ifwh264d_video_decode_op_t) && + ps_op->s_ivd_video_decode_op_t.u4_size != + offsetof(ivd_video_decode_op_t, u4_output_present)) + { + ps_op->s_ivd_video_decode_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_video_decode_op_t.u4_error_code |= + IVD_OP_API_STRUCT_SIZE_INCORRECT; + return (IV_FAIL); + } + } + break; + + case IVD_CMD_DELETE: + { + ifwh264d_delete_ip_t *ps_ip = (ifwh264d_delete_ip_t *)pv_api_ip; + ifwh264d_delete_op_t *ps_op = (ifwh264d_delete_op_t *)pv_api_op; + + ps_op->s_ivd_delete_op_t.u4_error_code = 0; + + if (ps_ip->s_ivd_delete_ip_t.u4_size != + sizeof(ifwh264d_delete_ip_t)) + { + ps_op->s_ivd_delete_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_delete_op_t.u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + return (IV_FAIL); + } + + if (ps_op->s_ivd_delete_op_t.u4_size != + sizeof(ifwh264d_delete_op_t)) + { + ps_op->s_ivd_delete_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_delete_op_t.u4_error_code |= + IVD_OP_API_STRUCT_SIZE_INCORRECT; + return (IV_FAIL); + } + } + break; + + case IVD_CMD_VIDEO_CTL: + { + UWORD32 *pu4_ptr_cmd; + UWORD32 sub_command; + + pu4_ptr_cmd = (UWORD32 *)pv_api_ip; + pu4_ptr_cmd += 2; + sub_command = *pu4_ptr_cmd; + + switch (sub_command) + { + case IVD_CMD_CTL_SETPARAMS: + { + ih264d_ctl_set_config_ip_t *ps_ip; + ih264d_ctl_set_config_op_t *ps_op; + ps_ip = (ih264d_ctl_set_config_ip_t *)pv_api_ip; + ps_op = (ih264d_ctl_set_config_op_t *)pv_api_op; + + if (ps_ip->s_ivd_ctl_set_config_ip_t.u4_size != + sizeof(ih264d_ctl_set_config_ip_t)) + { + ps_op->s_ivd_ctl_set_config_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_ctl_set_config_op_t.u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + } + break; + + case IVD_CMD_CTL_GETVERSION: + { + ih264d_ctl_getversioninfo_ip_t *ps_ip; + ih264d_ctl_getversioninfo_op_t *ps_op; + ps_ip = (ih264d_ctl_getversioninfo_ip_t *)pv_api_ip; + ps_op = (ih264d_ctl_getversioninfo_op_t *)pv_api_op; + if (ps_ip->s_ivd_ctl_getversioninfo_ip_t.u4_size != + sizeof(ih264d_ctl_getversioninfo_ip_t)) + { + ps_op->s_ivd_ctl_getversioninfo_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_ctl_getversioninfo_op_t.u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + if (ps_op->s_ivd_ctl_getversioninfo_op_t.u4_size != + sizeof(ih264d_ctl_getversioninfo_op_t)) + { + ps_op->s_ivd_ctl_getversioninfo_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_ctl_getversioninfo_op_t.u4_error_code |= + IVD_OP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + } + break; + + case IVD_CMD_CTL_FLUSH: + { + ih264d_ctl_flush_ip_t *ps_ip; + ih264d_ctl_flush_op_t *ps_op; + ps_ip = (ih264d_ctl_flush_ip_t *)pv_api_ip; + ps_op = (ih264d_ctl_flush_op_t *)pv_api_op; + if (ps_ip->s_ivd_ctl_flush_ip_t.u4_size != + sizeof(ih264d_ctl_flush_ip_t)) + { + ps_op->s_ivd_ctl_flush_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_ctl_flush_op_t.u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + if (ps_op->s_ivd_ctl_flush_op_t.u4_size != + sizeof(ih264d_ctl_flush_op_t)) + { + ps_op->s_ivd_ctl_flush_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_ctl_flush_op_t.u4_error_code |= + IVD_OP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + } + break; + + case IVD_CMD_CTL_RESET: + { + ih264d_ctl_reset_ip_t *ps_ip; + ih264d_ctl_reset_op_t *ps_op; + ps_ip = (ih264d_ctl_reset_ip_t *)pv_api_ip; + ps_op = (ih264d_ctl_reset_op_t *)pv_api_op; + if (ps_ip->s_ivd_ctl_reset_ip_t.u4_size != + sizeof(ih264d_ctl_reset_ip_t)) + { + ps_op->s_ivd_ctl_reset_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_ctl_reset_op_t.u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + if (ps_op->s_ivd_ctl_reset_op_t.u4_size != + sizeof(ih264d_ctl_reset_op_t)) + { + ps_op->s_ivd_ctl_reset_op_t.u4_error_code |= 1 + << IVD_UNSUPPORTEDPARAM; + ps_op->s_ivd_ctl_reset_op_t.u4_error_code |= + IVD_OP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + break; + } + + case IH264D_CMD_CTL_GET_VUI_PARAMS: + { + ih264d_ctl_get_vui_params_ip_t *ps_ip; + ih264d_ctl_get_vui_params_op_t *ps_op; + + ps_ip = (ih264d_ctl_get_vui_params_ip_t *)pv_api_ip; + ps_op = (ih264d_ctl_get_vui_params_op_t *)pv_api_op; + + if (ps_ip->u4_size != + sizeof(ih264d_ctl_get_vui_params_ip_t)) + { + ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; + ps_op->u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + + if (ps_op->u4_size != + sizeof(ih264d_ctl_get_vui_params_op_t)) + { + ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; + ps_op->u4_error_code |= + IVD_OP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + + break; + } + case IFWH264D_CMD_CTL_SET_NUM_CORES: + { + ifwh264d_ctl_set_num_cores_ip_t *ps_ip; + ifwh264d_ctl_set_num_cores_op_t *ps_op; + + ps_ip = (ifwh264d_ctl_set_num_cores_ip_t *)pv_api_ip; + ps_op = (ifwh264d_ctl_set_num_cores_op_t *)pv_api_op; + + if (ps_ip->u4_size != + sizeof(ifwh264d_ctl_set_num_cores_ip_t)) + { + ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; + ps_op->u4_error_code |= + IVD_IP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + + if (ps_op->u4_size != + sizeof(ifwh264d_ctl_set_num_cores_op_t)) + { + ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; + ps_op->u4_error_code |= + IVD_OP_API_STRUCT_SIZE_INCORRECT; + return IV_FAIL; + } + + if ((ps_ip->u4_num_cores != 1) && + (ps_ip->u4_num_cores != 2) && + (ps_ip->u4_num_cores != 3) && + (ps_ip->u4_num_cores != 4)) + { + ps_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; + return IV_FAIL; + } + break; + } + default: + *(pu4_api_op + 1) |= 1 << IVD_UNSUPPORTEDPARAM; + *(pu4_api_op + 1) |= IVD_UNSUPPORTED_API_CMD; + return IV_FAIL; + break; + } + } + break; + } + + return IV_SUCCESS; +} + +/************************************************************************** + * \if Function name : ifwh264d_init_decoder \endif + * + * + * \brief + * Initializes the decoder + * + * \param apiVersion : Version of the api being used. + * \param errorHandlingMechanism : Mechanism to be used for errror handling. + * \param postFilteringType: Type of post filtering operation to be used. + * \param uc_outputFormat: Format of the decoded picture [default 4:2:0]. + * \param uc_dispBufs: Number of Display Buffers. + * \param p_NALBufAPI: Pointer to NAL Buffer API. + * \param p_DispBufAPI: Pointer to Display Buffer API. + * \param ih264d_dec_mem_manager :Pointer to the function that will be called by decoder + * for memory allocation and freeing. + * + * \return + * 0 on Success and -1 on error + * + ************************************************************************** + */ +void ifwh264d_init_decoder(void *ps_dec_params) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_init_decoder"); + + char value[PROPERTY_VALUE_MAX]; + property_get(PROP_DECODER_LOGLEVEL, value, "3"); + unsigned loglevel = atoi(value); + ni_log(NI_LOG_DEBUG, "ifwh264d: AVC decoder using %s, hw_id %d\n", + PROP_DECODER_LOGLEVEL, loglevel); + if (loglevel > NI_LOG_TRACE) + { + loglevel = NI_LOG_TRACE; + } + ni_log_set_level(loglevel); + + ni_log(NI_LOG_DEBUG, "ifwh264d: ni_log_get_level: %d", ni_log_get_level()); + + dec_struct_t *ps_dec = (dec_struct_t *)ps_dec_params; + + /* decParams Initializations */ + ps_dec->u4_app_disp_width = 0; + ps_dec->i4_header_decoded = 0; + ps_dec->u4_total_frames_decoded = 0; + + ps_dec->i4_error_code = 0; + ps_dec->i4_content_type = -1; + + ps_dec->u2_pic_ht = ps_dec->u2_pic_wd = 0; + + /* Set the cropping parameters as zero */ + ps_dec->u2_crop_offset_y = 0; + ps_dec->u2_crop_offset_uv = 0; + + /* The Initial Frame Rate Info is not Present */ + ps_dec->i4_vui_frame_rate = -1; + ps_dec->i4_pic_type = -1; + ps_dec->i4_frametype = -1; + + ps_dec->u1_res_changed = 0; + + /* Initializing flush frame u4_flag */ + ps_dec->u1_flushfrm = 0; + ps_dec->u1_resetfrm = 0; + + XcodecDecStruct *xcodec_dec = ps_dec->xcodec_dec; + + ni_device_session_context_init(&(xcodec_dec->dec_ctx)); + xcodec_dec->dec_ctx.codec_format = NI_CODEC_FORMAT_H264; + xcodec_dec->dec_ctx.bit_depth_factor = 1; + xcodec_dec->dec_ctx.keep_alive_timeout = 10; + + xcodec_dec->sdPara.p_dec_ctx = (void *)&(xcodec_dec->dec_ctx); + xcodec_dec->rcPara.p_dec_ctx = (void *)&(xcodec_dec->dec_ctx); + + ni_log(NI_LOG_DEBUG, + "ifwh264d: ifwh264d_init_decoder xcodec_dec->input_video_width %d, " + "xcodec_dec->input_video_height %d", + xcodec_dec->input_video_width, xcodec_dec->input_video_height); + + if (ni_decoder_init_default_params(&(xcodec_dec->api_param_dec), 25, 1, + 200000, xcodec_dec->input_video_width, + xcodec_dec->input_video_height) < 0) + { + ni_log(NI_LOG_DEBUG, "ni_decoder_init_default_params failure !\n"); + + return; + } + + ni_log(NI_LOG_DEBUG, "ni_decoder_init_default_params success !\n"); + + memset(value, 0, PROPERTY_VALUE_MAX); + property_get(PROP_DECODER_HW_ID, value, 0); + unsigned hw_id = atoi(value); + ni_log(NI_LOG_DEBUG, "AVC decoder using %s, hw_id %d\n", PROP_DECODER_HW_ID, + hw_id); + if (hw_id > 32) + { + ni_log(NI_LOG_ERROR, "Error card hw_id %d!!!!!!!!!!!!!!!!!!!\n", hw_id); + hw_id = 0; + } + + xcodec_dec->dec_ctx.hw_id = hw_id; + + // default: 8 bit, little endian + xcodec_dec->dec_ctx.p_session_config = &(xcodec_dec->api_param_dec); + xcodec_dec->dec_ctx.src_bit_depth = 8; + xcodec_dec->dec_ctx.src_endian = NI_FRAME_LITTLE_ENDIAN; + + int err = + ni_device_session_open(&(xcodec_dec->dec_ctx), NI_DEVICE_TYPE_DECODER); + if (err < 0) + { + ni_log(NI_LOG_DEBUG, "ni_decoder_session_open failure !\n"); + return; + } + + ni_log(NI_LOG_DEBUG, "ni_device_session_open success !\n"); + + xcodec_dec->sos_flag = 1; + xcodec_dec->edFlag = 0; + xcodec_dec->bytes_sent = 0; + xcodec_dec->bytes_recv = 0; + xcodec_dec->total_bytes_recieved = 0; + xcodec_dec->xcodeRecvTotal = 0; + xcodec_dec->total_bytes_sent = 0; + + if (xcodec_dec->input_video_width == 0 || + xcodec_dec->input_video_height == 0) + { + xcodec_dec->input_video_width = 1280; + xcodec_dec->input_video_height = 720; + } + + xcodec_dec->output_video_width = xcodec_dec->input_video_width; + xcodec_dec->output_video_height = xcodec_dec->input_video_height; + + memset(&(xcodec_dec->in_pkt), 0, sizeof(ni_session_data_io_t)); + memset(&(xcodec_dec->out_frame), 0, sizeof(ni_session_data_io_t)); + + ps_dec->u1_frame_decoded_flag = 0; + + ps_dec->init_done = 1; +} + +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_create */ +/* */ +/* Description : creates decoder */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ +WORD32 ifwh264d_allocate_static_bufs(iv_obj_t **dec_hdl, void *pv_api_ip, + void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_allocate_static_bufs"); + + ifwh264d_create_ip_t *ps_create_ip; + ifwh264d_create_op_t *ps_create_op; + void *pv_buf; + dec_struct_t *ps_dec; + void *(*pf_aligned_alloc)(void *pv_mem_ctxt, WORD32 alignment, WORD32 size); + void (*pf_aligned_free)(void *pv_mem_ctxt, void *pv_buf); + void *pv_mem_ctxt; + + if ((NULL == dec_hdl) || (NULL == pv_api_ip) || (NULL == pv_api_op)) + { + return IV_FAIL; + } + + ps_create_ip = (ifwh264d_create_ip_t *)pv_api_ip; + ps_create_op = (ifwh264d_create_op_t *)pv_api_op; + + ps_create_op->s_ivd_create_op_t.u4_error_code = 0; + + pf_aligned_alloc = ps_create_ip->s_ivd_create_ip_t.pf_aligned_alloc; + pf_aligned_free = ps_create_ip->s_ivd_create_ip_t.pf_aligned_free; + pv_mem_ctxt = ps_create_ip->s_ivd_create_ip_t.pv_mem_ctxt; + + /* Initialize return handle to NULL */ + ps_create_op->s_ivd_create_op_t.pv_handle = NULL; + pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, sizeof(iv_obj_t)); + //RETURN_IF((NULL == pv_buf), IV_FAIL); + if (NULL == pv_buf) + { + return IV_FAIL; + } + *dec_hdl = (iv_obj_t *)pv_buf; + ps_create_op->s_ivd_create_op_t.pv_handle = *dec_hdl; + + (*dec_hdl)->pv_codec_handle = NULL; + pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, sizeof(dec_struct_t)); + //RETURN_IF((NULL == pv_buf), IV_FAIL); + if (NULL == pv_buf) + { + return IV_FAIL; + } + (*dec_hdl)->pv_codec_handle = (dec_struct_t *)pv_buf; + + ps_dec = (dec_struct_t *)pv_buf; + memset(ps_dec, 0, sizeof(dec_struct_t)); + + ps_dec->pf_aligned_alloc = pf_aligned_alloc; + ps_dec->pf_aligned_free = pf_aligned_free; + ps_dec->pv_mem_ctxt = pv_mem_ctxt; + + pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, sizeof(XcodecDecStruct)); + RETURN_IF((NULL == pv_buf), IV_FAIL); + if (NULL == pv_buf) + { + return IV_FAIL; + } + ps_dec->xcodec_dec = pv_buf; + + return IV_SUCCESS; +} + +WORD32 ifwh264d_free_static_bufs(iv_obj_t *dec_hdl) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_free_static_bufs"); + dec_struct_t *ps_dec; + + void (*pf_aligned_free)(void *pv_mem_ctxt, void *pv_buf); + void *pv_mem_ctxt; + + ps_dec = (dec_struct_t *)dec_hdl->pv_codec_handle; + pf_aligned_free = ps_dec->pf_aligned_free; + pv_mem_ctxt = ps_dec->pv_mem_ctxt; + + PS_DEC_ALIGNED_FREE(ps_dec, ps_dec->xcodec_dec); + + PS_DEC_ALIGNED_FREE(ps_dec, dec_hdl->pv_codec_handle); + + if (dec_hdl) + { + pf_aligned_free(pv_mem_ctxt, dec_hdl); + } + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_free_static_bufs end"); + return IV_SUCCESS; +} + +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_create */ +/* */ +/* Description : creates decoder */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ +WORD32 ifwh264d_create(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_create"); + + ifwh264d_create_ip_t *ps_create_ip; + ifwh264d_create_op_t *ps_create_op; + + WORD32 ret; + + ps_create_ip = (ifwh264d_create_ip_t *)pv_api_ip; + ps_create_op = (ifwh264d_create_op_t *)pv_api_op; + + ps_create_op->s_ivd_create_op_t.u4_error_code = 0; + dec_hdl = NULL; + ret = ifwh264d_allocate_static_bufs(&dec_hdl, pv_api_ip, pv_api_op); + + /* If allocation of some buffer fails, then free buffers allocated till then */ + if (IV_FAIL == ret) + { + if (dec_hdl) + { + if (dec_hdl->pv_codec_handle) + { + ifwh264d_free_static_bufs(dec_hdl); + } else + { + void (*pf_aligned_free)(void *pv_mem_ctxt, void *pv_buf); + void *pv_mem_ctxt; + + pf_aligned_free = + ps_create_ip->s_ivd_create_ip_t.pf_aligned_free; + pv_mem_ctxt = ps_create_ip->s_ivd_create_ip_t.pv_mem_ctxt; + pf_aligned_free(pv_mem_ctxt, dec_hdl); + } + } + //ps_create_op->s_ivd_create_op_t.u4_error_code = IVD_MEM_ALLOC_FAILED; + ps_create_op->s_ivd_create_op_t.u4_error_code = 1 << IVD_FATALERROR; + + return IV_FAIL; + } + + if (send_dump != 0) + { + pIn_file = fopen(mInFile, "ab"); + if (pIn_file == NULL) + { + ni_log(NI_LOG_ERROR, "ERROR: Cannot open mInFile\n"); + } + } + + if (receive_dump != 0) + { + p_file = fopen(mdecoderFile, "ab"); + if (p_file == NULL) + { + ni_log(NI_LOG_ERROR, "ERROR: Cannot open mdecoderFile\n"); + } + } + + //FW_CREATE_DUMP_FILE(mInFile); + + return IV_SUCCESS; +} + +UWORD32 ifwh264d_get_outbuf_size(WORD32 pic_wd, UWORD32 pic_ht, + UWORD8 u1_chroma_format, UWORD32 *p_buf_size) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_get_outbuf_size"); + + UWORD32 u4_min_num_out_bufs = 0; + + if (u1_chroma_format == IV_YUV_420P) + u4_min_num_out_bufs = MIN_OUT_BUFS_420; + else if (u1_chroma_format == IV_YUV_422ILE) + u4_min_num_out_bufs = MIN_OUT_BUFS_422ILE; + else if (u1_chroma_format == IV_RGB_565) + u4_min_num_out_bufs = MIN_OUT_BUFS_RGB565; + else if ((u1_chroma_format == IV_YUV_420SP_UV) || + (u1_chroma_format == IV_YUV_420SP_VU)) + u4_min_num_out_bufs = MIN_OUT_BUFS_420SP; + + if (u1_chroma_format == IV_YUV_420P) + { + p_buf_size[0] = (pic_wd * pic_ht); + p_buf_size[1] = (pic_wd * pic_ht) >> 2; + p_buf_size[2] = (pic_wd * pic_ht) >> 2; + } else if (u1_chroma_format == IV_YUV_422ILE) + { + p_buf_size[0] = (pic_wd * pic_ht) * 2; + p_buf_size[1] = p_buf_size[2] = 0; + } else if (u1_chroma_format == IV_RGB_565) + { + p_buf_size[0] = (pic_wd * pic_ht) * 2; + p_buf_size[1] = p_buf_size[2] = 0; + } else if ((u1_chroma_format == IV_YUV_420SP_UV) || + (u1_chroma_format == IV_YUV_420SP_VU)) + { + p_buf_size[0] = (pic_wd * pic_ht); + p_buf_size[1] = (pic_wd * pic_ht) >> 1; + p_buf_size[2] = 0; + } + + return u4_min_num_out_bufs; +} + +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_video_decode */ +/* */ +/* Description : handle video decode API command */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ + +WORD32 ifwh264d_video_decode(iv_obj_t *dec_hdl, void *pv_api_ip, + void *pv_api_op) +{ + /* ! */ + + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_video_decode"); + + dec_struct_t *ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle); + + UWORD8 *pu1_buf = NULL; + device_state_t xcodeState = {0}; + + UWORD32 u4_next_is_aud; + WORD32 api_ret_value = IV_SUCCESS; + WORD32 header_data_left = 0, frame_data_left = 0; + ivd_video_decode_ip_t *ps_dec_ip; + ivd_video_decode_op_t *ps_dec_op; + + ps_dec_ip = (ivd_video_decode_ip_t *)pv_api_ip; + ps_dec_op = (ivd_video_decode_op_t *)pv_api_op; + + { + UWORD32 u4_size; + u4_size = ps_dec_op->u4_size; + memset(ps_dec_op, 0, sizeof(ivd_video_decode_op_t)); + ps_dec_op->u4_size = u4_size; + } + + ps_dec_op->u4_num_bytes_consumed = 0; + + ps_dec->u4_ts = ps_dec_ip->u4_ts; + ps_dec_op->u4_error_code = 0; + ps_dec_op->u4_output_present = ps_dec->u4_output_present = 0; + ps_dec_op->u4_frame_decoded_flag = 0; + //ps_dec_op->u4_output_present = ps_dec->u4_output_present = 1; + + XcodecDecStruct *xcodec_dec = ps_dec->xcodec_dec; + + int output_video_width = xcodec_dec->input_video_width; + int output_video_height = xcodec_dec->input_video_height; + + /* In case the deocder is not in flush mode(in shared mode), + then decoder has to pick up a buffer to write current frame. + Check if a frame is available in such cases */ + + ni_log(NI_LOG_DEBUG, + "ifwh264d_video_decode ps_dec_ip->u4_num_Bytes: %d, " + "ps_dec_op->u4_num_bytes_consumed: %d\n", + ps_dec_ip->u4_num_Bytes, ps_dec_op->u4_num_bytes_consumed); + + send_fin_flag = 0; + recieve_fin_flag = 0; + xcodec_dec->bytes_recv = 0; + + (void)gettimeofday(¤t_time, NULL); + + int flush_enable = ps_dec->u1_flushfrm; + do + { + pu1_buf = (UWORD8 *)ps_dec_ip->pv_stream_buffer + + ps_dec_op->u4_num_bytes_consumed; + + UWORD32 u4_max_ofst = + ps_dec_ip->u4_num_Bytes - ps_dec_op->u4_num_bytes_consumed; + + (void)gettimeofday(¤t_time, NULL); + int print_time = ((current_time.tv_sec - previous_time.tv_sec) > 1); + + if (ps_dec->u1_resetfrm == 0 && ps_dec_ip->u4_num_Bytes == 0) + { + ni_log(NI_LOG_DEBUG, + "ifwh264d_video_decode ps_dec_ip->u4_num_Bytes: %d\n", + ps_dec_ip->u4_num_Bytes); + } else + { + //FW_DUMP_TO_FILE(mInFile, pu1_buf, ps_dec_ip->u4_num_Bytes, 0); + + // Sending + send_fin_flag = decoder_send_data_buf( + &xcodec_dec->dec_ctx, &xcodec_dec->in_pkt, xcodec_dec->sos_flag, + xcodec_dec->input_video_width, xcodec_dec->input_video_height, + pIn_file, pu1_buf, ps_dec_ip->u4_num_Bytes, u4_max_ofst, + &xcodec_dec->total_bytes_sent, print_time, send_dump, + &xcodeState); + xcodec_dec->sos_flag = 0; + if (send_fin_flag < 0) //Error + { + ni_log(NI_LOG_ERROR, + "Error: decoder_send_data failed, rc: %d\n", + send_fin_flag); + break; + } + + /* If dynamic bitstream buffer is not allocated and + * header decode is done, then allocate dynamic bitstream buffer + */ + } + + ps_dec_op->u4_num_bytes_consumed = ps_dec_ip->u4_num_Bytes; + + u4_next_is_aud = 0; + + header_data_left = + ((ps_dec->i4_decode_header == 1) && + (ps_dec->i4_header_decoded != 3) && + (ps_dec_op->u4_num_bytes_consumed < ps_dec_ip->u4_num_Bytes)); + frame_data_left = + (((ps_dec->i4_decode_header == 0) && + ((ps_dec->u1_pic_decode_done == 0) || (u4_next_is_aud == 1))) && + (ps_dec_op->u4_num_bytes_consumed < ps_dec_ip->u4_num_Bytes)); + + if (flush_enable) + { + frame_data_left = 1; + } + + ps_dec->ps_out_buffer = NULL; + + if (ps_dec_ip->u4_size >= offsetof(ivd_video_decode_ip_t, s_out_buffer)) + ps_dec->ps_out_buffer = &ps_dec_ip->s_out_buffer; + + ni_log(NI_LOG_DEBUG, "ifwh264d_video_decode 000\n"); + // Receiving + recieve_fin_flag = decoder_receive_data_buf( + &xcodec_dec->dec_ctx, &xcodec_dec->out_frame, output_video_width, + output_video_height, p_file, &xcodec_dec->bytes_recv, + &xcodec_dec->total_bytes_recieved, print_time, receive_dump, + &xcodeState); + + ni_log(NI_LOG_DEBUG, "ifwh264d_video_decode 001 recieve_fin_flag %d\n", + recieve_fin_flag); + if (print_time) + { + previous_time = current_time; + } + + if (recieve_fin_flag < 0 || + xcodec_dec->out_frame.data.frame.end_of_stream) //Error or eos + { + break; + } + + ni_log(NI_LOG_DEBUG, + "ifwh264d_video_decode 003 xcodec_dec->bytes_recv %d, Y %d, U " + "%d, V %d\n", + xcodec_dec->bytes_recv, + xcodec_dec->out_frame.data.frame.data_len[0], + xcodec_dec->out_frame.data.frame.data_len[1], + xcodec_dec->out_frame.data.frame.data_len[2]); +#if 1 + ps_dec->ps_out_buffer->u4_num_bufs_size = xcodec_dec->bytes_recv; + if (xcodec_dec->bytes_recv > 0) + { + int i, j; + ni_session_context_t *p_dec_ctx = &xcodec_dec->dec_ctx; + ni_session_data_io_t *p_out_data = &xcodec_dec->out_frame; + ni_frame_t *p_out_frame = &(p_out_data->data.frame); + for (i = 0; i < 3; i++) + { + uint8_t *src = p_out_frame->p_data[i]; + uint8_t *dst = ps_dec->ps_out_buffer->pu1_bufs[i]; + int plane_height = p_dec_ctx->active_video_height; + int plane_width = p_dec_ctx->active_video_width; + int write_height = output_video_height; + int write_width = output_video_width; + + // support for 8/10 bit depth + write_width *= p_dec_ctx->bit_depth_factor; + + if (i == 1 || i == 2) + { + plane_height /= 2; + plane_width = (((int)(p_dec_ctx->actual_video_width) / 2 * + p_dec_ctx->bit_depth_factor + + 127) / + 128) * + 128; + write_height /= 2; + write_width /= 2; + } + + // apply the cropping windown in writing out the YUV frame + // for now the windown is usually crop-left = crop-top = 0, and we use + // this to simplify the cropping logic + for (j = 0; j < plane_height; j++) + { + if (j < write_height) + { + memcpy(dst, src, write_width); + dst += write_width; + p_out_frame->data_len[i] += write_width; + } + src += plane_width; + } + } + + if (flush_enable) + { + flush_enable = 0; + } + + //memcpy(ps_dec->ps_out_buffer->pu1_bufs[0], xcodec_dec->out_frame.data.frame.p_data[0], xcodec_dec->out_frame.data.frame.data_len[0]); + //memcpy(ps_dec->ps_out_buffer->pu1_bufs[1], xcodec_dec->out_frame.data.frame.p_data[1], xcodec_dec->out_frame.data.frame.data_len[1]); + //memcpy(ps_dec->ps_out_buffer->pu1_bufs[2], xcodec_dec->out_frame.data.frame.p_data[2], xcodec_dec->out_frame.data.frame.data_len[2]); + + ps_dec_op->u4_ts = ps_dec->u4_ts; + ps_dec_op->u4_output_present = ps_dec->u4_output_present = 1; + } + + ni_log(NI_LOG_DEBUG, + "ifwh264d_video_decode 004 after padding xcodec_dec->bytes_recv " + "%d, Y %d, U %d, V %d\n", + xcodec_dec->bytes_recv, + xcodec_dec->out_frame.data.frame.data_len[0], + xcodec_dec->out_frame.data.frame.data_len[1], + xcodec_dec->out_frame.data.frame.data_len[2]); + + ni_decoder_frame_buffer_free(&(xcodec_dec->out_frame.data.frame)); + +#endif + +#if 0 + + UWORD32 i; + int x, y; + static int frameNumb = 0; + for(i = 0; i < ps_dec->ps_out_buffer->u4_num_bufs; i++) + { + if(ps_dec->ps_out_buffer->pu1_bufs[i] == NULL) + { + ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; + ps_dec_op->u4_error_code |= IVD_DISP_FRM_OP_BUF_NULL; + return IV_FAIL; + } + + if(ps_dec->ps_out_buffer->u4_min_out_buf_size[i] == 0) + { + ps_dec_op->u4_error_code |= 1 << IVD_UNSUPPORTEDPARAM; + ps_dec_op->u4_error_code |= + IVD_DISP_FRM_ZERO_OP_BUF_SIZE; + return IV_FAIL; + } + + if(i == 0){ + for (y = 0; y < output_video_height; y++) { + for (x = 0; x < output_video_width; x++) { + ps_dec->ps_out_buffer->pu1_bufs[i][y * output_video_width + x] = x + y + frameNumb * 3; + } + } + }else{ + for (y = 0; y < output_video_height/2; y++) { + for (x = 0; x < output_video_width/2; x++) { + ps_dec->ps_out_buffer->pu1_bufs[i][y * output_video_width/2 + x] = 128 + y + frameNumb * 2; + ps_dec->ps_out_buffer->pu1_bufs[i][y * output_video_width/2 + x] = 64 + x + frameNumb * 5; + } + } + } + } + + ps_dec_op->u4_ts = ps_dec->u4_ts; + ps_dec_op->u4_output_present = ps_dec->u4_output_present = 1; + + frameNumb++; + if(frameNumb == 25){ + frameNumb = 0; + } +#endif + + } while ((header_data_left == 1) || (frame_data_left == 1)); + + ifwh264d_fill_output_struct_from_context(ps_dec, ps_dec_op); + + ni_log(NI_LOG_DEBUG, + "ifwh264d_video_decode The num bytes consumed: %d, " + "ps_dec_op->u4_output_present %d\n", + ps_dec_op->u4_num_bytes_consumed, ps_dec_op->u4_output_present); + return api_ret_value; +} + +WORD32 ifwh264d_get_version(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_get_version"); + + char version_string[MAXVERSION_STRLEN + 1]; + UWORD32 version_string_len; + + ivd_ctl_getversioninfo_ip_t *ps_ip; + ivd_ctl_getversioninfo_op_t *ps_op; + + ps_ip = (ivd_ctl_getversioninfo_ip_t *)pv_api_ip; + ps_op = (ivd_ctl_getversioninfo_op_t *)pv_api_op; + + ps_op->u4_error_code = IV_SUCCESS; + + VERSION(version_string, CODEC_NAME, CODEC_RELEASE_TYPE, CODEC_RELEASE_VER, + CODEC_VENDOR); + + if ((WORD32)ps_ip->u4_version_buffer_size <= 0) + { + return (IV_FAIL); + } + + version_string_len = strnlen(version_string, MAXVERSION_STRLEN) + 1; + + if (ps_ip->u4_version_buffer_size >= + version_string_len) //(WORD32)sizeof(sizeof(version_string))) + { + memcpy(ps_ip->pv_version_buffer, version_string, version_string_len); + ps_op->u4_error_code = IV_SUCCESS; + } else + { + return IV_FAIL; + } + + return (IV_SUCCESS); +} + +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_fwcheck */ +/* */ +/* Description : */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Globals : */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ +WORD32 ifwh264d_fwcheck(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_fwcheck"); + + //ifwh264d_fwcheck_ip_t *ps_ip = (ifwh264d_fwcheck_ip_t *)pv_api_ip; + ifwh264d_fwcheck_op_t *ps_op = (ifwh264d_fwcheck_op_t *)pv_api_op; + + ps_op->s_ivd_fwcheck_op_t.u4_error_code = 0; + + char value[PROPERTY_VALUE_MAX]; + memset(value, 0, PROPERTY_VALUE_MAX); + property_get(PROP_DECODER_HW_ID, value, 0); + unsigned hw_id = atoi(value); + ni_log(NI_LOG_DEBUG, "AVC decoder using %s, hw_id %d\n", PROP_DECODER_HW_ID, + hw_id); + if (hw_id > 32) + { + ni_log(NI_LOG_ERROR, "Error card hw_id %d!!!!!!!!!!!!!!!!!!!\n", hw_id); + hw_id = 0; + } + + if (ni_rsrc_check_hw_available(hw_id, NI_DEVICE_TYPE_DECODER) == + NI_RETCODE_SUCCESS) + { + ni_log(NI_LOG_DEBUG, "Find netint devices %d", hw_id); + ps_op->s_ivd_fwcheck_op_t.u4_fw_status = 1; + } else + { + ni_log(NI_LOG_ERROR, "Failed to find netint device %d", hw_id); + ps_op->s_ivd_fwcheck_op_t.u4_fw_status = 0; + } + + return IV_SUCCESS; +} + +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_set_flush_mode */ +/* */ +/* Description : */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Globals : */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ +WORD32 ifwh264d_set_flush_mode(iv_obj_t *dec_hdl, void *pv_api_ip, + void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_set_flush_mode"); + + dec_struct_t *ps_dec; + ivd_ctl_flush_op_t *ps_ctl_op = (ivd_ctl_flush_op_t *)pv_api_op; + ps_ctl_op->u4_error_code = 0; + + ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle); + /* ! */ + /* Signal flush frame control call */ + ps_dec->u1_flushfrm = 1; + + ni_device_session_flush(&ps_dec->xcodec_dec->dec_ctx, + NI_DEVICE_TYPE_DECODER); + + return IV_SUCCESS; +} + +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_set_params */ +/* */ +/* Description : */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ +WORD32 ifwh264d_set_params(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_set_params"); + + dec_struct_t *ps_dec; + WORD32 ret = IV_SUCCESS; + + if ((NULL == dec_hdl) || (NULL == pv_api_ip) || (NULL == pv_api_op)) + { + return IV_FAIL; + } + + ivd_ctl_set_config_ip_t *ps_ctl_ip = (ivd_ctl_set_config_ip_t *)pv_api_ip; + ivd_ctl_set_config_op_t *ps_ctl_op = (ivd_ctl_set_config_op_t *)pv_api_op; + + ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle); + if (NULL == ps_dec) + { + return IV_FAIL; + } + + ps_ctl_op->u4_error_code = 0; + + ps_dec->i4_app_skip_mode = ps_ctl_ip->e_frm_skip_mode; + + /*Is it really supported test it when you so the corner testing using test app*/ + + ni_log(NI_LOG_DEBUG, + "ifwh264d: ifwh264d_set_params 000 ps_ctl_ip->u4_disp_ht %d, " + "ps_ctl_ip->u4_disp_wd %d", + ps_ctl_ip->u4_disp_ht, ps_ctl_ip->u4_disp_wd); + + if (ps_ctl_ip->u4_disp_ht != 0) + { + ps_dec->u4_app_disp_height = ps_ctl_ip->u4_disp_ht; + } + + if (ps_ctl_ip->u4_disp_wd != 0) + { + ps_dec->u4_app_disp_width = ps_ctl_ip->u4_disp_wd; + } else + { + /* + * Set the display width to zero. This will ensure that the wrong value we had stored (0xFFFFFFFF) + * does not propogate. + */ + ps_dec->u4_app_disp_width = 0; + ps_ctl_op->u4_error_code |= (1 << IVD_UNSUPPORTEDPARAM); + ps_ctl_op->u4_error_code |= ERROR_DISP_WIDTH_INVALID; + ret = IV_FAIL; + } + + ps_dec->xcodec_dec->input_video_width = ps_dec->u4_app_disp_width; + ps_dec->xcodec_dec->input_video_height = ps_dec->u4_app_disp_height; + + ni_log(NI_LOG_DEBUG, + "ifwh264d: ifwh264d_set_params 001 ps_dec->u4_app_disp_width %d, " + "ps_dec->u4_app_disp_height %d", + ps_dec->u4_app_disp_width, ps_dec->u4_app_disp_height); + + if (ps_ctl_ip->e_vid_dec_mode == IVD_DECODE_FRAME) + ps_dec->i4_decode_header = 0; + else if (ps_ctl_ip->e_vid_dec_mode == IVD_DECODE_HEADER) + ps_dec->i4_decode_header = 1; + else + { + ps_ctl_op->u4_error_code = (1 << IVD_UNSUPPORTEDPARAM); + ps_dec->i4_decode_header = 1; + ret = IV_FAIL; + } + //ps_dec->e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + + if ((ps_ctl_ip->e_frm_out_mode != IVD_DECODE_FRAME_OUT) && + (ps_ctl_ip->e_frm_out_mode != IVD_DISPLAY_FRAME_OUT)) + { + ps_ctl_op->u4_error_code = (1 << IVD_UNSUPPORTEDPARAM); + ret = IV_FAIL; + } + ps_dec->e_frm_out_mode = ps_ctl_ip->e_frm_out_mode; + + //dec_struct_t * ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle); + + { + ifwh264d_init_decoder(ps_dec); + } + + return ret; +} + +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_set_default_params */ +/* */ +/* Description : */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 08 08 2011 100421 Copied from set_params */ +/* */ +/*****************************************************************************/ +WORD32 ifwh264d_set_default_params(iv_obj_t *dec_hdl, void *pv_api_ip, + void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_set_default_params"); + + WORD32 ret = IV_SUCCESS; + + ivd_ctl_set_config_op_t *ps_ctl_op = (ivd_ctl_set_config_op_t *)pv_api_op; + + { + ps_ctl_op->u4_error_code = 0; + } + + return ret; +} +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_delete */ +/* */ +/* Description : */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Globals : */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ +WORD32 ifwh264d_delete(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_delete"); + + if (pIn_file) + fclose(pIn_file); + + if (p_file) + fclose(p_file); + + //ifwh264d_delete_ip_t *ps_ip = (ifwh264d_delete_ip_t *)pv_api_ip; + ifwh264d_delete_op_t *ps_op = (ifwh264d_delete_op_t *)pv_api_op; + dec_struct_t *ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle); + if (ps_dec != NULL) + { + if (ps_dec->u1_flushfrm) + { + ps_dec->u4_output_present = 0; + } + XcodecDecStruct *xcodec_dec = ps_dec->xcodec_dec; + + ni_device_session_close(&(xcodec_dec->dec_ctx), 1, + NI_DEVICE_TYPE_DECODER); + + ni_packet_buffer_free(&(xcodec_dec->in_pkt.data.packet)); + ni_decoder_frame_buffer_free(&(xcodec_dec->out_frame.data.frame)); + } + + ps_op->s_ivd_delete_op_t.u4_error_code = 0; + ifwh264d_free_static_bufs(dec_hdl); + return IV_SUCCESS; +} +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_reset */ +/* */ +/* Description : */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Globals : */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ +WORD32 ifwh264d_reset(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_reset"); + + ivd_ctl_reset_op_t *ps_ctl_op = (ivd_ctl_reset_op_t *)pv_api_op; + ps_ctl_op->u4_error_code = 0; + + dec_struct_t *ps_dec = (dec_struct_t *)(dec_hdl->pv_codec_handle); + ps_dec->u1_resetfrm = 1; + + return IV_SUCCESS; +} + +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_ctl */ +/* */ +/* Description : */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ +WORD32 ifwh264d_ctl(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op) +{ + ivd_ctl_set_config_ip_t *ps_ctl_ip; + ivd_ctl_set_config_op_t *ps_ctl_op; + WORD32 ret = IV_SUCCESS; + UWORD32 subcommand; + + ps_ctl_ip = (ivd_ctl_set_config_ip_t *)pv_api_ip; + ps_ctl_op = (ivd_ctl_set_config_op_t *)pv_api_op; + ps_ctl_op->u4_error_code = 0; + subcommand = ps_ctl_ip->e_sub_cmd; + + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_ctl subcommand %d", subcommand); + + switch (subcommand) + { + case IVD_CMD_CTL_SETPARAMS: + ret = ifwh264d_set_params(dec_hdl, (void *)pv_api_ip, + (void *)pv_api_op); + break; + case IVD_CMD_CTL_RESET: + ret = ifwh264d_reset(dec_hdl, (void *)pv_api_ip, (void *)pv_api_op); + break; + + case IVD_CMD_CTL_FLUSH: + ret = ifwh264d_set_flush_mode(dec_hdl, (void *)pv_api_ip, + (void *)pv_api_op); + break; + case IVD_CMD_CTL_GETVERSION: + ret = ifwh264d_get_version(dec_hdl, (void *)pv_api_ip, + (void *)pv_api_op); + break; + case IH264D_CMD_CTL_GET_VUI_PARAMS: + ret = ifwh264d_get_vui_params(dec_hdl, (void *)pv_api_ip, + (void *)pv_api_op); + break; + case IFWH264D_CMD_CTL_SET_NUM_CORES: + ret = ifwh264d_set_num_cores(dec_hdl, (void *)pv_api_ip, + (void *)pv_api_op); + break; + default: + ni_log(NI_LOG_DEBUG, "\ndo nothing\n"); + break; + } + + return ret; +} + +WORD32 ifwh264d_set_num_cores(iv_obj_t *dec_hdl, void *pv_api_ip, + void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_set_num_cores"); + + ifwh264d_ctl_set_num_cores_ip_t *ps_ip; + ifwh264d_ctl_set_num_cores_op_t *ps_op; + dec_struct_t *ps_dec = dec_hdl->pv_codec_handle; + + ps_ip = (ifwh264d_ctl_set_num_cores_ip_t *)pv_api_ip; + ps_op = (ifwh264d_ctl_set_num_cores_op_t *)pv_api_op; + ps_op->u4_error_code = 0; + ps_dec->u4_num_cores = ps_ip->u4_num_cores; + if (ps_dec->u4_num_cores == 1) + { + ps_dec->u1_separate_parse = 0; + } else + { + ps_dec->u1_separate_parse = 1; + } + + /*using only upto three threads currently*/ + if (ps_dec->u4_num_cores > 3) + ps_dec->u4_num_cores = 3; + + return IV_SUCCESS; +} + +WORD32 ifwh264d_get_vui_params(iv_obj_t *dec_hdl, void *pv_api_ip, + void *pv_api_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_get_vui_params"); + + ih264d_ctl_get_vui_params_ip_t *ps_ip; + ih264d_ctl_get_vui_params_op_t *ps_op; + //dec_struct_t *ps_dec = dec_hdl->pv_codec_handle; + //dec_seq_params_t *ps_sps; + //vui_t *ps_vui; + UWORD32 u4_size; + + ps_ip = (ih264d_ctl_get_vui_params_ip_t *)pv_api_ip; + ps_op = (ih264d_ctl_get_vui_params_op_t *)pv_api_op; + UNUSED(ps_ip); + + u4_size = ps_op->u4_size; + memset(ps_op, 0, sizeof(ih264d_ctl_get_vui_params_op_t)); + ps_op->u4_size = u4_size; + + ps_op->u1_aspect_ratio_idc = 1; + ps_op->u2_sar_width = 1; + ps_op->u2_sar_height = 1; + ps_op->u1_overscan_appropriate_flag = 1; + ps_op->u1_video_format = 1; + ps_op->u1_video_full_range_flag = 1; + ps_op->u1_colour_primaries = 1; + ps_op->u1_tfr_chars = 1; + ps_op->u1_matrix_coeffs = 1; + ps_op->u1_cr_top_field = 1; + ps_op->u1_cr_bottom_field = 1; + ps_op->u4_num_units_in_tick = 1; + ps_op->u4_time_scale = 1; + ps_op->u1_fixed_frame_rate_flag = 1; + ps_op->u1_nal_hrd_params_present = 1; + ps_op->u1_vcl_hrd_params_present = 1; + ps_op->u1_low_delay_hrd_flag = 1; + ps_op->u1_pic_struct_present_flag = 1; + ps_op->u1_bitstream_restriction_flag = 1; + ps_op->u1_mv_over_pic_boundaries_flag = 1; + ps_op->u4_max_bytes_per_pic_denom = 1; + ps_op->u4_max_bits_per_mb_denom = 1; + ps_op->u4_log2_max_mv_length_horz = 1; + ps_op->u4_log2_max_mv_length_vert = 1; + ps_op->u4_num_reorder_frames = 1; + ps_op->u4_max_dec_frame_buffering = 1; + + ni_log(NI_LOG_DEBUG, + "ifwh264d_get_vui_params = ps_op->u1_colour_primaries %d\n", + ps_op->u1_colour_primaries); + ni_log(NI_LOG_DEBUG, "ifwh264d_get_vui_params = ps_op->u1_tfr_chars %d\n", + ps_op->u1_tfr_chars); + ni_log(NI_LOG_DEBUG, + "ifwh264d_get_vui_params = ps_op->u1_matrix_coeffs %d\n", + ps_op->u1_matrix_coeffs); + ni_log(NI_LOG_DEBUG, + "ifwh264d_get_vui_params = ps_op->u1_video_full_range_flag %d\n", + ps_op->u1_video_full_range_flag); + + return IV_SUCCESS; +} + +void ifwh264d_fill_output_struct_from_context(dec_struct_t *ps_dec, + ivd_video_decode_op_t *ps_dec_op) +{ + ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_fill_output_struct_from_context"); + + if ((ps_dec_op->u4_error_code & 0xff) != + ERROR_DYNAMIC_RESOLUTION_NOT_SUPPORTED) + { + ps_dec_op->u4_pic_wd = (UWORD32)ps_dec->u2_disp_width; + ps_dec_op->u4_pic_ht = (UWORD32)ps_dec->u2_disp_height; + } + + ps_dec_op->u4_new_seq = 0; + ps_dec_op->u4_output_present = ps_dec->u4_output_present; + ps_dec_op->u4_progressive_frame_flag = + ps_dec->s_disp_op.u4_progressive_frame_flag; + + ps_dec_op->u4_is_ref_flag = 1; + + ps_dec_op->e_output_format = ps_dec->s_disp_op.e_output_format; + ps_dec_op->s_disp_frm_buf = ps_dec->s_disp_op.s_disp_frm_buf; + ps_dec_op->e4_fld_type = ps_dec->s_disp_op.e4_fld_type; + ps_dec_op->u4_ts = ps_dec->s_disp_op.u4_ts; + ps_dec_op->u4_disp_buf_id = ps_dec->s_disp_op.u4_disp_buf_id; +} + +/*****************************************************************************/ +/* */ +/* Function Name : ifwh264d_api_function */ +/* */ +/* Description : */ +/* */ +/* Inputs :iv_obj_t decoder handle */ +/* :pv_api_ip pointer to input structure */ +/* :pv_api_op pointer to output structure */ +/* Outputs : */ +/* Returns : void */ +/* */ +/* Issues : none */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 22 10 2008 100356 Draft */ +/* */ +/*****************************************************************************/ +IV_API_CALL_STATUS_T ifwh264d_api_function(iv_obj_t *dec_hdl, void *pv_api_ip, + void *pv_api_op) +{ + UWORD32 command; + UWORD32 *pu2_ptr_cmd; + UWORD32 u4_api_ret; + IV_API_CALL_STATUS_T e_status; + e_status = api_check_struct_sanity(dec_hdl, pv_api_ip, pv_api_op); + + if (e_status != IV_SUCCESS) + { + UWORD32 *ptr_err; + + ptr_err = (UWORD32 *)pv_api_op; + ni_log(NI_LOG_DEBUG, "error code = %d\n", *(ptr_err + 1)); + return IV_FAIL; + } + + pu2_ptr_cmd = (UWORD32 *)pv_api_ip; + pu2_ptr_cmd++; + + command = *pu2_ptr_cmd; + //ni_log(NI_LOG_DEBUG, "ifwh264d: ifwh264d_api_function command: %d\n",command); + + switch (command) + { + case IVD_CMD_CREATE: + u4_api_ret = + ifwh264d_create(dec_hdl, (void *)pv_api_ip, (void *)pv_api_op); + ni_log(NI_LOG_DEBUG, "ifwh264d_create u4_api_ret = %d\n", + u4_api_ret); + break; + + case IVD_CMD_FWCHECK: + u4_api_ret = + ifwh264d_fwcheck(dec_hdl, (void *)pv_api_ip, (void *)pv_api_op); + ni_log(NI_LOG_DEBUG, "ifwh264d_fwcheck u4_api_ret = %d\n", + u4_api_ret); + break; + + case IVD_CMD_DELETE: + u4_api_ret = + ifwh264d_delete(dec_hdl, (void *)pv_api_ip, (void *)pv_api_op); + ni_log(NI_LOG_DEBUG, "ifwh264d_delete u4_api_ret = %d\n", + u4_api_ret); + break; + + case IVD_CMD_VIDEO_DECODE: + u4_api_ret = ifwh264d_video_decode(dec_hdl, (void *)pv_api_ip, + (void *)pv_api_op); + break; + + case IVD_CMD_VIDEO_CTL: + u4_api_ret = + ifwh264d_ctl(dec_hdl, (void *)pv_api_ip, (void *)pv_api_op); + break; + default: + u4_api_ret = IV_FAIL; + break; + } + + return u4_api_ret; +} diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_debug.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_debug.h new file mode 100755 index 00000000..8d67256d --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_debug.h @@ -0,0 +1,139 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +#ifndef _IH264D_DEBUG_H_ +#define _IH264D_DEBUG_H_ + +#define DEBUG_DEC + +/*! + ************************************************************************** + * \file ih264d_debug.h + * + * \brief + * Contains declarations used for debugging + * + * \date + * 2/12/2002 + * + * \author AI + ************************************************************************** + */ +#ifdef DEBUG_DEC +#define H264_DEC_DEBUG_PRINT(...) \ + printf("\n[H264_DEBUG] %s/%d:: ", __FUNCTION__, __LINE__); \ + printf(__VA_ARGS__) +#else //DEBUG_DEC +#define H264_DEC_DEBUG_PRINT(...) \ + { \ + } +#endif //DEBUG_DEC +#define STRENGTH_DEBLOCKING 0 //sanjeev +#define DEBUG_RECONSTRUCT_LUMA 0 +#define DEBUG_RECONSTRUCT_CHROMA 0 + +#define DEBUG_IDCT 0 +#define DEBUG_LUMA_IDCT 0 +#define DEBUG_REF_IDCT 0 + +#define BIN_BIT_RATIO 0 +#define MB_PART_HIST 0 + +#define MB_INTRA_PREDICTION 1 + +#ifdef WIN32 +#define CHK_PURIFY 0 +#else +#define CHK_PURIFY 0 +#endif + +#if MB_INTRA_PREDICTION +#define MB_INTRA_CHROMA_PREDICTION_ON 1 +#define MB_INTRA_4x4_PREDICTION_ON 1 +#define MB_INTRA_16x16_PREDICTION_ON 1 +#endif + +#define TRACE 0 +#define DEBUG_CABAC 0 +#define DEBUG_ABS_MVD 0 +#define DEBUG_INTRA_PRED_MODES 0 +#define DEBUG_DEBLOCKING 0 + +#define COPYTHECONTEXT(s, val) +#define PRINT_TRACE +#define PRINT_TRACE_CAB +#define SWITCHOFFTRACE +#define SWITCHONTRACE +#define SWITCHOFFTRACECABAC +#define SWITCHONTRACECABAC + +#define INC_BIN_COUNT(ps_cab_env) +#define INC_DECISION_BINS(ps_cab_env) +#define INC_BYPASS_BINS(ps_cab_env) +#define INC_SYM_COUNT(ps_cab_env) +#define PRINT_BIN_BIT_RATIO(ps_dec) +#define RESET_BIN_COUNTS(ps_cab_env) + +#ifdef PROFILE_DIS_DEBLK +#define PROFILE_DISABLE_DEBLK() return; +#else +#define PROFILE_DISABLE_DEBLK() ; +#endif + +#ifdef PROFILE_DIS_IQ_IT_RECON +#define PROFILE_DISABLE_IQ_IT_RECON() if (0) +#define PROFILE_DISABLE_IQ_IT_RECON_RETURN() return; +#else +#define PROFILE_DISABLE_IQ_IT_RECON() ; +#define PROFILE_DISABLE_IQ_IT_RECON_RETURN() ; +#endif + +#ifdef PROFILE_DIS_INTRA_PRED +#define PROFILE_DISABLE_INTRA_PRED() if (0) +#else +#define PROFILE_DISABLE_INTRA_PRED() ; +#endif + +#ifdef PROFILE_DIS_UNPACK +#define PROFILE_DISABLE_UNPACK_LUMA() return 0; +#define PROFILE_DISABLE_UNPACK_CHROMA() return; +#else +#define PROFILE_DISABLE_UNPACK_LUMA() ; +#define PROFILE_DISABLE_UNPACK_CHROMA() ; +#endif + +#ifdef PROFILE_DIS_INTER_PRED +#define PROFILE_DISABLE_INTER_PRED() return; +#else +#define PROFILE_DISABLE_INTER_PRED() ; +#endif + +#ifdef PROFILE_DIS_BOUNDARY_STRENGTH +#define PROFILE_DISABLE_BOUNDARY_STRENGTH() return; +#else +#define PROFILE_DISABLE_BOUNDARY_STRENGTH() ; +#endif + +#ifdef PROFILE_DIS_MB_PART_INFO +#define PROFILE_DISABLE_MB_PART_INFO() return 0; +#else +#define PROFILE_DISABLE_MB_PART_INFO() ; +#endif + +#endif /* _IH264D_DEBUG_H_ */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_defs.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_defs.h new file mode 100755 index 00000000..baf95f40 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_defs.h @@ -0,0 +1,611 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +#ifndef _IH264D_DEFS_H_ +#define _IH264D_DEFS_H_ + +/** + ************************************************************************ + * \file ih264d_defs.h + * + * \brief + * Type definitions used in the code + * + * \date + * 19/11/2002 + * + * \author Sriram Sethuraman + * + ************************************************************************ + */ +#define H264_MAX_FRAME_WIDTH 4080 +#define H264_MAX_FRAME_HEIGHT 4080 +#define H264_MAX_FRAME_SIZE (4096 * 2048) + +#define H264_MIN_FRAME_WIDTH 16 +#define H264_MIN_FRAME_HEIGHT 16 + +#define FMT_CONV_NUM_ROWS 16 + +/** Bit manipulation macros */ +#define CHECKBIT(a, i) ((a) & (1 << i)) +#define CLEARBIT(a, i) ((a) &= ~(1 << i)) + +/** Macro to convert a integer to a boolean value */ +#define BOOLEAN(x) (!!(x)) + +/** Arithmetic operations */ +#define MOD(x, y) ((x) % (y)) +#define DIV(x, y) ((x) / (y)) +#define MUL(x, y) ((x) * (y)) +#define SIGN_POW2_DIV(x, y) (((x) < 0) ? (-((-(x)) >> (y))) : ((x) >> (y))) + +#define MB_ENABLE_FILTERING 0x00 +#define MB_DISABLE_FILTERING 0x01 +#define MB_DISABLE_TOP_EDGE 0x02 +#define MB_DISABLE_LEFT_EDGE 0x04 + +/** Maximum number of reference pics */ +#define MAX_REF_BUFS 32 +#define MAX_DISP_BUFS_NEW 64 +#define MAX_FRAMES 16 + +#define INVALID_FRAME_NUM 0x0fffffff +#define GAP_FRAME_NUM 0x1fffffff + +/** macros for reference picture lists, refIdx to POC mapping */ +// 1 extra entry into reference picture lists for refIdx = -1. +// this entry is always 0. this saves conditional checks in +// FillBs modules. +#define POC_LIST_L0_TO_L1_DIFF ((2 * MAX_FRAMES) + 1) +#define POC_LIST_L0_TO_L1_DIFF_1 ((MAX_FRAMES) + 1) + +#define FRM_LIST_L0 0 //0 +#define FRM_LIST_L1 \ + 1 * POC_LIST_L0_TO_L1_DIFF //FRM_LIST_L0 + POC_LIST_L0_TO_L1_DIFF //0+33 //(1 * POC_LIST_L0_TO_L1_DIFF) +#define TOP_LIST_FLD_L0 \ + 2 * POC_LIST_L0_TO_L1_DIFF //FRM_LIST_L1 + POC_LIST_L0_TO_L1_DIFF //0+33+33 //(2 * POC_LIST_L0_TO_L1_DIFF) +#define TOP_LIST_FLD_L1 \ + 3 * POC_LIST_L0_TO_L1_DIFF //TOP_LIST_FLD_L0 + POC_LIST_L0_TO_L1_DIFF_1 //0+33+33+17 //(3 * POC_LIST_L0_TO_L1_DIFF) +#define BOT_LIST_FLD_L0 \ + 4 * POC_LIST_L0_TO_L1_DIFF //TOP_LIST_FLD_L1 + POC_LIST_L0_TO_L1_DIFF_1 //0+33+33+17+17 +#define BOT_LIST_FLD_L1 \ + 5 * POC_LIST_L0_TO_L1_DIFF //BOT_LIST_FLD_L0 + POC_LIST_L0_TO_L1_DIFF_1 //0+33+33+17+17+17 +#define TOTAL_LIST_ENTRIES \ + 6 * POC_LIST_L0_TO_L1_DIFF //BOT_LIST_FLD_L1 + POC_LIST_L0_TO_L1_DIFF_1 //0+33+33+17+17+17+17 +#define PAD_MV_BANK_ROW 64 +#define OFFSET_MV_BANK_ROW ((PAD_MV_BANK_ROW) >> 1) +#define PAD_PUC_CURNNZ 32 +#define OFFSET_PUC_CURNNZ (PAD_PUC_CURNNZ) +#define PAD_MAP_IDX_POC (1) +#define OFFSET_MAP_IDX_POC (1) + +#define OFFSET_MAP_IDX_POC (1) + +#define NAL_REF_IDC(nal_first_byte) ((nal_first_byte >> 5) & 0x3) +#define NAL_FORBIDDEN_BIT(nal_first_byte) (nal_first_byte >> 7) +#define NAL_UNIT_TYPE(nal_first_byte) (nal_first_byte & 0x1F) + +#define INT_PIC_TYPE_I (0x00) + +#define YIELD_CNT_THRESHOLD 8 + +/* For 420SP */ +#define YUV420SP_FACTOR 2 + +/*To prevent buffer overflow access; in case the size of nal unit is + * greater than the allocated buffer size*/ +#define EXTRA_BS_OFFSET 16 * 16 * 2 + +/** + *************************************************************************** + * Enum to hold various mem records being request + **************************************************************************** + */ +enum +{ + /** + * Codec Object at API level + */ + MEM_REC_IV_OBJ, + + /** + * Codec context + */ + MEM_REC_CODEC, + + /** + * Bitstream buffer which holds emulation prevention removed bytes + */ + MEM_REC_BITSBUF, + + /** + * Buffer to hold coeff data + */ + MEM_REC_COEFF_DATA, + + /** + * Motion vector bank + */ + MEM_REC_MVBANK, + + /** + * Holds mem records passed to the codec. + */ + MEM_REC_BACKUP, + + /** + * Holds SPS + */ + MEM_REC_SPS, + + /** + * Holds PPS + */ + MEM_REC_PPS, + + /** + * Holds Slice Headers + */ + MEM_REC_SLICE_HDR, + + /** + * Holds thread handles + */ + MEM_REC_THREAD_HANDLE, + + /** + * Contains i4_status map indicating parse i4_status per MB basis + */ + MEM_REC_PARSE_MAP, + + /** + * Contains i4_status map indicating processing i4_status per MB basis + */ + MEM_REC_PROC_MAP, + + /** + * Contains slice number info for each MB + */ + + MEM_REC_SLICE_NUM_MAP, + + /** + * Holds dpb manager context + */ + MEM_REC_DPB_MGR, + + /** + * Holds neighbors' info + */ + MEM_REC_NEIGHBOR_INFO, + + /** + * Holds neighbors' info + */ + MEM_REC_PRED_INFO, + + /** + * Holds inter pred inforamation on packed format info + */ + MEM_REC_PRED_INFO_PKD, + /** + * Holds neighbors' info + */ + MEM_REC_MB_INFO, + + /** + * Holds deblock Mb info structure frame level) + */ + MEM_REC_DEBLK_MB_INFO, + + /** + * Holds reference picture buffers in non-shared mode + */ + MEM_REC_REF_PIC, + + /** + * Holds some misc intermediate_buffers + */ + MEM_REC_EXTRA_MEM, + + /** + * Holds some misc intermediate_buffers + */ + MEM_REC_INTERNAL_SCRATCH, + + /** + * Holds some misc intermediate_buffers + */ + MEM_REC_INTERNAL_PERSIST, + + /* holds structures related to picture buffer manager*/ + MEM_REC_PIC_BUF_MGR, + + /*holds structure related to MV buffer manager*/ + MEM_REC_MV_BUF_MGR, + + /** + * Place holder to compute number of memory records. + */ + MEM_REC_CNT + /* Do not add anything below */ +}; + +#ifdef DEBLOCK_THREAD +#define H264_MUTEX_LOCK(lock) ithread_mutex_lock(lock) +#define H264_MUTEX_UNLOCK(lock) ithread_mutex_unlock(lock) +#else //DEBLOCK_THREAD +#define H264_MUTEX_LOCK(lock) +#define H264_MUTEX_UNLOCK(lock) + +#define DEBUG_THREADS_PRINTF(...) +#define DEBUG_PERF_PRINTF(...) + +/** Profile Types*/ +#define BASE_PROFILE_IDC 66 +#define MAIN_PROFILE_IDC 77 +#define EXTENDED_PROFILE_IDC 88 +#define HIGH_PROFILE_IDC 100 + +#define MB_SIZE 16 +#define BLK8x8SIZE 8 +#define BLK_SIZE 4 +#define NUM_BLKS_PER_MB 24 +#define NUM_LUM_BLKS_PER_MB 16 +#define LUM_BLK 0 +#define CHROM_BLK 1 +#define NUM_PELS_IN_MB 64 + +/* Level Types */ +#define H264_LEVEL_1_0 10 +#define H264_LEVEL_1_1 11 +#define H264_LEVEL_1_2 12 +#define H264_LEVEL_1_3 13 +#define H264_LEVEL_2_0 20 +#define H264_LEVEL_2_1 21 +#define H264_LEVEL_2_2 22 +#define H264_LEVEL_3_0 30 +#define H264_LEVEL_3_1 31 +#define H264_LEVEL_3_2 32 +#define H264_LEVEL_4_0 40 +#define H264_LEVEL_4_1 41 +#define H264_LEVEL_4_2 42 +#define H264_LEVEL_5_0 50 +#define H264_LEVEL_5_1 51 + +#define MAX_MBS_LEVEL_51 36864 +#define MAX_MBS_LEVEL_50 22080 +#define MAX_MBS_LEVEL_42 8704 +#define MAX_MBS_LEVEL_41 8192 +#define MAX_MBS_LEVEL_40 8192 +#define MAX_MBS_LEVEL_32 5120 +#define MAX_MBS_LEVEL_31 3600 +#define MAX_MBS_LEVEL_30 1620 +#define MAX_MBS_LEVEL_22 1620 +#define MAX_MBS_LEVEL_21 792 +#define MAX_MBS_LEVEL_20 396 +#define MAX_MBS_LEVEL_13 396 +#define MAX_MBS_LEVEL_12 396 +#define MAX_MBS_LEVEL_11 396 +#define MAX_MBS_LEVEL_10 99 + +/** NAL Types */ +#define SLICE_NAL 1 +#define SLICE_DATA_PARTITION_A_NAL 2 +#define SLICE_DATA_PARTITION_B_NAL 3 +#define SLICE_DATA_PARTITION_C_NAL 4 +#define IDR_SLICE_NAL 5 +#define SEI_NAL 6 +#define SEQ_PARAM_NAL 7 +#define PIC_PARAM_NAL 8 +#define ACCESS_UNIT_DELIMITER_RBSP 9 +#define END_OF_SEQ_RBSP 10 +#define END_OF_STREAM_RBSP 11 +#define FILLER_DATA_NAL 12 + +/** Entropy coding modes */ +#define CAVLC 0 +#define CABAC 1 + +/** Picture Types */ +#define I_PIC 0 +#define IP_PIC 1 +#define IPB_PIC 2 +#define SI_PIC 3 +#define SIP_PIC 4 +#define ISI_PIC 5 +#define ISI_PSP_PIC 6 +#define ALL_PIC 7 + +/* Frame or field picture type */ +#define FRM_PIC 0x00 +#define TOP_FLD 0x01 +#define BOT_FLD 0x02 +#define COMP_FLD_PAIR 0x03 /* TOP_FLD | BOT_FLD */ +#define AFRM_PIC 0x04 +#define TOP_REF 0x08 +#define BOT_REF 0x10 +#define PIC_MASK 0x03 +#define NON_EXISTING 0xff + +/* field picture type for display */ +#define DISP_TOP_FLD 0x00 +#define DISP_BOT_FLD 0x01 + +/** Slice Types */ +#define P_SLICE 0 +#define B_SLICE 1 +#define I_SLICE 2 +#define SP_SLICE 3 +#define SI_SLICE 4 + +/* Definition for picture skip */ +#define SKIP_NONE (0x0) +#define I_SLC_BIT (0x1) +#define P_SLC_BIT (0x2) +#define B_SLC_BIT (0x4) + +/** Macros used for Deblocking */ +#define D_INTER_MB 0 +#define D_INTRA_MB 1 +#define D_PRED_NON_16x16 2 +#define D_B_SLICE 4 +#define D_B_SUBMB 6 //D_B_SLICE | D_PRED_NON_16x16 | D_INTER_MB +#define D_FLD_MB 0x80 + +/** Macros for Cabac checks */ +/** MbType */ +/** |x|x|I_PCM|SKIP| + |S|Inter/Intra|P/B|NON-BD16x16/BD16x16,I16x16/I4x4| */ +#define CAB_INTRA 0x00 /* 0000 00xx */ +#define CAB_INTER 0x04 /* 0000 01xx */ +#define CAB_I4x4 0x00 /* 0000 00x0 */ +#define CAB_I16x16 0x01 /* 0000 00x1 */ +#define CAB_BD16x16 0x04 /* 0000 0100 */ +#define CAB_NON_BD16x16 0x05 /* 0000 0101 */ +#define CAB_P 0x07 /* 0000 0111 */ +#define CAB_SI4x4 0x08 /* 0000 10x0 */ +#define CAB_SI16x16 0x09 /* 0000 10x1 */ +#define CAB_SKIP_MASK 0x10 /* 0001 0000 */ +#define CAB_SKIP 0x10 /* 0001 0000 */ +#define CAB_P_SKIP 0x16 /* 0001 x11x */ +#define CAB_B_SKIP 0x14 /* 0001 x100 */ +#define CAB_BD16x16_MASK 0x07 /* 0000 0111 */ +#define CAB_INTRA_MASK 0x04 /* 0000 0100 */ +#define CAB_I_PCM 0x20 /* 001x xxxx */ + +/**< Binarization types for CABAC */ +/* |x|x|x|x|MSB_FIRST_FLC|FLC|TUNARY|UNARY| */ +#define UNARY 1 +#define TUNARY 2 +#define FLC 4 +#define MSB_FIRST_FLC 12 + +/** Macroblock Types */ +#define I_4x4_MB 0 +#define I_16x16_MB 1 +#define P_MB 2 +#define B_MB 3 +#define SI_MB 4 +#define SP_MB 5 +#define I_PCM_MB 6 + +#define SI4x4_MB 0xFF + +/** Intra luma 16x16 and chroma 8x8 prediction modes */ +#define NUM_INTRA_PRED_MODES 4 +#define VERT 0 +#define HORIZ 1 +#define DC 2 +#define PLANE 3 +#define NOT_VALID -1 +#define DC_DC_DC_DC 0x02020202 /*packed 4 bytes used in Decode Intra Mb*/ + +/** Intra luma 4x4 prediction modes */ +#define NUM_INTRA4x4_PRED_MODES 9 + +/** VERT, HORIZ, DC are applicable to 4x4 as well */ +/** D - Down; U - Up; L - Left; R - Right */ +#define DIAG_DL 3 +#define DIAG_DR 4 +#define VERT_R 5 +#define HORIZ_D 6 +#define VERT_L 7 +#define HORIZ_U 8 + +/** P_MB prediction modes */ +#define NUM_INTER_MB_PRED_MODES 5 +#define PRED_16x16 0 +#define PRED_16x8 1 +#define PRED_8x16 2 +#define PRED_8x8 3 +#define PRED_8x8R0 4 +#define MAGIC_16x16 5 +#define MB_SKIP 255 + +/* P_MB submb modes */ +#define P_L0_8x8 0 +#define P_L0_8x4 1 +#define P_L0_4x8 2 +#define P_L0_4x4 3 + +/* B_MB submb modes */ +#define B_DIRECT_8x8 0 +#define B_L0_8x8 1 +#define B_L1_8x8 2 +#define B_BI_8x8 3 +#define B_L0_8x4 4 +#define B_L0_4x8 5 +#define B_L1_8x4 6 +#define B_L1_4x8 7 +#define B_BI_8x4 8 +#define B_BI_4x8 9 +#define B_L0_4x4 10 +#define B_L1_4x4 11 +#define B_BI_4x4 12 + +/** B_MB prediction modes */ +#define B_8x8 22 +#define PRED_INVALID -1 +#define B_DIRECT 0 +#define PRED_L0 1 +#define PRED_L1 2 +#define BI_PRED 3 +#define B_DIRECT_BI_PRED 23 +#define B_DIRECT_PRED_L0 24 +#define B_DIRECT_PRED_L1 25 +#define B_DIRECT_SPATIAL 26 + +#define B_DIRECT8x8_BI_PRED 13 +#define B_DIRECT8x8_PRED_L0 14 +#define B_DIRECT8x8_PRED_L1 15 + +#define ONE_TO_ONE 0 +#define FRM_TO_FLD 1 +#define FLD_TO_FRM 2 + +/** Inter Sub MB Pred modes */ +#define NUM_INTER_SUBMB_PRED_MODES 4 +#define SUBMB_8x8 0 +#define SUBMB_8x4 1 +#define SUBMB_4x8 2 +#define SUBMB_4x4 3 + +/** Coded Block Pattern - Chroma */ +#define CBPC_ALLZERO 0 +#define CBPC_ACZERO 1 +#define CBPC_NONZERO 2 + +/** Index for accessing the left MB in the MV predictor array */ +#define LEFT 0 +/** Index for accessing the top MB in the MV predictor array */ +#define TOP 1 +/** Index for accessing the top right MB in the MV predictor array */ +#define TOP_R 2 +/** Index for accessing the top Left MB in the MV predictor array */ +#define TOP_L 3 + +/** Maximum number of Sequence Parameter sets */ +#define MAX_NUM_SEQ_PARAMS 32 + +/** Maximum number of Picture Parameter sets */ +#define MAX_NUM_PIC_PARAMS 256 + +#define MASK_ERR_SEQ_SET_ID (0xFFFFFFE0) +#define MASK_ERR_PIC_SET_ID (0xFFFFFF00) + +#define MAX_PIC_ORDER_CNT_TYPE 2 + +#define MAX_BITS_IN_FRAME_NUM 16 +#define MAX_BITS_IN_POC_LSB 16 + +#define H264_MAX_REF_PICS 16 +#define H264_MAX_REF_IDX 32 +#define MAX_WEIGHT_BIPRED_IDC 2 +#define MAX_CABAC_INIT_IDC 2 + +#define H264_DEFAULT_NUM_CORES 1 +#define DEFAULT_SEPARATE_PARSE (H264_DEFAULT_NUM_CORES == 2) ? 1 : 0 + +/** Maximum number of Slice groups */ +#define MAX_NUM_SLICE_GROUPS 8 +#define MAX_NUM_REF_FRAMES_OFFSET 255 + +/** Deblocking modes for a slice */ +#define SLICE_BOUNDARY_DBLK_DISABLED 2 +#define DBLK_DISABLED 1 +#define DBLK_ENABLED 0 +#define MIN_DBLK_FIL_OFF -12 +#define MAX_DBLK_FIL_OFF 12 + +/** Width of the predictor buffers used for MC */ +#define MB_SIZE 16 +#define BLK8x8SIZE 8 +#define BLK_SIZE 4 +#define NUM_BLKS_PER_MB 24 +#define NUM_LUM_BLKS_PER_MB 16 + +#define SUB_BLK_WIDTH 4 +#define SUB_SUB_BLK_SIZE 4 /* 2x2 pixel i4_size */ +#define SUB_BLK_SIZE ((SUB_BLK_WIDTH) * (SUB_BLK_WIDTH)) +#define MB_LUM_SIZE 256 +#define MB_CHROM_SIZE 64 + +/**< Width to pad the luminance frame buff */ +/**< Height to pad the luminance frame buff */ +/**< Width to pad the chrominance frame buff */ +/**< Height to pad the chrominance frame buff */ + +#define PAD_LEN_Y_H 32 +#define PAD_LEN_Y_V 20 +#define PAD_LEN_UV_H 16 +#define PAD_LEN_UV_V 8 + +#define PAD_MV_BANK_ROW 64 + +/**< Maimum u4_ofst by which the Mvs could point outside the frame buffers + horizontally in the left and vertically in the top direction */ +#define MAX_OFFSET_OUTSIDE_X_FRM -20 +#define MAX_OFFSET_OUTSIDE_Y_FRM -20 +#define MAX_OFFSET_OUTSIDE_UV_FRM -8 + +/** UVLC parsing macros */ +#define UEV 1 +#define SEV 2 +#define TEV 3 + +/** Defines for Boolean values */ +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#define UNUSED_FOR_REF 0 +#define IS_SHORT_TERM 1 +#define IS_LONG_TERM 2 + +/** Defines for which field gets displayed first */ +#define MAX_FRAMES 16 +#define INVALID_FRAME_NUM 0x0fffffff +#define DO_NOT_DISP 254 +#define DISP_FLD_FIRST_UNDEF 0 +#define DISP_TOP_FLD_FIRST 1 +#define DISP_BOT_FLD_FIRST 2 + +/** Misc error resilience requirements*/ +#define MASK_LOG2_WEIGHT_DENOM 0xFFFFFFF8 +#define MASK_PRED_WEIGHT_OFFSET 0xFFFFFF00 +#define MAX_REDUNDANT_PIC_CNT 127 + +#endif //DEBLOCK_THREAD + +#define NUM_COEFFS_IN_4x4BLK 16 + +#define MEMSET_16BYTES(pu4_start, value) \ + { \ + memset(pu4_start, value, 16); \ + } + +#define MEMCPY_16BYTES(dst, src) \ + { \ + memcpy(dst, src, 16); \ + } + +#endif /*_IH264D_DEFS_H_*/ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_error_handler.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_error_handler.h new file mode 100755 index 00000000..2c45d8d1 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_error_handler.h @@ -0,0 +1,119 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ + +#ifndef _IH264D_ERROR_HANDLER_H_ +#define _IH264D_ERROR_HANDLER_H_ + +/*! + ************************************************************************* + * \file ih264d_error_handler.h + * + * \brief + * Contains declaration of ih264d_global_error_handler function + * + * \date + * 21/11/2002 + * + * \author AI + ************************************************************************* + */ + +#include "ifwh264_typedefs.h" +#include "ifwh264_macros.h" +#include "ifwh264d_structs.h" + +typedef enum +{ + + ERROR_MEM_ALLOC_ISRAM_T = 0x50, + ERROR_MEM_ALLOC_SDRAM_T = 0x51, + ERROR_BUF_MGR = 0x52, + ERROR_DBP_MANAGER_T = 0x53, + ERROR_GAPS_IN_FRM_NUM = 0x54, + ERROR_UNKNOWN_NAL = 0x55, + ERROR_INV_MB_SLC_GRP_T = 0x56, + ERROR_MULTIPLE_SLC_GRP_T = 0x57, + ERROR_UNKNOWN_LEVEL = 0x58, + ERROR_FEATURE_UNAVAIL = 0x59, + ERROR_NOT_SUPP_RESOLUTION = 0x5A, + ERROR_INVALID_PIC_PARAM = 0x5B, + ERROR_INVALID_SEQ_PARAM = 0x5C, + ERROR_EGC_EXCEED_32_1_T = 0x5D, + ERROR_EGC_EXCEED_32_2_T = 0x5E, + ERROR_INV_RANGE_TEV_T = 0x5F, + ERROR_INV_SLC_TYPE_T = 0x60, + ERROR_UNAVAIL_PICBUF_T = 0x61, + ERROR_UNAVAIL_MVBUF_T = 0x62, + ERROR_UNAVAIL_DISPBUF_T = 0x63, + ERROR_INV_POC_TYPE_T = 0x64, + ERROR_PIC1_NOT_FOUND_T = 0x65, + ERROR_PIC0_NOT_FOUND_T = 0x66, + ERROR_NUM_REF = 0x67, + ERROR_REFIDX_ORDER_T = 0x68, + ERROR_EOB_FLUSHBITS_T = 0x69, + ERROR_EOB_GETBITS_T = 0x6A, + ERROR_EOB_GETBIT_T = 0x6B, + ERROR_EOB_BYPASS_T = 0x6C, + ERROR_EOB_DECISION_T = 0x6D, + ERROR_EOB_TERMINATE_T = 0x6E, + ERROR_EOB_READCOEFF4X4CAB_T = 0x6F, + ERROR_INV_RANGE_QP_T = 0x70, + ERROR_END_OF_FRAME_EXPECTED_T = 0x71, + ERROR_MB_TYPE = 0x72, + ERROR_SUB_MB_TYPE = 0x73, + ERROR_CBP = 0x74, + ERROR_REF_IDX = 0x75, + ERROR_NUM_MV = 0x76, + ERROR_CHROMA_PRED_MODE = 0x77, + ERROR_INTRAPRED = 0x78, + ERROR_NEXT_MB_ADDRESS_T = 0x79, + ERROR_MB_ADDRESS_T = 0x7A, + ERROR_MB_GROUP_ASSGN_T = 0x7B, + ERROR_CAVLC_NUM_COEFF_T = 0x7C, + ERROR_CAVLC_SCAN_POS_T = 0x7D, + ERROR_CABAC_RENORM_T = 0x7E, + ERROR_CABAC_SIG_COEFF1_T = 0x7F, + ERROR_CABAC_SIG_COEFF2_T = 0x80, + ERROR_CABAC_ENCODE_COEFF_T = 0x81, + ERROR_INV_SPS_PPS_T = 0x82, + ERROR_INV_SLICE_HDR_T = 0x83, + ERROR_PRED_WEIGHT_TABLE_T = 0x84, + IH264D_VERS_BUF_INSUFFICIENT = 0x85, + ERROR_ACTUAL_LEVEL_GREATER_THAN_INIT = 0x86, + ERROR_CORRUPTED_SLICE = 0x87, + ERROR_FRAME_LIMIT_OVER = 0x88, + ERROR_ACTUAL_RESOLUTION_GREATER_THAN_INIT = 0x89, + ERROR_PROFILE_NOT_SUPPORTED = 0x8A, + ERROR_DISP_WIDTH_RESET_TO_PIC_WIDTH = 0x8B, + ERROR_DISP_WIDTH_INVALID = 0x8C, + ERROR_DANGLING_FIELD_IN_PIC = 0x8D, + ERROR_DYNAMIC_RESOLUTION_NOT_SUPPORTED = 0x8E, + ERROR_INIT_NOT_DONE = 0x8F, + ERROR_LEVEL_UNSUPPORTED = 0x90, + ERROR_START_CODE_NOT_FOUND = 0x91, + ERROR_PIC_NUM_IS_REPEATED = 0x92, + ERROR_IN_LAST_SLICE_OF_PIC = 0x93, + ERROR_NEW_FRAME_EXPECTED = 0x94, + ERROR_INCOMPLETE_FRAME = 0x95, + ERROR_VUI_PARAMS_NOT_FOUND = 0x96 + +} h264_decoder_error_code_t; + +#endif /* _IH264D_ERROR_HANDLER_H_ */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_structs.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_structs.h new file mode 100755 index 00000000..02322f22 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_structs.h @@ -0,0 +1,169 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +#ifndef _IH264D_STRUCTS_H_ +#define _IH264D_STRUCTS_H_ + +#include "ifwh264d_vui.h" +#include "ni_device_api.h" +#include "ni_rsrc_api.h" +#include "ni_device_test.h" + +struct _DecStruct; + +typedef struct +{ + UWORD8 u1_seq_parameter_set_id; /** id for the seq par set 0-31 */ + UWORD8 u1_is_valid; /** is Seq Param set valid */ + + UWORD16 u2_frm_wd_in_mbs; /** Frame width expressed in MB units */ + UWORD16 u2_frm_ht_in_mbs; /** Frame height expressed in MB units */ + + /* Following are derived from the above two */ + UWORD16 u2_fld_ht_in_mbs; /** Field height expressed in MB units */ + UWORD16 + u2_max_mb_addr; /** Total number of macroblocks in a coded picture */ + UWORD16 + u2_total_num_of_mbs; /** Total number of macroblocks in a coded picture */ + UWORD32 u4_fld_ht; /** field height */ + UWORD32 u4_cwidth; /** chroma width */ + UWORD32 u4_chr_frm_ht; /** chroma height */ + UWORD32 u4_chr_fld_ht; /** chroma field height */ + UWORD8 u1_mb_aff_flag; /** 0 - no mb_aff; 1 - uses mb_aff */ + + UWORD8 u1_profile_idc; /** profile value */ + UWORD8 u1_level_idc; /** level value */ + + /* high profile related syntax elements */ + WORD32 i4_chroma_format_idc; + WORD32 i4_bit_depth_luma_minus8; + WORD32 i4_bit_depth_chroma_minus8; + WORD32 i4_qpprime_y_zero_transform_bypass_flag; + WORD32 i4_seq_scaling_matrix_present_flag; + UWORD8 u1_seq_scaling_list_present_flag[8]; + UWORD8 u1_use_default_scaling_matrix_flag[8]; + WORD16 i2_scalinglist4x4[6][16]; + WORD16 i2_scalinglist8x8[2][64]; + UWORD8 u1_more_than_one_slice_group_allowed_flag; + UWORD8 u1_arbitrary_slice_order_allowed_flag; + UWORD8 u1_redundant_slices_allowed_flag; + UWORD8 u1_bits_in_frm_num; /** Number of bits in frame num */ + UWORD16 u2_u4_max_pic_num_minus1; /** Maximum frame num minus 1 */ + UWORD8 + u1_pic_order_cnt_type; /** 0 - 2 indicates the method to code picture order count */ + UWORD8 u1_log2_max_pic_order_cnt_lsb_minus; + WORD32 i4_max_pic_order_cntLsb; + UWORD8 u1_num_ref_frames_in_pic_order_cnt_cycle; + UWORD8 u1_delta_pic_order_always_zero_flag; + WORD32 i4_ofst_for_non_ref_pic; + WORD32 i4_ofst_for_top_to_bottom_field; + WORD32 i4_ofst_for_ref_frame[MAX_NUM_REF_FRAMES_OFFSET]; + UWORD8 u1_num_ref_frames; + UWORD8 u1_gaps_in_frame_num_value_allowed_flag; + UWORD8 u1_frame_mbs_only_flag; /** 1 - frame only; 0 - field/frame pic */ + UWORD8 u1_direct_8x8_inference_flag; + UWORD8 u1_vui_parameters_present_flag; + vui_t s_vui; +} dec_seq_params_t; + +typedef struct _XcodecDecStruct +{ + int sos_flag, edFlag, bytes_sent, bytes_recv; + unsigned long total_bytes_sent; + unsigned long long total_bytes_recieved; + unsigned long long xcodeRecvTotal; + + ni_session_context_t dec_ctx; + tx_data_t sdPara; + rx_data_t rcPara; + + int input_video_width; + int input_video_height; + int output_video_width; + int output_video_height; + + ni_xcoder_params_t api_param_dec; + + ni_session_data_io_t in_pkt; + ni_session_data_io_t out_frame; + +} XcodecDecStruct; + +/** Aggregating structure that is globally available */ +typedef struct _DecStruct +{ + /* Output format sent by the application */ + dec_seq_params_t *ps_cur_sps; + + UWORD8 u1_chroma_format; + UWORD8 u1_pic_decode_done; + UWORD8 u1_slice_header_done; + WORD32 init_done; + + UWORD32 u4_ts; + UWORD8 u1_flushfrm; + + UWORD8 u1_resetfrm; + + UWORD16 u2_pic_wd; /** Width of the picture being decoded */ + UWORD16 u2_pic_ht; /** Height of the picture being decoded */ + + /* Variables required for cropping */ + UWORD16 u2_disp_width; + UWORD16 u2_disp_height; + UWORD16 u2_crop_offset_y; + UWORD16 u2_crop_offset_uv; + + WORD32 i4_frametype; + UWORD32 u4_output_present; + + WORD32 i4_pic_type; + WORD32 i4_content_type; + WORD32 i4_decode_header; + WORD32 i4_header_decoded; + UWORD32 u4_total_frames_decoded; + + UWORD32 u4_app_disp_width; + UWORD32 u4_app_disp_height; + WORD32 i4_error_code; + + ivd_out_bufdesc_t *ps_out_buffer; + ivd_get_display_frame_op_t s_disp_op; + + WORD32 i4_vui_frame_rate; + + UWORD8 u1_res_changed; + + UWORD8 u1_frame_decoded_flag; + UWORD32 u4_num_cores; + UWORD8 u1_separate_parse; + + WORD32 i4_app_skip_mode; + + IVD_DISPLAY_FRAME_OUT_MODE_T e_frm_out_mode; + + XcodecDecStruct *xcodec_dec; + + void *(*pf_aligned_alloc)(void *pv_mem_ctxt, WORD32 alignment, WORD32 size); + void (*pf_aligned_free)(void *pv_mem_ctxt, void *pv_buf); + void *pv_mem_ctxt; + +} dec_struct_t; + +#endif /* _H264_DEC_STRUCTS_H */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_utils.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_utils.h new file mode 100755 index 00000000..f7f44947 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_utils.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +#ifndef _IFWH264D_UTILS_H_ +#define _IFWH264D_UTILS_H_ +/*! +************************************************************************** +* \file ih264d_utils.h +* +* \brief +* Contains declaration of routines +* that handle of start and end of pic processing +* +* \date +* 19/12/2002 +* +* \author AI +************************************************************************** +*/ +#include "ifwh264d_defs.h" +#include "ifwh264d_structs.h" + +#define PS_DEC_ALIGNED_FREE(ps_dec, y) \ + if (y) \ + { \ + ps_dec->pf_aligned_free(ps_dec->pv_mem_ctxt, ((void *)y)); \ + (y) = NULL; \ + } + +#endif /* _IFWH264D_UTILS_H_ */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_vui.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_vui.h new file mode 100755 index 00000000..cd660dc8 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwh264d_vui.h @@ -0,0 +1,92 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ + +/*****************************************************************************/ +/* */ +/* File Name : ih264d_vui.h */ +/* */ +/* Description : This file contains routines to parse SEI NAL's */ +/* */ +/* List of Functions : */ +/* */ +/* Issues / Problems : None */ +/* */ +/* Revision History : */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 25 05 2005 NS Draft */ +/* */ +/*****************************************************************************/ + +#ifndef _IH264D_VUI_H_ +#define _IH264D_VUI_H_ + +#include "ifwh264_typedefs.h" +#include "ifwh264_macros.h" + +#define VUI_EXTENDED_SAR 255 + +typedef struct +{ + UWORD32 u4_cpb_cnt; + UWORD8 u1_bit_rate_scale; + UWORD8 u1_cpb_size_scale; + UWORD32 u4_bit_rate[32]; + UWORD32 u4_cpb_size[32]; + UWORD8 u1_cbr_flag[32]; + UWORD8 u1_initial_cpb_removal_delay; + UWORD8 u1_cpb_removal_delay_length; + UWORD8 u1_dpb_output_delay_length; + UWORD8 u1_time_offset_length; +} hrd_t; + +typedef struct +{ + UWORD8 u1_aspect_ratio_idc; + UWORD16 u2_sar_width; + UWORD16 u2_sar_height; + UWORD8 u1_overscan_appropriate_flag; + UWORD8 u1_video_format; + UWORD8 u1_video_full_range_flag; + UWORD8 u1_colour_primaries; + UWORD8 u1_tfr_chars; + UWORD8 u1_matrix_coeffs; + UWORD8 u1_cr_top_field; + UWORD8 u1_cr_bottom_field; + UWORD32 u4_num_units_in_tick; + UWORD32 u4_time_scale; + UWORD8 u1_fixed_frame_rate_flag; + UWORD8 u1_nal_hrd_params_present; + hrd_t s_nal_hrd; + UWORD8 u1_vcl_hrd_params_present; + hrd_t s_vcl_hrd; + UWORD8 u1_low_delay_hrd_flag; + UWORD8 u1_pic_struct_present_flag; + UWORD8 u1_bitstream_restriction_flag; + UWORD8 u1_mv_over_pic_boundaries_flag; + UWORD32 u4_max_bytes_per_pic_denom; + UWORD32 u4_max_bits_per_mb_denom; + UWORD32 u4_log2_max_mv_length_horz; + UWORD32 u4_log2_max_mv_length_vert; + UWORD32 u4_num_reorder_frames; + UWORD32 u4_max_dec_frame_buffering; +} vui_t; + +#endif /* _SEI_H_ */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwv.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwv.h new file mode 100755 index 00000000..651fd8ec --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwv.h @@ -0,0 +1,238 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +/** +******************************************************************************* +* @file +* iv.h +* +* @brief +* This file contains all the necessary structure and enumeration +* definitions needed for the Application Program Interface(API) of the +* Ittiam Video and Image codecs +* +* @author +* 100239(RCY) +* +* @par List of Functions: +* +* @remarks +* None +* +******************************************************************************* +*/ + +#ifndef _IV_H +#define _IV_H + +/*****************************************************************************/ +/* Constant Macros */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Typedefs */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Enums */ +/*****************************************************************************/ + +/* IV_API_CALL_STATUS_T:This is only to return the FAIL/PASS status to the */ +/* application for the current API call */ + +typedef enum +{ + IV_STATUS_NA = 0x7FFFFFFF, + IV_SUCCESS = 0x0, + IV_FAIL = 0x1, +} IV_API_CALL_STATUS_T; + +/* IV_COLOR_FORMAT_T: This enumeration lists all the color formats which */ +/* finds usage in video/image codecs */ + +typedef enum +{ + IV_CHROMA_NA = 0x7FFFFFFF, + IV_YUV_420P = 0x1, + IV_YUV_422P = 0x2, + IV_420_UV_INTL = 0x3, + IV_YUV_422IBE = 0x4, + IV_YUV_422ILE = 0x5, + IV_YUV_444P = 0x6, + IV_YUV_411P = 0x7, + IV_GRAY = 0x8, + IV_RGB_565 = 0x9, + IV_RGB_24 = 0xa, + IV_YUV_420SP_UV = 0xb, + IV_YUV_420SP_VU = 0xc, + IV_RGBA_8888 = 0xd +} IV_COLOR_FORMAT_T; + +/* IV_PICTURE_CODING_TYPE_T: VOP/Frame coding type Enumeration */ + +typedef enum +{ + IV_NA_FRAME = 0x7FFFFFFF, + IV_I_FRAME = 0x0, + IV_P_FRAME = 0x1, + IV_B_FRAME = 0x2, + IV_IDR_FRAME = 0x3, + IV_II_FRAME = 0x4, + IV_IP_FRAME = 0x5, + IV_IB_FRAME = 0x6, + IV_PI_FRAME = 0x7, + IV_PP_FRAME = 0x8, + IV_PB_FRAME = 0x9, + IV_BI_FRAME = 0xa, + IV_BP_FRAME = 0xb, + IV_BB_FRAME = 0xc, + IV_MBAFF_I_FRAME = 0xd, + IV_MBAFF_P_FRAME = 0xe, + IV_MBAFF_B_FRAME = 0xf, + IV_MBAFF_IDR_FRAME = 0x10, + IV_NOT_CODED_FRAME = 0x11, + IV_FRAMETYPE_DEFAULT = IV_I_FRAME +} IV_PICTURE_CODING_TYPE_T; + +/* IV_FLD_TYPE_T: field type Enumeration */ + +typedef enum +{ + IV_NA_FLD = 0x7FFFFFFF, + IV_TOP_FLD = 0x0, + IV_BOT_FLD = 0x1, + IV_FLD_TYPE_DEFAULT = IV_TOP_FLD +} IV_FLD_TYPE_T; + +/* IV_CONTENT_TYPE_T: Video content type */ + +typedef enum +{ + IV_CONTENTTYPE_NA = 0x7FFFFFFF, + IV_PROGRESSIVE = 0x0, + IV_INTERLACED = 0x1, + IV_PROGRESSIVE_FRAME = 0x2, + IV_INTERLACED_FRAME = 0x3, + IV_INTERLACED_TOPFIELD = 0x4, + IV_INTERLACED_BOTTOMFIELD = 0x5, + IV_CONTENTTYPE_DEFAULT = IV_PROGRESSIVE, +} IV_CONTENT_TYPE_T; + +/* IV_API_COMMAND_TYPE_T:API command type */ +typedef enum +{ + IV_CMD_NA = 0x7FFFFFFF, + IV_CMD_DUMMY_ELEMENT = 0x4, +} IV_API_COMMAND_TYPE_T; + +/*****************************************************************************/ +/* Structure */ +/*****************************************************************************/ + +/* IV_OBJ_T: This structure defines the handle for the codec instance */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * Pointer to the API function pointer table of the codec + */ + void *pv_fxns; + + /** + * Pointer to the handle of the codec + */ + void *pv_codec_handle; +} iv_obj_t; + +/* IV_YUV_BUF_T: This structure defines attributes for the yuv buffer */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * Pointer to Luma (Y) Buffer + */ + + void *pv_y_buf; + /** + * Pointer to Chroma (Cb) Buffer + */ + void *pv_u_buf; + + /** + * Pointer to Chroma (Cr) Buffer + */ + void *pv_v_buf; + + /** + * Width of the Luma (Y) Buffer + */ + UWORD32 u4_y_wd; + + /** + * Height of the Luma (Y) Buffer + */ + UWORD32 u4_y_ht; + + /** + * Stride/Pitch of the Luma (Y) Buffer + */ + UWORD32 u4_y_strd; + + /** + * Width of the Chroma (Cb) Buffer + */ + UWORD32 u4_u_wd; + + /** + * Height of the Chroma (Cb) Buffer + */ + UWORD32 u4_u_ht; + + /** + * Stride/Pitch of the Chroma (Cb) Buffer + */ + UWORD32 u4_u_strd; + + /** + * Width of the Chroma (Cr) Buffer + */ + UWORD32 u4_v_wd; + + /** + * Height of the Chroma (Cr) Buffer + */ + UWORD32 u4_v_ht; + + /** + * Stride/Pitch of the Chroma (Cr) Buffer + */ + UWORD32 u4_v_strd; +} iv_yuv_buf_t; + +#endif /* _IV_H */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwvd.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwvd.h new file mode 100755 index 00000000..f025d232 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/decoder/ifwvd.h @@ -0,0 +1,1027 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +/** +******************************************************************************* +* @file +* ivd.h +* +* @brief +* This file contains all the necessary structure and enumeration +* definitions needed for the Application Program Interface(API) of the +* Ittiam Video Decoders +* +* @author +* 100239(RCY) +* +* @remarks +* None +* +******************************************************************************* +*/ + +#ifndef _IVD_H +#define _IVD_H + +/*****************************************************************************/ +/* Constant Macros */ +/*****************************************************************************/ +#define IVD_VIDDEC_MAX_IO_BUFFERS 64 +/*****************************************************************************/ +/* Typedefs */ +/*****************************************************************************/ + +/*****************************************************************************/ +/* Enums */ +/*****************************************************************************/ + +/* IVD_ARCH_T: Architecture Enumeration */ +typedef enum +{ + ARCH_NA = 0x7FFFFFFF, + ARCH_ARM_NONEON = 0x0, + ARCH_ARM_A9Q, + ARCH_ARM_A9A, + ARCH_ARM_A9, + ARCH_ARM_A7, + ARCH_ARM_A5, + ARCH_ARM_A15, + ARCH_ARM_NEONINTR, + ARCH_ARMV8_GENERIC, + ARCH_X86_GENERIC = 0x100, + ARCH_X86_SSSE3, + ARCH_X86_SSE42, + ARCH_X86_AVX2, + ARCH_MIPS_GENERIC = 0x200, + ARCH_MIPS_32 +} IVD_ARCH_T; + +/* IVD_SOC_T: SOC Enumeration */ +typedef enum +{ + SOC_NA = 0x7FFFFFFF, + SOC_GENERIC = 0x0, + SOC_HISI_37X = 0x100, +} IVD_SOC_T; + +/* IVD_FRAME_SKIP_MODE_T:Skip mode Enumeration */ + +typedef enum +{ + IVD_SKIP_NONE = 0x7FFFFFFF, + IVD_SKIP_P = 0x1, + IVD_SKIP_B = 0x2, + IVD_SKIP_I = 0x3, + IVD_SKIP_IP = 0x4, + IVD_SKIP_IB = 0x5, + IVD_SKIP_PB = 0x6, + IVD_SKIP_IPB = 0x7, + IVD_SKIP_IDR = 0x8, + IVD_SKIP_DEFAULT = IVD_SKIP_NONE, +} IVD_FRAME_SKIP_MODE_T; + +/* IVD_VIDEO_DECODE_MODE_T: Set decoder to decode either frame worth of data */ +/* or only header worth of data */ + +typedef enum +{ + IVD_DECODE_MODE_NA = 0x7FFFFFFF, + + /* This enables the codec to process all decodable units */ + IVD_DECODE_FRAME = 0x0, + + /* This enables the codec to decode header only */ + IVD_DECODE_HEADER = 0x1, + +} IVD_VIDEO_DECODE_MODE_T; + +/* IVD_DISPLAY_FRAME_OUT_MODE_T: Video Display Frame Output Mode */ + +typedef enum +{ + + IVD_DISPLAY_ORDER_NA = 0x7FFFFFFF, + /* To set codec to fill output buffers in display order */ + IVD_DISPLAY_FRAME_OUT = 0x0, + + /* To set codec to fill output buffers in decode order */ + IVD_DECODE_FRAME_OUT = 0x1, +} IVD_DISPLAY_FRAME_OUT_MODE_T; + +/* IVD_API_COMMAND_TYPE_T:API command type */ +typedef enum +{ + IVD_CMD_VIDEO_NA = 0x7FFFFFFF, + IVD_CMD_CREATE = IV_CMD_DUMMY_ELEMENT + 1, + IVD_CMD_DELETE, + IVD_CMD_VIDEO_CTL, + IVD_CMD_VIDEO_DECODE, + IVD_CMD_FWCHECK, + IVD_CMD_GET_DISPLAY_FRAME, + IVD_CMD_REL_DISPLAY_FRAME, + IVD_CMD_SET_DISPLAY_FRAME +} IVD_API_COMMAND_TYPE_T; + +/* IVD_CONTROL_API_COMMAND_TYPE_T: Video Control API command type */ + +typedef enum +{ + IVD_CMD_NA = 0x7FFFFFFF, + IVD_CMD_CTL_GETPARAMS = 0x0, + IVD_CMD_CTL_SETPARAMS = 0x1, + IVD_CMD_CTL_RESET = 0x2, + IVD_CMD_CTL_SETDEFAULT = 0x3, + IVD_CMD_CTL_FLUSH = 0x4, + IVD_CMD_CTL_GETBUFINFO = 0x5, + IVD_CMD_CTL_GETVERSION = 0x6, + IVD_CMD_CTL_CODEC_SUBCMD_START = 0x7 +} IVD_CONTROL_API_COMMAND_TYPE_T; + +/* IVD_ERROR_BITS_T: A UWORD32 container will be used for reporting the error*/ +/* code to the application. The first 8 bits starting from LSB have been */ +/* reserved for the codec to report internal error details. The rest of the */ +/* bits will be generic for all video decoders and each bit has an associated*/ +/* meaning as mentioned below. The unused bit fields are reserved for future */ +/* extenstions and will be zero in the current implementation */ + +typedef enum +{ + /* Bit 8 - Applied concealment. */ + IVD_APPLIEDCONCEALMENT = 0x8, + /* Bit 9 - Insufficient input data. */ + IVD_INSUFFICIENTDATA = 0x9, + /* Bit 10 - Data problem/corruption. */ + IVD_CORRUPTEDDATA = 0xa, + /* Bit 11 - Header problem/corruption. */ + IVD_CORRUPTEDHEADER = 0xb, + /* Bit 12 - Unsupported feature/parameter in input. */ + IVD_UNSUPPORTEDINPUT = 0xc, + /* Bit 13 - Unsupported input parameter orconfiguration. */ + IVD_UNSUPPORTEDPARAM = 0xd, + /* Bit 14 - Fatal error (stop the codec).If there is an */ + /* error and this bit is not set, the error is a recoverable one. */ + IVD_FATALERROR = 0xe, + /* Bit 15 - Invalid bitstream. Applies when Bitstream/YUV frame */ + /* buffer for encode/decode call is made with non-valid or zero u4_size */ + /* data */ + IVD_INVALID_BITSTREAM = 0xf, + /* Bit 16 */ + IVD_INCOMPLETE_BITSTREAM = 0x10, + IVD_ERROR_BITS_T_DUMMY_ELEMENT = 0x7FFFFFFF +} IVD_ERROR_BITS_T; + +/* IVD_CONTROL_API_COMMAND_TYPE_T: Video Control API command type */ +typedef enum +{ + IVD_ERROR_NONE = 0x0, + IVD_NUM_MEM_REC_FAILED = 0x1, + IVD_NUM_REC_NOT_SUFFICIENT = 0x2, + IVD_FILL_MEM_REC_FAILED = 0x3, + IVD_REQUESTED_WIDTH_NOT_SUPPPORTED = 0x4, + IVD_REQUESTED_HEIGHT_NOT_SUPPPORTED = 0x5, + IVD_INIT_DEC_FAILED = 0x6, + IVD_INIT_DEC_NOT_SUFFICIENT = 0x7, + IVD_INIT_DEC_WIDTH_NOT_SUPPPORTED = 0x8, + IVD_INIT_DEC_HEIGHT_NOT_SUPPPORTED = 0x9, + IVD_INIT_DEC_MEM_NOT_ALIGNED = 0xa, + IVD_INIT_DEC_COL_FMT_NOT_SUPPORTED = 0xb, + IVD_INIT_DEC_MEM_REC_NOT_SUFFICIENT = 0xc, + IVD_GET_VERSION_DATABUFFER_SZ_INSUFFICIENT = 0xd, + IVD_BUFFER_SIZE_SET_TO_ZERO = 0xe, + IVD_UNEXPECTED_END_OF_STREAM = 0xf, + IVD_SEQUENCE_HEADER_NOT_DECODED = 0x10, + IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED = 0x11, + IVD_MAX_FRAME_LIMIT_REACHED = 0x12, + IVD_IP_API_STRUCT_SIZE_INCORRECT = 0x13, + IVD_OP_API_STRUCT_SIZE_INCORRECT = 0x14, + IVD_HANDLE_NULL = 0x15, + IVD_HANDLE_STRUCT_SIZE_INCORRECT = 0x16, + IVD_INVALID_HANDLE_NULL = 0x17, + IVD_INVALID_API_CMD = 0x18, + IVD_UNSUPPORTED_API_CMD = 0x19, + IVD_MEM_REC_STRUCT_SIZE_INCORRECT = 0x1a, + IVD_DISP_FRM_ZERO_OP_BUFS = 0x1b, + IVD_DISP_FRM_OP_BUF_NULL = 0x1c, + IVD_DISP_FRM_ZERO_OP_BUF_SIZE = 0x1d, + IVD_DEC_FRM_BS_BUF_NULL = 0x1e, + IVD_SET_CONFG_INVALID_DEC_MODE = 0x1f, + IVD_SET_CONFG_UNSUPPORTED_DISP_WIDTH = 0x20, + IVD_RESET_FAILED = 0x21, + IVD_INIT_DEC_MEM_REC_OVERLAP_ERR = 0x22, + IVD_INIT_DEC_MEM_REC_BASE_NULL = 0x23, + IVD_INIT_DEC_MEM_REC_ALIGNMENT_ERR = 0x24, + IVD_INIT_DEC_MEM_REC_INSUFFICIENT_SIZE = 0x25, + IVD_INIT_DEC_MEM_REC_INCORRECT_TYPE = 0x26, + IVD_DEC_NUMBYTES_INV = 0x27, + IVD_DEC_REF_BUF_NULL = 0x28, + IVD_DEC_FRM_SKIPPED = 0x29, + IVD_RES_CHANGED = 0x2a, + IVD_MEM_ALLOC_FAILED = 0x2b, + IVD_DUMMY_ELEMENT_FOR_CODEC_EXTENSIONS = 0xD0, +} IVD_ERROR_CODES_T; + +/*****************************************************************************/ +/* Structure */ +/*****************************************************************************/ +/* structure for passing output buffers to codec during get display buffer */ +/* call */ +typedef struct +{ + /** + * number of output buffers + */ + UWORD32 u4_num_bufs; + + /** + *list of pointers to output buffers + */ + UWORD8 *pu1_bufs[IVD_VIDDEC_MAX_IO_BUFFERS]; + + /** + * sizes of each output buffer + */ + UWORD32 u4_min_out_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS]; + + UWORD32 u4_num_bufs_size; + +} ivd_out_bufdesc_t; + +/*****************************************************************************/ +/* Create decoder */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_CREATE */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * e_cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * format in which codec has to give out frame data for display + */ + IV_COLOR_FORMAT_T e_output_format; + + /** + * Flag to indicate shared display buffer mode + */ + UWORD32 u4_share_disp_buf; + + /** + * Pointer to a function for aligned allocation. + */ + void *(*pf_aligned_alloc)(void *pv_mem_ctxt, WORD32 alignment, WORD32 size); + + /** + * Pointer to a function for aligned free. + */ + void (*pf_aligned_free)(void *pv_mem_ctxt, void *pv_buf); + + /** + * Pointer to memory context that is needed during alloc/free for custom + * memory managers. This will be passed as first argument to pf_aligned_alloc and + * pf_aligned_free. + * If application is using standard memory functions like + * malloc/aligned_malloc/memalign/free/aligned_free, + * then this is not needed and can be set to NULL + */ + void *pv_mem_ctxt; + +} ivd_create_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * u4_error_code + */ + UWORD32 u4_error_code; + + /** + * Codec Handle + */ + void *pv_handle; + +} ivd_create_op_t; + +/*****************************************************************************/ +/* FWCheck decoder */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_FWCHECK */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + +} ivd_fwcheck_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error_code + */ + UWORD32 u4_error_code; + + UWORD32 u4_fw_status; + +} ivd_fwcheck_op_t; + +/*****************************************************************************/ +/* Delete decoder */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_DELETE */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + +} ivd_delete_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error_code + */ + UWORD32 u4_error_code; + +} ivd_delete_op_t; + +/*****************************************************************************/ +/* Video Decode */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_VIDEO_DECODE */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * e_cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * u4_ts + */ + UWORD32 u4_ts; + + /** + * u4_num_Bytes + */ + UWORD32 u4_num_Bytes; + + /** + * pv_stream_buffer + */ + void *pv_stream_buffer; + + /** + * output buffer desc + */ + ivd_out_bufdesc_t s_out_buffer; + +} ivd_video_decode_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * u4_error_code + */ + UWORD32 u4_error_code; + + /** + * num_bytes_consumed + */ + UWORD32 u4_num_bytes_consumed; + + /** + * pic_wd + */ + UWORD32 u4_pic_wd; + + /** + * pic_ht + */ + UWORD32 u4_pic_ht; + + /** + * pic_type + */ + IV_PICTURE_CODING_TYPE_T e_pic_type; + + /** + * frame_decoded_flag + */ + UWORD32 u4_frame_decoded_flag; + + /** + * new_seq + */ + UWORD32 u4_new_seq; + + /** + * output_present + */ + UWORD32 u4_output_present; + + /** + * progressive_frame_flag + */ + UWORD32 u4_progressive_frame_flag; + + /** + * is_ref_flag + */ + UWORD32 u4_is_ref_flag; + + /** + * output_format + */ + IV_COLOR_FORMAT_T e_output_format; + + /** + * disp_frm_buf + */ + iv_yuv_buf_t s_disp_frm_buf; + + /** + * fld_type + */ + IV_FLD_TYPE_T e4_fld_type; + + /** + * ts + */ + UWORD32 u4_ts; + + /** + * disp_buf_id + */ + UWORD32 u4_disp_buf_id; +} ivd_video_decode_op_t; + +/*****************************************************************************/ +/* Get Display Frame */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_GET_DISPLAY_FRAME */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * e_cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * output buffer desc + */ + ivd_out_bufdesc_t s_out_buffer; + +} ivd_get_display_frame_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error_code + */ + UWORD32 u4_error_code; + + /** + * progressive_frame_flag + */ + UWORD32 u4_progressive_frame_flag; + + /** + * pic_type + */ + IV_PICTURE_CODING_TYPE_T e_pic_type; + + /** + * is_ref_flag + */ + UWORD32 u4_is_ref_flag; + + /** + * output_format + */ + IV_COLOR_FORMAT_T e_output_format; + + /** + * disp_frm_buf + */ + iv_yuv_buf_t s_disp_frm_buf; + + /** + * fld_type + */ + IV_FLD_TYPE_T e4_fld_type; + + /** + * ts + */ + UWORD32 u4_ts; + + /** + * disp_buf_id + */ + UWORD32 u4_disp_buf_id; +} ivd_get_display_frame_op_t; + +/*****************************************************************************/ +/* Set Display Frame */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_SET_DISPLAY_FRAME */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * num_disp_bufs + */ + UWORD32 num_disp_bufs; + + /** + * output buffer desc + */ + ivd_out_bufdesc_t s_disp_buffer[IVD_VIDDEC_MAX_IO_BUFFERS]; + +} ivd_set_display_frame_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error code + */ + UWORD32 u4_error_code; +} ivd_set_display_frame_op_t; + +/*****************************************************************************/ +/* Release Display Frame */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_SET_DISPLAY_FRAME */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * e_cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * disp_buf_id + */ + UWORD32 u4_disp_buf_id; +} ivd_rel_display_frame_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error code + */ + UWORD32 u4_error_code; +} ivd_rel_display_frame_op_t; + +/*****************************************************************************/ +/* Video control Flush */ +/*****************************************************************************/ +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_VIDEO_CTL */ +/* IVD_CONTROL_API_COMMAND_TYPE_T::e_sub_cmd = IVD_CMD_ctl_FLUSH */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * sub_cmd + */ + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; +} ivd_ctl_flush_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error code + */ + UWORD32 u4_error_code; +} ivd_ctl_flush_op_t; + +/*****************************************************************************/ +/* Video control reset */ +/*****************************************************************************/ +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_VIDEO_CTL */ +/* IVD_CONTROL_API_COMMAND_TYPE_T::e_sub_cmd = IVD_CMD_ctl_RESET */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * sub_cmd + */ + + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; +} ivd_ctl_reset_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error code + */ + UWORD32 u4_error_code; +} ivd_ctl_reset_op_t; + +/*****************************************************************************/ +/* Video control Set Params */ +/*****************************************************************************/ +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_VIDEO_CTL */ +/* IVD_CONTROL_API_COMMAND_TYPE_T::e_sub_cmd=IVD_CMD_ctl_SETPARAMS */ +/* IVD_CONTROL_API_COMMAND_TYPE_T::e_sub_cmd=IVD_CMD_ctl_SETDEFAULT */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * sub_cmd + */ + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + + /** + * vid_dec_mode + */ + IVD_VIDEO_DECODE_MODE_T e_vid_dec_mode; + + /** + * disp_wd + */ + UWORD32 u4_disp_wd; + + /** + * disp_ht + */ + UWORD32 u4_disp_ht; + + /** + * frm_skip_mode + */ + IVD_FRAME_SKIP_MODE_T e_frm_skip_mode; + + /** + * frm_out_mode + */ + IVD_DISPLAY_FRAME_OUT_MODE_T e_frm_out_mode; +} ivd_ctl_set_config_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * u4_error_code + */ + UWORD32 u4_error_code; +} ivd_ctl_set_config_op_t; + +/*****************************************************************************/ +/* Video control:Get Buf Info */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_VIDEO_CTL */ +/* IVD_CONTROL_API_COMMAND_TYPE_T::e_sub_cmd=IVD_CMD_ctl_GETBUFINFO */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * e_cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * sub_cmd + */ + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; +} ivd_ctl_getbufinfo_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error code + */ + UWORD32 u4_error_code; + + /** + * no of display buffer sets required by codec + */ + UWORD32 u4_num_disp_bufs; + + /** + * no of input buffers required for codec + */ + UWORD32 u4_min_num_in_bufs; + + /** + * no of output buffers required for codec + */ + UWORD32 u4_min_num_out_bufs; + + /** + * sizes of each input buffer required + */ + UWORD32 u4_min_in_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS]; + + /** + * sizes of each output buffer required + */ + UWORD32 u4_min_out_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS]; +} ivd_ctl_getbufinfo_op_t; + +/*****************************************************************************/ +/* Video control:Getstatus Call */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_VIDEO_CTL */ +/* IVD_CONTROL_API_COMMAND_TYPE_T::e_sub_cmd=IVD_CMD_ctl_GETPARAMS */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * sub_cmd + */ + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; +} ivd_ctl_getstatus_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error code + */ + UWORD32 u4_error_code; + + /** + * no of display buffer sets required by codec + */ + UWORD32 u4_num_disp_bufs; + + /** + * u4_pic_ht + */ + UWORD32 u4_pic_ht; + + /** + * u4_pic_wd + */ + UWORD32 u4_pic_wd; + + /** + * frame_rate + */ + UWORD32 u4_frame_rate; + + /** + * u4_bit_rate + */ + UWORD32 u4_bit_rate; + + /** + * content_type + */ + IV_CONTENT_TYPE_T e_content_type; + + /** + * output_chroma_format + */ + IV_COLOR_FORMAT_T e_output_chroma_format; + + /** + * no of input buffers required for codec + */ + UWORD32 u4_min_num_in_bufs; + + /** + * no of output buffers required for codec + */ + UWORD32 u4_min_num_out_bufs; + + /** + * sizes of each input buffer required + */ + UWORD32 u4_min_in_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS]; + + /** + * sizes of each output buffer required + */ + UWORD32 u4_min_out_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS]; +} ivd_ctl_getstatus_op_t; + +/*****************************************************************************/ +/* Video control:Get Version Info */ +/*****************************************************************************/ + +/* IVD_API_COMMAND_TYPE_T::e_cmd = IVD_CMD_VIDEO_CTL */ +/* IVD_CONTROL_API_COMMAND_TYPE_T::e_sub_cmd=IVD_CMD_ctl_GETVERSION */ + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * cmd + */ + IVD_API_COMMAND_TYPE_T e_cmd; + + /** + * sub_cmd + */ + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + + /** + * pv_version_buffer + */ + void *pv_version_buffer; + + /** + * version_buffer_size + */ + UWORD32 u4_version_buffer_size; +} ivd_ctl_getversioninfo_ip_t; + +typedef struct +{ + /** + * u4_size of the structure + */ + UWORD32 u4_size; + + /** + * error code + */ + UWORD32 u4_error_code; +} ivd_ctl_getversioninfo_op_t; + +#endif /* __IVD_H__ */ diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/test/decoder/dec.cfg b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/test/decoder/dec.cfg new file mode 100755 index 00000000..c886a305 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/test/decoder/dec.cfg @@ -0,0 +1,12 @@ +--input input.h264 +--save_output 1 +--num_frames -1 +--output out.yuv +--chroma_format YUV_420P +--share_display_buf 0 +--num_cores 3 +--loopback 0 +--display 0 +--fps 59.94 +--arch ARM_A9Q +--soc GENERIC diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/test/decoder/main.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/test/decoder/main.c new file mode 100755 index 00000000..97ede70b --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/android/test/decoder/main.c @@ -0,0 +1,1749 @@ +/****************************************************************************** + * + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore +*/ +/*****************************************************************************/ +/* */ +/* File Name : main.c */ +/* */ +/* Description : Contains an application that demonstrates use of H264*/ +/* decoder API */ +/* */ +/* List of Functions : */ +/* */ +/* Issues / Problems : None */ +/* */ +/* Revision History : */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 Harish Initial Version */ +/*****************************************************************************/ +/*****************************************************************************/ +/* File Includes */ +/*****************************************************************************/ +#include +#include +#include + +#include + +#include "ifwh264_typedefs.h" + +#include "ifwv.h" +#include "ifwvd.h" +#include "ifwh264d.h" +#include "ifwthread.h" + +#include + +//#define ADAPTIVE_TEST +#define ADAPTIVE_MAX_WD 4096 +#define ADAPTIVE_MAX_HT 2160 + +#define ALIGN8(x) ((((x) + 7) >> 3) << 3) +#define NUM_DISPLAY_BUFFERS 4 +#define DEFAULT_FPS 30 + +#define MAX_DISP_BUFFERS 64 +#define EXTRA_DISP_BUFFERS 8 +#define STRLENGTH 1000 + +#define FLUSH_FRM_CNT 100 +//#define APP_EXTRA_BUFS 1 + +typedef WORD32 TIMER; + +#define GETTIME(timer) +#define ELAPSEDTIME(s_start_timer, s_end_timer, s_elapsed_time, frequency) + +/* Function declarations */ +#ifndef MD5_DISABLE +void calc_md5_cksum(UWORD8 *pu1_inbuf, UWORD32 u4_stride, UWORD32 u4_width, + UWORD32 u4_height, UWORD8 *pu1_cksum_p); +#else +#define calc_md5_cksum(a, b, c, d, e) +#endif + +typedef struct +{ + UWORD32 u4_piclen_flag; + UWORD32 u4_file_save_flag; + UWORD32 u4_chksum_save_flag; + UWORD32 u4_max_frm_ts; + IV_COLOR_FORMAT_T e_output_chroma_format; + IVD_ARCH_T e_arch; + IVD_SOC_T e_soc; + UWORD32 dump_q_rd_idx; + UWORD32 dump_q_wr_idx; + WORD32 disp_q_wr_idx; + WORD32 disp_q_rd_idx; + + void *cocodec_obj; + UWORD32 u4_share_disp_buf; + UWORD32 num_disp_buf; + UWORD32 b_pic_present; + UWORD32 u4_disable_dblk_level; + WORD32 i4_degrade_type; + WORD32 i4_degrade_pics; + UWORD32 u4_num_cores; + UWORD32 disp_delay; + WORD32 trace_enable; + CHAR ac_trace_fname[STRLENGTH]; + CHAR ac_piclen_fname[STRLENGTH]; + CHAR ac_ip_fname[STRLENGTH]; + CHAR ac_op_fname[STRLENGTH]; + CHAR ac_op_chksum_fname[STRLENGTH]; + ivd_out_bufdesc_t s_disp_buffers[MAX_DISP_BUFFERS]; + iv_yuv_buf_t s_disp_frm_queue[MAX_DISP_BUFFERS]; + UWORD32 s_disp_frm_id_queue[MAX_DISP_BUFFERS]; + UWORD32 loopback; + UWORD32 display; + UWORD32 full_screen; + UWORD32 fps; + + UWORD32 u4_strd; + + /* For signalling to display thread */ + UWORD32 u4_pic_wd; + UWORD32 u4_pic_ht; + + //UWORD32 u4_output_present; + WORD32 quit; + WORD32 paused; + + void *pv_disp_ctx; + void *display_thread_handle; + WORD32 display_thread_created; + volatile WORD32 display_init_done; + volatile WORD32 display_deinit_flag; + + void *(*disp_init)(UWORD32, UWORD32, WORD32, WORD32, WORD32, WORD32, WORD32, + WORD32 *, WORD32 *); + void (*alloc_disp_buffers)(void *); + void (*display_buffer)(void *, WORD32); + void (*set_disp_buffers)(void *, WORD32, UWORD8 **, UWORD8 **, UWORD8 **); + void (*disp_deinit)(void *); + void (*disp_usleep)(UWORD32); + IV_COLOR_FORMAT_T (*get_color_fmt)(void); + UWORD32 (*get_stride)(void); +} vid_dec_ctx_t; + +typedef enum +{ + INVALID, + HELP, + VERSION, + INPUT_FILE, + OUTPUT, + CHKSUM, + SAVE_OUTPUT, + SAVE_CHKSUM, + CHROMA_FORMAT, + NUM_FRAMES, + NUM_CORES, + DISABLE_DEBLOCK_LEVEL, + SHARE_DISPLAY_BUF, + LOOPBACK, + DISPLAY, + FULLSCREEN, + FPS, + TRACE, + CONFIG, + + DEGRADE_TYPE, + DEGRADE_PICS, + ARCH, + SOC, + PICLEN, + PICLEN_FILE, +} ARGUMENT_T; + +typedef struct +{ + CHAR argument_shortname[4]; + CHAR argument_name[128]; + ARGUMENT_T argument; + CHAR description[512]; +} argument_t; + +static const argument_t argument_mapping[] = { + {"-h", "--help", HELP, "Print this help\n"}, + {"-c", "--config", CONFIG, "config file (Default: test.cfg)\n"}, + + {"-v", "--version", VERSION, "Version information\n"}, + {"-i", "--input", INPUT_FILE, "Input file\n"}, + {"-o", "--output", OUTPUT, "Output file\n"}, + {"--", "--piclen", PICLEN, + "Flag to signal if the decoder has to use a file containing number of " + "bytes in each picture to be fed in each call\n"}, + {"--", "--piclen_file", PICLEN_FILE, + "File containing number of bytes in each picture - each line containing " + "one i4_size\n"}, + {"--", "--chksum", CHKSUM, "Output MD5 Checksum file\n"}, + {"-s", "--save_output", SAVE_OUTPUT, "Save Output file\n"}, + {"--", "--save_chksum", SAVE_CHKSUM, "Save Check sum file\n"}, + {"--", "--chroma_format", CHROMA_FORMAT, + "Output Chroma format Supported values YUV_420P, YUV_422ILE, RGB_565, " + "YUV_420SP_UV, YUV_420SP_VU\n"}, + {"-n", "--num_frames", NUM_FRAMES, "Number of frames to be decoded\n"}, + {"--", "--num_cores", NUM_CORES, "Number of cores to be used\n"}, + {"--", "--share_display_buf", SHARE_DISPLAY_BUF, + "Enable shared display buffer mode\n"}, + {"--", "--disable_deblock_level", DISABLE_DEBLOCK_LEVEL, + "Disable deblocking level : 0 to 4 - 0 Enable deblocking 4 Disable " + "deblocking completely\n"}, + {"--", "--loopback", LOOPBACK, "Enable playback in a loop\n"}, + {"--", "--display", DISPLAY, "Enable display (uses SDL)\n"}, + {"--", "--fullscreen", FULLSCREEN, + "Enable full screen (Only for GDL and SDL)\n"}, + {"--", "--fps", FPS, "FPS to be used for display \n"}, + {"-i", "--trace", TRACE, "Trace file\n"}, + + {"--", "--degrade_type", DEGRADE_TYPE, + "Degrade type : 0: No degrade 0th bit set : Disable SAO 1st bit set : " + "Disable deblocking 2nd bit set : Faster inter prediction filters 3rd bit " + "set : Fastest inter prediction filters\n"}, + {"--", "--degrade_pics", DEGRADE_PICS, + "Degrade pics : 0 : No degrade 1 : Only on non-reference frames 2 : Do " + "not degrade every 4th or key frames 3 : All non-key frames 4 : All " + "frames"}, + + {"--", "--arch", ARCH, + "Set Architecture. Supported values ARM_NONEON, ARM_A9Q, ARM_A7, ARM_A5, " + "ARM_NEONINTR,ARMV8_GENERIC, X86_GENERIC, X86_SSSE3, X86_SSE4 \n"}, + {"--", "--soc", SOC, "Set SOC. Supported values GENERIC, HISI_37X \n"}, + +}; + +#define PEAK_WINDOW_SIZE 8 +#define DEFAULT_SHARE_DISPLAY_BUF 0 +#define STRIDE 1280 +#define SITIDE_HEIGHT 720 +#define DEFAULT_NUM_CORES 1 + +#define DUMP_SINGLE_BUF 0 +#define IV_ISFATALERROR(x) (((x) >> IVD_FATALERROR) & 0x1) + +#define ivd_api_function ifwh264d_api_function + +#if ANDROID_NDK +/*****************************************************************************/ +/* */ +/* Function Name : raise */ +/* */ +/* Description : Needed as a workaround when the application is built in */ +/* Android NDK. This is an exception to be called for divide*/ +/* by zero error */ +/* */ +/* Inputs : a */ +/* Globals : */ +/* Processing : None */ +/* */ +/* Outputs : */ +/* Returns : */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ +int raise(int a) +{ + printf("Divide by zero\n"); + return 0; +} +#endif + +#if (!defined(IOS)) && (!defined(_WIN32)) +void *ih264a_aligned_malloc(void *pv_ctxt, WORD32 alignment, WORD32 i4_size) +{ + (void)pv_ctxt; + return memalign(alignment, i4_size); +} + +void ih264a_aligned_free(void *pv_ctxt, void *pv_buf) +{ + (void)pv_ctxt; + free(pv_buf); + return; +} +#endif + +/*****************************************************************************/ +/* */ +/* Function Name : release_disp_frame */ +/* */ +/* Description : Calls release display control - Used to signal to the */ +/* decoder that this particular buffer has been displayed */ +/* and that the codec is now free to write to this buffer */ +/* */ +/* */ +/* Inputs : codec_obj : Codec Handle */ +/* buf_id : Buffer Id of the buffer to be released */ +/* This id would have been returned earlier by */ +/* the codec */ +/* Globals : */ +/* Processing : Calls Release Display call */ +/* */ +/* Outputs : */ +/* Returns : Status of release display call */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +IV_API_CALL_STATUS_T release_disp_frame(void *codec_obj, UWORD32 buf_id) +{ + ivd_rel_display_frame_ip_t s_video_rel_disp_ip; + ivd_rel_display_frame_op_t s_video_rel_disp_op; + IV_API_CALL_STATUS_T e_dec_status; + + s_video_rel_disp_ip.e_cmd = IVD_CMD_REL_DISPLAY_FRAME; + s_video_rel_disp_ip.u4_size = sizeof(ivd_rel_display_frame_ip_t); + s_video_rel_disp_op.u4_size = sizeof(ivd_rel_display_frame_op_t); + s_video_rel_disp_ip.u4_disp_buf_id = buf_id; + + e_dec_status = + ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_video_rel_disp_ip, + (void *)&s_video_rel_disp_op); + if (IV_SUCCESS != e_dec_status) + { + printf("Error in Release Disp frame\n"); + } + + return (e_dec_status); +} + +/*****************************************************************************/ +/* */ +/* Function Name : get_version */ +/* */ +/* Description : Control call to get codec version */ +/* */ +/* */ +/* Inputs : codec_obj : Codec handle */ +/* Globals : */ +/* Processing : Calls enable skip B frames control */ +/* */ +/* Outputs : */ +/* Returns : Control call return i4_status */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +IV_API_CALL_STATUS_T get_version(void *codec_obj) +{ + ivd_ctl_getversioninfo_ip_t ps_ctl_ip; + ivd_ctl_getversioninfo_op_t ps_ctl_op; + UWORD8 au1_buf[512]; + IV_API_CALL_STATUS_T i4_status; + ps_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + ps_ctl_ip.e_sub_cmd = IVD_CMD_CTL_GETVERSION; + ps_ctl_ip.u4_size = sizeof(ivd_ctl_getversioninfo_ip_t); + ps_ctl_op.u4_size = sizeof(ivd_ctl_getversioninfo_op_t); + ps_ctl_ip.pv_version_buffer = au1_buf; + ps_ctl_ip.u4_version_buffer_size = sizeof(au1_buf); + + printf("\n ivd_api_function IVD_CMD_CTL_GETVERSION\n"); + + i4_status = ivd_api_function((iv_obj_t *)codec_obj, (void *)&(ps_ctl_ip), + (void *)&(ps_ctl_op)); + + if (i4_status != IV_SUCCESS) + { + printf("Error in Getting Version number e_dec_status = %d " + "u4_error_code = %x\n", + i4_status, ps_ctl_op.u4_error_code); + } else + { + printf("Ittiam Decoder Version number: %s\n", + (char *)ps_ctl_ip.pv_version_buffer); + } + return i4_status; +} +/*****************************************************************************/ +/* */ +/* Function Name : codec_exit */ +/* */ +/* Description : handles unrecoverable errors */ +/* Inputs : Error message */ +/* Globals : None */ +/* Processing : Prints error message to console and exits. */ +/* Outputs : Error mesage to the console */ +/* Returns : None */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 07 06 2006 Sankar Creation */ +/* */ +/*****************************************************************************/ +void codec_exit(CHAR *pc_err_message) +{ + printf("%s\n", pc_err_message); + exit(-1); +} + +/*****************************************************************************/ +/* */ +/* Function Name : dump_output */ +/* */ +/* Description : Used to dump output YUV */ +/* Inputs : App context, disp output desc, File pointer */ +/* Globals : None */ +/* Processing : Dumps to a file */ +/* Returns : None */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes (Describe the changes made) */ +/* 07 06 2006 Sankar Creation */ +/* */ +/*****************************************************************************/ +void dump_output(vid_dec_ctx_t *ps_app_ctx, iv_yuv_buf_t *ps_disp_frm_buf, + UWORD32 u4_disp_frm_id, FILE *ps_op_file, + FILE *ps_op_chksum_file, WORD32 i4_op_frm_ts, + UWORD32 file_save, UWORD32 chksum_save) + +{ + UWORD32 i; + iv_yuv_buf_t s_dump_disp_frm_buf; + UWORD32 u4_disp_id; + + memset(&s_dump_disp_frm_buf, 0, sizeof(iv_yuv_buf_t)); + + if (ps_app_ctx->u4_share_disp_buf) + { + if (ps_app_ctx->dump_q_wr_idx == MAX_DISP_BUFFERS) + ps_app_ctx->dump_q_wr_idx = 0; + + if (ps_app_ctx->dump_q_rd_idx == MAX_DISP_BUFFERS) + ps_app_ctx->dump_q_rd_idx = 0; + + ps_app_ctx->s_disp_frm_queue[ps_app_ctx->dump_q_wr_idx] = + *ps_disp_frm_buf; + ps_app_ctx->s_disp_frm_id_queue[ps_app_ctx->dump_q_wr_idx] = + u4_disp_frm_id; + ps_app_ctx->dump_q_wr_idx++; + + if ((WORD32)i4_op_frm_ts >= (WORD32)(ps_app_ctx->disp_delay - 1)) + { + s_dump_disp_frm_buf = + ps_app_ctx->s_disp_frm_queue[ps_app_ctx->dump_q_rd_idx]; + u4_disp_id = + ps_app_ctx->s_disp_frm_id_queue[ps_app_ctx->dump_q_rd_idx]; + ps_app_ctx->dump_q_rd_idx++; + } else + { + return; + } + } else + { + s_dump_disp_frm_buf = *ps_disp_frm_buf; + u4_disp_id = u4_disp_frm_id; + } + + release_disp_frame(ps_app_ctx->cocodec_obj, u4_disp_id); + + if (0 == file_save && 0 == chksum_save) + return; + + if (NULL == s_dump_disp_frm_buf.pv_y_buf) + return; + + if (ps_app_ctx->e_output_chroma_format == IV_YUV_420P) + { +#if DUMP_SINGLE_BUF + { + UWORD8 *buf = s_dump_disp_frm_buf.pv_y_buf - 80 - + (s_dump_disp_frm_buf.u4_y_strd * 80); + + UWORD32 i4_size = s_dump_disp_frm_buf.u4_y_strd * + ((s_dump_disp_frm_buf.u4_y_ht + 160) + + (s_dump_disp_frm_buf.u4_u_ht + 80)); + fwrite(buf, 1, i4_size, ps_op_file); + } +#else + if (0 != file_save) + { + UWORD8 *buf; + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_y_buf; + for (i = 0; i < s_dump_disp_frm_buf.u4_y_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_y_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_y_strd; + } + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_u_buf; + for (i = 0; i < s_dump_disp_frm_buf.u4_u_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_u_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_u_strd; + } + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_v_buf; + for (i = 0; i < s_dump_disp_frm_buf.u4_v_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_v_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_v_strd; + } + } + + if (0 != chksum_save) + { + UWORD8 au1_y_chksum[16] = {0}; + UWORD8 au1_u_chksum[16] = {0}; + UWORD8 au1_v_chksum[16] = {0}; + calc_md5_cksum((UWORD8 *)s_dump_disp_frm_buf.pv_y_buf, + s_dump_disp_frm_buf.u4_y_strd, + s_dump_disp_frm_buf.u4_y_wd, + s_dump_disp_frm_buf.u4_y_ht, au1_y_chksum); + calc_md5_cksum((UWORD8 *)s_dump_disp_frm_buf.pv_u_buf, + s_dump_disp_frm_buf.u4_u_strd, + s_dump_disp_frm_buf.u4_u_wd, + s_dump_disp_frm_buf.u4_u_ht, au1_u_chksum); + calc_md5_cksum((UWORD8 *)s_dump_disp_frm_buf.pv_v_buf, + s_dump_disp_frm_buf.u4_v_strd, + s_dump_disp_frm_buf.u4_v_wd, + s_dump_disp_frm_buf.u4_v_ht, au1_v_chksum); + + fwrite(au1_y_chksum, sizeof(UWORD8), 16, ps_op_chksum_file); + fwrite(au1_u_chksum, sizeof(UWORD8), 16, ps_op_chksum_file); + fwrite(au1_v_chksum, sizeof(UWORD8), 16, ps_op_chksum_file); + } +#endif + } else if ((ps_app_ctx->e_output_chroma_format == IV_YUV_420SP_UV) || + (ps_app_ctx->e_output_chroma_format == IV_YUV_420SP_VU)) + { +#if DUMP_SINGLE_BUF + { + UWORD8 *buf = s_dump_disp_frm_buf.pv_y_buf - 24 - + (s_dump_disp_frm_buf.u4_y_strd * 40); + + UWORD32 i4_size = s_dump_disp_frm_buf.u4_y_strd * + ((s_dump_disp_frm_buf.u4_y_ht + 80) + + (s_dump_disp_frm_buf.u4_u_ht + 40)); + fwrite(buf, 1, i4_size, ps_op_file); + } +#else + { + UWORD8 *buf; + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_y_buf; + for (i = 0; i < s_dump_disp_frm_buf.u4_y_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_y_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_y_strd; + } + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_u_buf; + for (i = 0; i < s_dump_disp_frm_buf.u4_u_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_u_wd, ps_op_file); + buf += s_dump_disp_frm_buf.u4_u_strd; + } + } +#endif + } else if (ps_app_ctx->e_output_chroma_format == IV_RGBA_8888) + { + UWORD8 *buf; + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_y_buf; + for (i = 0; i < s_dump_disp_frm_buf.u4_y_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_y_wd * 4, ps_op_file); + buf += s_dump_disp_frm_buf.u4_y_strd * 4; + } + } else + { + UWORD8 *buf; + + buf = (UWORD8 *)s_dump_disp_frm_buf.pv_y_buf; + for (i = 0; i < s_dump_disp_frm_buf.u4_y_ht; i++) + { + fwrite(buf, 1, s_dump_disp_frm_buf.u4_y_strd * 2, ps_op_file); + buf += s_dump_disp_frm_buf.u4_y_strd * 2; + } + } + + fflush(ps_op_file); + fflush(ps_op_chksum_file); +} + +/*****************************************************************************/ +/* */ +/* Function Name : print_usage */ +/* */ +/* Description : Prints argument format */ +/* */ +/* */ +/* Inputs : */ +/* Globals : */ +/* Processing : Prints argument format */ +/* */ +/* Outputs : */ +/* Returns : */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +void print_usage(void) +{ + WORD32 i = 0; + WORD32 num_entries = sizeof(argument_mapping) / sizeof(argument_t); + printf("\nUsage:\n"); + while (i < num_entries) + { + printf("%-32s\t %s", argument_mapping[i].argument_name, + argument_mapping[i].description); + i++; + } +} + +/*****************************************************************************/ +/* */ +/* Function Name : get_argument */ +/* */ +/* Description : Gets argument for a given string */ +/* */ +/* */ +/* Inputs : name */ +/* Globals : */ +/* Processing : Searches the given string in the array and returns */ +/* appropriate argument ID */ +/* */ +/* Outputs : Argument ID */ +/* Returns : Argument ID */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +ARGUMENT_T get_argument(CHAR *name) +{ + WORD32 i = 0; + WORD32 num_entries = sizeof(argument_mapping) / sizeof(argument_t); + while (i < num_entries) + { + if ((0 == strcmp(argument_mapping[i].argument_name, name)) || + ((0 == strcmp(argument_mapping[i].argument_shortname, name)) && + (0 != strcmp(argument_mapping[i].argument_shortname, "--")))) + { + return argument_mapping[i].argument; + } + i++; + } + return INVALID; +} + +/*****************************************************************************/ +/* */ +/* Function Name : get_argument */ +/* */ +/* Description : Gets argument for a given string */ +/* */ +/* */ +/* Inputs : name */ +/* Globals : */ +/* Processing : Searches the given string in the array and returns */ +/* appropriate argument ID */ +/* */ +/* Outputs : Argument ID */ +/* Returns : Argument ID */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +void parse_argument(vid_dec_ctx_t *ps_app_ctx, CHAR *argument, CHAR *value) +{ + ARGUMENT_T arg; + + arg = get_argument(argument); + printf("\nparse_argument %s\n", argument); + switch (arg) + { + case HELP: + print_usage(); + exit(-1); + case VERSION: + break; + case INPUT_FILE: + sscanf(value, "%999s", ps_app_ctx->ac_ip_fname); + //input_passed = 1; + break; + + case OUTPUT: + sscanf(value, "%999s", ps_app_ctx->ac_op_fname); + break; + + case CHKSUM: + sscanf(value, "%999s", ps_app_ctx->ac_op_chksum_fname); + break; + + case SAVE_OUTPUT: + sscanf(value, "%d", &ps_app_ctx->u4_file_save_flag); + break; + + case SAVE_CHKSUM: + sscanf(value, "%d", &ps_app_ctx->u4_chksum_save_flag); + break; + + case CHROMA_FORMAT: + if ((strcmp(value, "YUV_420P")) == 0) + ps_app_ctx->e_output_chroma_format = IV_YUV_420P; + else if ((strcmp(value, "YUV_422ILE")) == 0) + ps_app_ctx->e_output_chroma_format = IV_YUV_422ILE; + else if ((strcmp(value, "RGB_565")) == 0) + ps_app_ctx->e_output_chroma_format = IV_RGB_565; + else if ((strcmp(value, "RGBA_8888")) == 0) + ps_app_ctx->e_output_chroma_format = IV_RGBA_8888; + else if ((strcmp(value, "YUV_420SP_UV")) == 0) + ps_app_ctx->e_output_chroma_format = IV_YUV_420SP_UV; + else if ((strcmp(value, "YUV_420SP_VU")) == 0) + ps_app_ctx->e_output_chroma_format = IV_YUV_420SP_VU; + else + { + printf("\nInvalid colour format setting it to IV_YUV_420P\n"); + ps_app_ctx->e_output_chroma_format = IV_YUV_420P; + } + + break; + case NUM_FRAMES: + sscanf(value, "%d", &ps_app_ctx->u4_max_frm_ts); + break; + + case NUM_CORES: + sscanf(value, "%d", &ps_app_ctx->u4_num_cores); + break; + case DEGRADE_PICS: + sscanf(value, "%d", &ps_app_ctx->i4_degrade_pics); + break; + case DEGRADE_TYPE: + sscanf(value, "%d", &ps_app_ctx->i4_degrade_type); + break; + case SHARE_DISPLAY_BUF: + sscanf(value, "%d", &ps_app_ctx->u4_share_disp_buf); + break; + case LOOPBACK: + sscanf(value, "%d", &ps_app_ctx->loopback); + break; + case DISPLAY: + ps_app_ctx->display = 0; + break; + case FULLSCREEN: + sscanf(value, "%d", &ps_app_ctx->full_screen); + break; + case FPS: + sscanf(value, "%d", &ps_app_ctx->fps); + if (ps_app_ctx->fps <= 0) + ps_app_ctx->fps = DEFAULT_FPS; + break; + case ARCH: + if ((strcmp(value, "ARM_NONEON")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_NONEON; + else if ((strcmp(value, "ARM_A9Q")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_A9Q; + else if ((strcmp(value, "ARM_A7")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_A7; + else if ((strcmp(value, "ARM_A5")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_A5; + else if ((strcmp(value, "ARM_NEONINTR")) == 0) + ps_app_ctx->e_arch = ARCH_ARM_NEONINTR; + else if ((strcmp(value, "X86_GENERIC")) == 0) + ps_app_ctx->e_arch = ARCH_X86_GENERIC; + else if ((strcmp(value, "X86_SSSE3")) == 0) + ps_app_ctx->e_arch = ARCH_X86_SSSE3; + else if ((strcmp(value, "X86_SSE42")) == 0) + ps_app_ctx->e_arch = ARCH_X86_SSE42; + else if ((strcmp(value, "X86_AVX2")) == 0) + ps_app_ctx->e_arch = ARCH_X86_AVX2; + else if ((strcmp(value, "MIPS_GENERIC")) == 0) + ps_app_ctx->e_arch = ARCH_MIPS_GENERIC; + else if ((strcmp(value, "MIPS_32")) == 0) + ps_app_ctx->e_arch = ARCH_MIPS_32; + else if ((strcmp(value, "ARMV8_GENERIC")) == 0) + ps_app_ctx->e_arch = ARCH_ARMV8_GENERIC; + else + { + printf("\nInvalid Arch. Setting it to ARM_A9Q\n"); + ps_app_ctx->e_arch = ARCH_ARM_A9Q; + } + + break; + case SOC: + if ((strcmp(value, "GENERIC")) == 0) + ps_app_ctx->e_soc = SOC_GENERIC; + else if ((strcmp(value, "HISI_37X")) == 0) + ps_app_ctx->e_soc = SOC_HISI_37X; + else + { + ps_app_ctx->e_soc = atoi(value); + /* + printf("\nInvalid SOC. Setting it to GENERIC\n"); + ps_app_ctx->e_soc = SOC_GENERIC; +*/ + } + break; + case PICLEN: + sscanf(value, "%d", &ps_app_ctx->u4_piclen_flag); + break; + + case PICLEN_FILE: + sscanf(value, "%999s", ps_app_ctx->ac_piclen_fname); + break; + case DISABLE_DEBLOCK_LEVEL: + sscanf(value, "%d", &ps_app_ctx->u4_disable_dblk_level); + break; + + case INVALID: + default: + printf("Ignoring argument : %s\n", argument); + break; + } +} + +/*****************************************************************************/ +/* */ +/* Function Name : read_cfg_file */ +/* */ +/* Description : Reads arguments from a configuration file */ +/* */ +/* */ +/* Inputs : ps_app_ctx : Application context */ +/* fp_cfg_file : Configuration file handle */ +/* Globals : */ +/* Processing : Parses the arguments and fills in the application context*/ +/* */ +/* Outputs : Arguments parsed */ +/* Returns : None */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ + +void read_cfg_file(vid_dec_ctx_t *ps_app_ctx, FILE *fp_cfg_file) +{ + CHAR line[STRLENGTH]; + CHAR description[STRLENGTH]; + CHAR value[STRLENGTH]; + CHAR argument[STRLENGTH]; + void *ret; + while (0 == feof(fp_cfg_file)) + { + line[0] = '\0'; + ret = fgets(line, STRLENGTH, fp_cfg_file); + if (NULL == ret) + break; + argument[0] = '\0'; + /* Reading Input File Name */ + sscanf(line, "%999s %999s %999s", argument, value, description); + if (argument[0] == '\0') + continue; + + parse_argument(ps_app_ctx, argument, value); + } + + printf("\read_cfg_file success\n"); +} + +void flush_output(iv_obj_t *codec_obj, vid_dec_ctx_t *ps_app_ctx, + ivd_out_bufdesc_t *ps_out_buf, UWORD8 *pu1_bs_buf, + UWORD32 *pu4_op_frm_ts, FILE *ps_op_file, + FILE *ps_op_chksum_file, UWORD32 u4_ip_frm_ts, + UWORD32 u4_bytes_remaining) +{ + WORD32 ret; + + do + { + ivd_ctl_flush_ip_t s_ctl_ip; + ivd_ctl_flush_op_t s_ctl_op; + + if (*pu4_op_frm_ts >= + (ps_app_ctx->u4_max_frm_ts + ps_app_ctx->disp_delay)) + break; + + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_FLUSH; + s_ctl_ip.u4_size = sizeof(ivd_ctl_flush_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_flush_op_t); + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + + if (ret != IV_SUCCESS) + { + printf("Error in Setting the decoder in flush mode\n"); + } + + if (IV_SUCCESS == ret) + { + ivd_video_decode_ip_t s_video_decode_ip; + ivd_video_decode_op_t s_video_decode_op; + + s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.u4_ts = u4_ip_frm_ts; + s_video_decode_ip.pv_stream_buffer = pu1_bs_buf; + s_video_decode_ip.u4_num_Bytes = u4_bytes_remaining; + s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t); + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[0] = + ps_out_buf->u4_min_out_buf_size[0]; + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[1] = + ps_out_buf->u4_min_out_buf_size[1]; + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[2] = + ps_out_buf->u4_min_out_buf_size[2]; + + s_video_decode_ip.s_out_buffer.pu1_bufs[0] = + ps_out_buf->pu1_bufs[0]; + s_video_decode_ip.s_out_buffer.pu1_bufs[1] = + ps_out_buf->pu1_bufs[1]; + s_video_decode_ip.s_out_buffer.pu1_bufs[2] = + ps_out_buf->pu1_bufs[2]; + s_video_decode_ip.s_out_buffer.u4_num_bufs = + ps_out_buf->u4_num_bufs; + + s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t); + + /*****************************************************************************/ + /* API Call: Video Decode */ + /*****************************************************************************/ + ret = ivd_api_function((iv_obj_t *)codec_obj, + (void *)&s_video_decode_ip, + (void *)&s_video_decode_op); + + if (1 == s_video_decode_op.u4_output_present) + { + CHAR cur_fname[1000]; + CHAR *extn = NULL; + /* The objective is to dump the decoded frames into separate files instead of + * dumping all the frames in one common file. Also, the number of dumped frames + * at any given instance of time cannot exceed 'frame_memory' + */ + if (ps_app_ctx->u4_file_save_flag) + { + /* Locate the position of extension yuv */ + extn = strstr(ps_app_ctx->ac_op_fname, "%d"); + if (extn != NULL) + { + /* Generate output file names */ + sprintf(cur_fname, ps_app_ctx->ac_op_fname, + *pu4_op_frm_ts); + /* Open Output file */ + ps_op_file = fopen(cur_fname, "wb"); + if (NULL == ps_op_file) + { + CHAR ac_error_str[STRLENGTH]; + sprintf(ac_error_str, + "Could not open output file %s", cur_fname); + + codec_exit(ac_error_str); + } + } + } + + dump_output(ps_app_ctx, &(s_video_decode_op.s_disp_frm_buf), + s_video_decode_op.u4_disp_buf_id, ps_op_file, + ps_op_chksum_file, *pu4_op_frm_ts, + ps_app_ctx->u4_file_save_flag, + ps_app_ctx->u4_chksum_save_flag); + if (extn != NULL) + fclose(ps_op_file); + (*pu4_op_frm_ts)++; + } + } + } while (IV_SUCCESS == ret); +} + +UWORD32 default_get_stride(void) +{ + return 0; +} + +IV_COLOR_FORMAT_T default_get_color_fmt(void) +{ + return IV_YUV_420P; +} +/*****************************************************************************/ +/* */ +/* Function Name : main */ +/* */ +/* Description : Application to demonstrate codec API */ +/* */ +/* */ +/* Inputs : argc - Number of arguments */ +/* argv[] - Arguments */ +/* Globals : */ +/* Processing : Shows how to use create, process, control and delete */ +/* */ +/* Outputs : Codec output in a file */ +/* Returns : */ +/* */ +/* Issues : Assumes both PROFILE_ENABLE to be */ +/* defined for multithread decode-display working */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* 09 05 2013 100578 Multithread decode-display */ +/*****************************************************************************/ + +int main(WORD32 argc, CHAR *argv[]) +{ + CHAR ac_cfg_fname[STRLENGTH]; + FILE *fp_cfg_file = NULL; + FILE *ps_piclen_file = NULL; + FILE *ps_ip_file = NULL; + FILE *ps_op_file = NULL; + FILE *ps_op_chksum_file = NULL; + WORD32 ret; + CHAR ac_error_str[STRLENGTH]; + vid_dec_ctx_t s_app_ctx; + UWORD8 *pu1_bs_buf = NULL; + + ivd_out_bufdesc_t *ps_out_buf; + UWORD32 file_pos = 0; + + UWORD32 u4_ip_frm_ts = 0, u4_op_frm_ts = 0; + + //WORD32 u4_bytes_remaining = 0; + UWORD32 i; + UWORD32 u4_ip_buf_len; + //WORD32 total_bytes_comsumed; + + //WORD32 width = 0, height = 0; + iv_obj_t *codec_obj; +#if defined(GPU_BUILD) && !defined(X86) +// int ioctl_init(); +// ioctl_init(); +#endif + + strcpy(ac_cfg_fname, "test.cfg"); + + /***********************************************************************/ + /* Initialize Application parameters */ + /***********************************************************************/ + + strcpy(s_app_ctx.ac_ip_fname, "\0"); + s_app_ctx.dump_q_wr_idx = 0; + s_app_ctx.dump_q_rd_idx = 0; + s_app_ctx.disp_q_wr_idx = 0; + s_app_ctx.disp_q_rd_idx = 0; + s_app_ctx.disp_delay = 0; + s_app_ctx.loopback = 0; + s_app_ctx.full_screen = 0; + s_app_ctx.u4_piclen_flag = 0; + s_app_ctx.fps = DEFAULT_FPS; + file_pos = 0; + //total_bytes_comsumed = 0; + u4_ip_frm_ts = 0; + u4_op_frm_ts = 0; + + s_app_ctx.u4_share_disp_buf = DEFAULT_SHARE_DISPLAY_BUF; + s_app_ctx.u4_num_cores = DEFAULT_NUM_CORES; + s_app_ctx.i4_degrade_type = 0; + s_app_ctx.i4_degrade_pics = 0; + s_app_ctx.e_arch = ARCH_ARM_A9Q; + s_app_ctx.e_soc = SOC_GENERIC; + + s_app_ctx.u4_strd = STRIDE; + + s_app_ctx.quit = 0; + s_app_ctx.paused = 0; + //s_app_ctx.u4_output_present = 0; + + s_app_ctx.get_stride = &default_get_stride; + + s_app_ctx.get_color_fmt = &default_get_color_fmt; + + /* Set function pointers for display */ + + s_app_ctx.display_deinit_flag = 0; + s_app_ctx.e_output_chroma_format = IV_YUV_420SP_UV; + /*************************************************************************/ + /* Parse arguments */ + /*************************************************************************/ + /* Read command line arguments */ + if (argc > 2) + { + for (i = 1; i < (UWORD32)argc; i += 2) + { + if (CONFIG == get_argument(argv[i])) + { + strcpy(ac_cfg_fname, argv[i + 1]); + if ((fp_cfg_file = fopen(ac_cfg_fname, "r")) == NULL) + { + sprintf(ac_error_str, + "Could not open Configuration file %s", + ac_cfg_fname); + codec_exit(ac_error_str); + } + read_cfg_file(&s_app_ctx, fp_cfg_file); + fclose(fp_cfg_file); + } else + { + parse_argument(&s_app_ctx, argv[i], argv[i + 1]); + } + } + } else + { + if ((fp_cfg_file = fopen(ac_cfg_fname, "r")) == NULL) + { + sprintf(ac_error_str, "Could not open Configuration file %s", + ac_cfg_fname); + codec_exit(ac_error_str); + } + read_cfg_file(&s_app_ctx, fp_cfg_file); + fclose(fp_cfg_file); + } + + printf("\ns_app_ctx.ac_ip_fname %s\n", s_app_ctx.ac_ip_fname); + + /* If display is enabled, then turn off shared mode and get color format that is supported by display */ + if (strcmp(s_app_ctx.ac_ip_fname, "\0") == 0) + { + printf("\nNo input file given for decoding\n"); + exit(-1); + } + + /***********************************************************************/ + /* create the file object for input file */ + /***********************************************************************/ + + ps_ip_file = fopen(s_app_ctx.ac_ip_fname, "rb"); + if (NULL == ps_ip_file) + { + sprintf(ac_error_str, "Could not open input file %s", + s_app_ctx.ac_ip_fname); + codec_exit(ac_error_str); + } + /***********************************************************************/ + /* create the file object for input file */ + /***********************************************************************/ + + if (1 == s_app_ctx.u4_piclen_flag) + { + ps_piclen_file = fopen(s_app_ctx.ac_piclen_fname, "rb"); + if (NULL == ps_piclen_file) + { + sprintf(ac_error_str, "Could not open piclen file %s", + s_app_ctx.ac_piclen_fname); + codec_exit(ac_error_str); + } + } + + /***********************************************************************/ + /* create the file object for output file */ + /***********************************************************************/ + + /* If the filename does not contain %d, then output will be dumped to + a single file and it is opened here */ + if ((1 == s_app_ctx.u4_file_save_flag) && + (strstr(s_app_ctx.ac_op_fname, "%d") == NULL)) + { + ps_op_file = fopen(s_app_ctx.ac_op_fname, "wb"); + if (NULL == ps_op_file) + { + sprintf(ac_error_str, "Could not open output file %s", + s_app_ctx.ac_op_fname); + codec_exit(ac_error_str); + } + } + + /***********************************************************************/ + /* create the file object for check sum file */ + /***********************************************************************/ + if (1 == s_app_ctx.u4_chksum_save_flag) + { + ps_op_chksum_file = fopen(s_app_ctx.ac_op_chksum_fname, "wb"); + if (NULL == ps_op_chksum_file) + { + sprintf(ac_error_str, "Could not open check sum file %s", + s_app_ctx.ac_op_chksum_fname); + codec_exit(ac_error_str); + } + } + /***********************************************************************/ + /* Create decoder instance */ + /***********************************************************************/ + { + ps_out_buf = (ivd_out_bufdesc_t *)malloc(sizeof(ivd_out_bufdesc_t)); + + /*****************************************************************************/ + /* API Call: Initialize the Decoder */ + /*****************************************************************************/ + { + ifwh264d_create_ip_t s_create_ip; + ifwh264d_create_op_t s_create_op; + void *fxns = &ivd_api_function; + + s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE; + s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = + s_app_ctx.u4_share_disp_buf; + s_create_ip.s_ivd_create_ip_t.e_output_format = + (IV_COLOR_FORMAT_T)s_app_ctx.e_output_chroma_format; + s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = + ih264a_aligned_malloc; + s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ih264a_aligned_free; + s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL; + s_create_ip.s_ivd_create_ip_t.u4_size = + sizeof(ifwh264d_create_ip_t); + s_create_op.s_ivd_create_op_t.u4_size = + sizeof(ifwh264d_create_op_t); + + printf("\n ivd_api_function IVD_CMD_CREATE\n"); + + ret = ivd_api_function(NULL, (void *)&s_create_ip, + (void *)&s_create_op); + if (ret != IV_SUCCESS) + { + sprintf(ac_error_str, "Error in Create %8x\n", + s_create_op.s_ivd_create_op_t.u4_error_code); + codec_exit(ac_error_str); + } + codec_obj = (iv_obj_t *)s_create_op.s_ivd_create_op_t.pv_handle; + codec_obj->pv_fxns = fxns; + codec_obj->u4_size = sizeof(iv_obj_t); + s_app_ctx.cocodec_obj = codec_obj; + printf("\n ivd_api_function IVD_CMD_CREATE Success\n"); + + /*****************************************************************************/ + /* set stride */ + /*****************************************************************************/ + + printf("\n ivd_api_function set stride\n"); + + { + ivd_ctl_set_config_ip_t s_ctl_ip; + ivd_ctl_set_config_op_t s_ctl_op; + + s_ctl_ip.u4_disp_wd = STRIDE; + + s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; + s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.e_vid_dec_mode = IVD_DECODE_HEADER; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); + + printf("\n ivd_api_function IVD_CMD_CTL_SETPARAMS\n"); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + if (ret != IV_SUCCESS) + { + sprintf(ac_error_str, "\nError in setting the stride"); + codec_exit(ac_error_str); + } + } + } + } + + /*************************************************************************/ + /* set num of cores */ + /*************************************************************************/ + { + printf("\n ivd_api_function num of cores\n"); + + ifwh264d_ctl_set_num_cores_ip_t s_ctl_set_cores_ip; + ifwh264d_ctl_set_num_cores_op_t s_ctl_set_cores_op; + + s_ctl_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_set_cores_ip.e_sub_cmd = + (IVD_CONTROL_API_COMMAND_TYPE_T)IFWH264D_CMD_CTL_SET_NUM_CORES; + s_ctl_set_cores_ip.u4_num_cores = s_app_ctx.u4_num_cores; + s_ctl_set_cores_ip.u4_size = sizeof(ifwh264d_ctl_set_num_cores_ip_t); + s_ctl_set_cores_op.u4_size = sizeof(ifwh264d_ctl_set_num_cores_op_t); + + printf("\n ivd_api_function IFWH264D_CMD_CTL_SET_NUM_CORES %d\n", + s_ctl_set_cores_ip.u4_num_cores); + + ret = + ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_cores_ip, + (void *)&s_ctl_set_cores_op); + if (ret != IV_SUCCESS) + { + sprintf(ac_error_str, "\nError in setting number of cores"); + codec_exit(ac_error_str); + } + } + + /*printf("\n ivd_api_function flush_output\n"); + + flush_output(codec_obj, &s_app_ctx, ps_out_buf, + pu1_bs_buf, &u4_op_frm_ts, + ps_op_file, ps_op_chksum_file, + u4_ip_frm_ts, u4_bytes_remaining);*/ + + /*****************************************************************************/ + /* Decode header to get width and height and buffer sizes */ + /*****************************************************************************/ + { + ivd_video_decode_ip_t s_video_decode_ip; + ivd_video_decode_op_t s_video_decode_op; + + { + ivd_ctl_set_config_ip_t s_ctl_ip; + ivd_ctl_set_config_op_t s_ctl_op; + + s_ctl_ip.u4_disp_wd = STRIDE; + + s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE; + s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.e_vid_dec_mode = IVD_DECODE_HEADER; + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t); + s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t); + + printf("\n ivd_api_function IVD_CMD_CTL_SETPARAMS\n"); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_ip, + (void *)&s_ctl_op); + if (ret != IV_SUCCESS) + { + sprintf(ac_error_str, + "\nError in setting the codec in header decode mode"); + codec_exit(ac_error_str); + } + } + + /* Allocate input buffer for header */ + u4_ip_buf_len = 256 * 1024; + pu1_bs_buf = (UWORD8 *)malloc(u4_ip_buf_len); + + if (pu1_bs_buf == NULL) + { + sprintf(ac_error_str, + "\nAllocation failure for input buffer of i4_size %d", + u4_ip_buf_len); + codec_exit(ac_error_str); + } + + do + { + WORD32 numbytes; + + if (0 == s_app_ctx.u4_piclen_flag) + { + fseek(ps_ip_file, file_pos, SEEK_SET); + numbytes = u4_ip_buf_len; + } else + { + WORD32 entries; + entries = fscanf(ps_piclen_file, "%d\n", &numbytes); + if (1 != entries) + numbytes = u4_ip_buf_len; + } + + WORD32 u4_bytes_remaining = + fread(pu1_bs_buf, sizeof(UWORD8), numbytes, ps_ip_file); + + printf("\n ivd_api_function u4_bytes_remaining %d\n", + u4_bytes_remaining); + + if (0 == u4_bytes_remaining) + { + sprintf(ac_error_str, "\nUnable to read from input file"); + codec_exit(ac_error_str); + } + + s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.u4_ts = u4_ip_frm_ts; + s_video_decode_ip.pv_stream_buffer = pu1_bs_buf; + s_video_decode_ip.u4_num_Bytes = u4_bytes_remaining; + s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t); + s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t); + + /*****************************************************************************/ + /* API Call: Header Decode */ + /*****************************************************************************/ + + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE HEAD\n"); + + ret = ivd_api_function((iv_obj_t *)codec_obj, + (void *)&s_video_decode_ip, + (void *)&s_video_decode_op); + + if (ret != IV_SUCCESS) + { + printf("Error in header decode 0x%x\n", + s_video_decode_op.u4_error_code); + // codec_exit(ac_error_str); + } + + UWORD32 u4_num_bytes_dec = s_video_decode_op.u4_num_bytes_consumed; + + printf("u4_num_bytes_consumed %d\n", + s_video_decode_op.u4_num_bytes_consumed); + + file_pos += u4_num_bytes_dec; + //total_bytes_comsumed += u4_num_bytes_dec; + } while (ret != IV_SUCCESS); + + /* copy pic_wd and pic_ht to initialize buffers */ + s_app_ctx.u4_pic_wd = s_video_decode_op.u4_pic_wd; + s_app_ctx.u4_pic_ht = s_video_decode_op.u4_pic_ht; + + printf( + "s_video_decode_op.u4_pic_wd %d, s_video_decode_op.u4_pic_ht %d\n", + s_video_decode_op.u4_pic_wd, s_video_decode_op.u4_pic_ht); + + //free(pu1_bs_buf); + /* Create display thread and wait for the display buffers to be initialized */ + } + + /*************************************************************************/ + /* Get VUI parameters */ + /*************************************************************************/ + { + ih264d_ctl_get_vui_params_ip_t s_ctl_get_vui_params_ip; + ih264d_ctl_get_vui_params_op_t s_ctl_get_vui_params_op; + + s_ctl_get_vui_params_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_get_vui_params_ip.e_sub_cmd = + (IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_GET_VUI_PARAMS; + s_ctl_get_vui_params_ip.u4_size = + sizeof(ih264d_ctl_get_vui_params_ip_t); + s_ctl_get_vui_params_op.u4_size = + sizeof(ih264d_ctl_get_vui_params_op_t); + + printf("\n ivd_api_function IH264D_CMD_CTL_GET_VUI_PARAMS\n"); + + ret = ivd_api_function((iv_obj_t *)codec_obj, + (void *)&s_ctl_get_vui_params_ip, + (void *)&s_ctl_get_vui_params_op); + if (IV_SUCCESS != ret) + { + printf("Error in Get VUI params\n"); + codec_exit(ac_error_str); + } + } + + get_version(codec_obj); + + while (1) + { + /*************************************************************************/ + /* set num of cores */ + /*************************************************************************/ + /***********************************************************************/ + /* Seek the file to start of current frame, this is equavelent of */ + /* having a parcer which tells the start of current frame */ + /***********************************************************************/ + WORD32 u4_bytes_remaining = 0; + { + WORD32 numbytes; + + if (0 == s_app_ctx.u4_piclen_flag) + { + fseek(ps_ip_file, file_pos, SEEK_SET); + numbytes = u4_ip_buf_len; + } else + { + WORD32 entries; + entries = fscanf(ps_piclen_file, "%d\n", &numbytes); + if (1 != entries) + numbytes = u4_ip_buf_len; + } + + u4_bytes_remaining = + fread(pu1_bs_buf, sizeof(UWORD8), numbytes, ps_ip_file); + + if (u4_bytes_remaining == 0) + { + if (1 == s_app_ctx.loopback) + { + file_pos = 0; + if (0 == s_app_ctx.u4_piclen_flag) + { + fseek(ps_ip_file, file_pos, SEEK_SET); + numbytes = u4_ip_buf_len; + } else + { + WORD32 entries; + entries = fscanf(ps_piclen_file, "%d\n", &numbytes); + if (1 != entries) + numbytes = u4_ip_buf_len; + } + + u4_bytes_remaining = + fread(pu1_bs_buf, sizeof(UWORD8), numbytes, ps_ip_file); + } else + break; + } + } + + /*********************************************************************/ + /* Following calls can be enabled at diffent times */ + /*********************************************************************/ + + { + ivd_video_decode_ip_t s_video_decode_ip; + ivd_video_decode_op_t s_video_decode_op; + + s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.u4_ts = u4_ip_frm_ts; + s_video_decode_ip.pv_stream_buffer = pu1_bs_buf; + s_video_decode_ip.u4_num_Bytes = u4_bytes_remaining; + s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t); + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[0] = + ps_out_buf->u4_min_out_buf_size[0]; + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[1] = + ps_out_buf->u4_min_out_buf_size[1]; + s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[2] = + ps_out_buf->u4_min_out_buf_size[2]; + + s_video_decode_ip.s_out_buffer.pu1_bufs[0] = + ps_out_buf->pu1_bufs[0]; + s_video_decode_ip.s_out_buffer.pu1_bufs[1] = + ps_out_buf->pu1_bufs[1]; + s_video_decode_ip.s_out_buffer.pu1_bufs[2] = + ps_out_buf->pu1_bufs[2]; + s_video_decode_ip.s_out_buffer.u4_num_bufs = + ps_out_buf->u4_num_bufs; + s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t); + + /* Get display buffer pointers */ + /*****************************************************************************/ + /* API Call: Video Decode */ + /*****************************************************************************/ + + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA before " + "s_video_decode_ip.u4_num_Bytes %d\n", + s_video_decode_ip.u4_num_Bytes); + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA before " + "ps_out_buf->u4_min_out_buf_size[0] %d\n", + ps_out_buf->u4_min_out_buf_size[0]); + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA before " + "ps_out_buf->u4_min_out_buf_size[1] %d\n", + ps_out_buf->u4_min_out_buf_size[1]); + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA before " + "ps_out_buf->u4_min_out_buf_size[2] %d\n", + ps_out_buf->u4_min_out_buf_size[2]); + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA before " + "ps_out_buf->u4_num_bufs %d\n", + ps_out_buf->u4_num_bufs); + + GETTIME(&s_start_timer); + + ret = ivd_api_function((iv_obj_t *)codec_obj, + (void *)&s_video_decode_ip, + (void *)&s_video_decode_op); + + GETTIME(&s_end_timer); + ELAPSEDTIME(s_start_timer, s_end_timer, s_elapsed_time, frequency); + + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA after " + "s_video_decode_ip.u4_num_Bytes %d\n", + s_video_decode_ip.u4_num_Bytes); + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA after " + "ps_out_buf->u4_min_out_buf_size[0] %d\n", + ps_out_buf->u4_min_out_buf_size[0]); + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA after " + "ps_out_buf->u4_min_out_buf_size[1] %d\n", + ps_out_buf->u4_min_out_buf_size[1]); + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA after " + "ps_out_buf->u4_min_out_buf_size[2] %d\n", + ps_out_buf->u4_min_out_buf_size[2]); + printf("\n ivd_api_function IVD_CMD_VIDEO_DECODE DATA after " + "ps_out_buf->u4_num_bufs %d\n", + ps_out_buf->u4_num_bufs); + + printf("IVD_CMD_VIDEO_DECODE " + "s_video_decode_op.u4_num_bytes_consumed %d\n", + s_video_decode_op.u4_num_bytes_consumed); + + if (ret != IV_SUCCESS) + { + printf("Error in video Frame decode : ret %x Error %x\n", ret, + s_video_decode_op.u4_error_code); + } + + if (IV_B_FRAME == s_video_decode_op.e_pic_type) + s_app_ctx.b_pic_present |= 1; + + UWORD32 u4_num_bytes_dec = s_video_decode_op.u4_num_bytes_consumed; + + file_pos += u4_num_bytes_dec; + //total_bytes_comsumed += u4_num_bytes_dec; + u4_ip_frm_ts++; + printf("u4_ip_frm_ts:%d\n", u4_ip_frm_ts); + + printf( + "IVD_CMD_VIDEO_DECODE s_video_decode_op.u4_output_present %d\n", + s_video_decode_op.u4_output_present); + + if (1 == s_video_decode_op.u4_output_present) + { + CHAR cur_fname[1000]; + CHAR *extn = NULL; + /* The objective is to dump the decoded frames into separate files instead of + * dumping all the frames in one common file. Also, the number of dumped frames + * at any given instance of time cannot exceed 'frame_memory' + */ + if (s_app_ctx.u4_file_save_flag) + { + /* Locate the position of extension yuv */ + extn = strstr(s_app_ctx.ac_op_fname, "%d"); + if (extn != NULL) + { + /* Generate output file names */ + sprintf(cur_fname, s_app_ctx.ac_op_fname, u4_op_frm_ts); + /* Open Output file */ + ps_op_file = fopen(cur_fname, "wb"); + if (NULL == ps_op_file) + { + sprintf(ac_error_str, + "Could not open output file %s", cur_fname); + + codec_exit(ac_error_str); + } + } + } + + //width = s_video_decode_op.s_disp_frm_buf.u4_y_wd; + //height = s_video_decode_op.s_disp_frm_buf.u4_y_ht; + dump_output(&s_app_ctx, &(s_video_decode_op.s_disp_frm_buf), + s_video_decode_op.u4_disp_buf_id, ps_op_file, + ps_op_chksum_file, u4_op_frm_ts, + s_app_ctx.u4_file_save_flag, + s_app_ctx.u4_chksum_save_flag); + + u4_op_frm_ts++; + if (extn != NULL) + fclose(ps_op_file); + + } else + { + if ((s_video_decode_op.u4_error_code >> IVD_FATALERROR) & 1) + { + printf("Fatal error\n"); + break; + } + } + } + + break; + } + + /***********************************************************************/ + /* To get the last decoded frames, call process with NULL input */ + /***********************************************************************/ + /*flush_output(codec_obj, &s_app_ctx, ps_out_buf, + pu1_bs_buf, &u4_op_frm_ts, + ps_op_file, ps_op_chksum_file, + u4_ip_frm_ts, u4_bytes_remaining); + + s_app_ctx.quit = 1;*/ + + /***********************************************************************/ + /* Clear the decoder, close all the files, free all the memory */ + /***********************************************************************/ + + { + ivd_delete_ip_t s_delete_dec_ip; + ivd_delete_op_t s_delete_dec_op; + + s_delete_dec_ip.e_cmd = IVD_CMD_DELETE; + s_delete_dec_ip.u4_size = sizeof(ivd_delete_ip_t); + s_delete_dec_op.u4_size = sizeof(ivd_delete_op_t); + + printf("\n ivd_api_function IVD_CMD_DELETE\n"); + + ret = ivd_api_function((iv_obj_t *)codec_obj, (void *)&s_delete_dec_ip, + (void *)&s_delete_dec_op); + + if (IV_SUCCESS != ret) + { + sprintf(ac_error_str, "Error in Codec delete"); + codec_exit(ac_error_str); + } + } + /***********************************************************************/ + /* Close all the files and free all the memory */ + /***********************************************************************/ + { + fclose(ps_ip_file); + + if ((1 == s_app_ctx.u4_file_save_flag) && + (strstr(s_app_ctx.ac_op_fname, "%d") == NULL)) + { + fclose(ps_op_file); + } + if (1 == s_app_ctx.u4_chksum_save_flag) + { + fclose(ps_op_chksum_file); + } + } + + if (0 == s_app_ctx.u4_share_disp_buf) + { + free(ps_out_buf->pu1_bufs[0]); + } + + for (i = 0; i < s_app_ctx.num_disp_buf; i++) + { + free(s_app_ctx.s_disp_buffers[i].pu1_bufs[0]); + } + + free(ps_out_buf); + free(pu1_bs_buf); + + return (0); +} diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/init_rsrc.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/init_rsrc.c index e0dbc1f7..15c88e42 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/init_rsrc.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/init_rsrc.c @@ -34,7 +34,7 @@ #include #include -#ifdef __linux__ +#if __linux__ || __APPLE__ #include #include #elif _WIN32 @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) int should_match_rev = 1; int opt; int timeout_seconds = 0; - ni_log_level_t log_level; + ni_log_level_t log_level = NI_LOG_INFO; // arg handling while ((opt = getopt(argc, argv, "hrt:l:v")) != -1) @@ -102,11 +102,12 @@ int main(int argc, char *argv[]) } break; case 'v': - printf("Ver: %s\n" - "Date: %s\n" - "ID: %s\n", - NI_XCODER_REVISION, NI_SW_RELEASE_TIME, - NI_SW_RELEASE_ID); + printf("Release ver: %s\n" + "API ver: %s\n" + "Date: %s\n" + "ID: %s\n", + NI_XCODER_REVISION, LIBXCODER_API_VERSION, + NI_SW_RELEASE_TIME, NI_SW_RELEASE_ID); return 0; default: fprintf(stderr, "FATAL: invalid arg '%c'\n", opt); @@ -114,7 +115,7 @@ int main(int argc, char *argv[]) } } -#ifdef __linux__ +#if __linux__ || __APPLE__ return ni_rsrc_init(should_match_rev, timeout_seconds); #elif _WIN32 ni_retcode_t retval = ni_rsrc_init(should_match_rev, timeout_seconds); diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_av_codec.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_av_codec.c index 047102de..1aa0903d 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_av_codec.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_av_codec.c @@ -25,13 +25,7 @@ * \brief NETINT audio/video related utility functions * *******************************************************************************/ -#ifdef _WIN32 -#include -#include -#pragma comment(lib, "wsock32.lib") -#elif __linux__ -#include -#endif + #include #include #include @@ -284,33 +278,33 @@ void ni_dec_retrieve_aux_data(ni_frame_t *frame) // HEVC uses a g,b,r ordering, which we convert to a more natural r, // g,b,this is so we are compatible with FFmpeg default soft decoder mdm->display_primaries[0][0].num = - ntohs(pColourVolume->display_primaries[2][0]); + ni_ntohs(pColourVolume->display_primaries[2][0]); mdm->display_primaries[0][0].den = chroma_den; mdm->display_primaries[0][1].num = - ntohs(pColourVolume->display_primaries[2][1]); + ni_ntohs(pColourVolume->display_primaries[2][1]); mdm->display_primaries[0][1].den = chroma_den; mdm->display_primaries[1][0].num = - ntohs(pColourVolume->display_primaries[0][0]); + ni_ntohs(pColourVolume->display_primaries[0][0]); mdm->display_primaries[1][0].den = chroma_den; mdm->display_primaries[1][1].num = - ntohs(pColourVolume->display_primaries[0][1]); + ni_ntohs(pColourVolume->display_primaries[0][1]); mdm->display_primaries[1][1].den = chroma_den; mdm->display_primaries[2][0].num = - ntohs(pColourVolume->display_primaries[1][0]); + ni_ntohs(pColourVolume->display_primaries[1][0]); mdm->display_primaries[2][0].den = chroma_den; mdm->display_primaries[2][1].num = - ntohs(pColourVolume->display_primaries[1][1]); + ni_ntohs(pColourVolume->display_primaries[1][1]); mdm->display_primaries[2][1].den = chroma_den; - mdm->white_point[0].num = ntohs(pColourVolume->white_point_x); + mdm->white_point[0].num = ni_ntohs(pColourVolume->white_point_x); mdm->white_point[0].den = chroma_den; - mdm->white_point[1].num = ntohs(pColourVolume->white_point_y); + mdm->white_point[1].num = ni_ntohs(pColourVolume->white_point_y); mdm->white_point[1].den = chroma_den; mdm->min_luminance.num = - ntohl(pColourVolume->min_display_mastering_luminance); + ni_ntohl(pColourVolume->min_display_mastering_luminance); mdm->min_luminance.den = luma_den; mdm->max_luminance.num = - ntohl(pColourVolume->max_display_mastering_luminance); + ni_ntohl(pColourVolume->max_display_mastering_luminance); mdm->max_luminance.den = luma_den; mdm->has_luminance = mdm->has_primaries = 1; @@ -338,8 +332,8 @@ void ni_dec_retrieve_aux_data(ni_frame_t *frame) *)((uint8_t *)frame->p_data[start_offset] + frame->sei_hdr_content_light_level_info_offset); - clm->max_cll = ntohs(pLightLevel->max_content_light_level); - clm->max_fall = ntohs(pLightLevel->max_pic_average_light_level); + clm->max_cll = ni_ntohs(pLightLevel->max_content_light_level); + clm->max_fall = ni_ntohs(pLightLevel->max_pic_average_light_level); } } @@ -960,8 +954,7 @@ void ni_enc_prep_aux_data(ni_session_context_t *p_enc_ctx, // save a copy if (!p_enc_ctx->p_master_display_meta_data) { - p_enc_ctx->p_master_display_meta_data = - malloc(sizeof(ni_mastering_display_metadata_t)); + p_enc_ctx->p_master_display_meta_data = malloc(sizeof(ni_mastering_display_metadata_t)); } if (!p_enc_ctx->p_master_display_meta_data) { @@ -973,11 +966,11 @@ void ni_enc_prep_aux_data(ni_session_context_t *p_enc_ctx, const int luma_den = 10000; - uint32_t uint32_t_tmp = htonl( + uint32_t uint32_t_tmp = ni_htonl( (uint32_t)(lrint(luma_den * ni_q2d(p_src->max_luminance)))); memcpy(p_enc_ctx->ui8_mdcv_max_min_lum_data, &uint32_t_tmp, sizeof(uint32_t)); - uint32_t_tmp = htonl( + uint32_t_tmp = ni_htonl( (uint32_t)(lrint(luma_den * ni_q2d(p_src->min_luminance)))); memcpy(p_enc_ctx->ui8_mdcv_max_min_lum_data + 4, &uint32_t_tmp, sizeof(uint32_t)); @@ -1030,27 +1023,27 @@ void ni_enc_prep_aux_data(ni_session_context_t *p_enc_ctx, // when sent to encoder dp00 = (uint16_t)lrint(chroma_den * ni_q2d(p_src->display_primaries[1][0])); - p_mdcv->display_primaries[0][0] = htons(dp00); + p_mdcv->display_primaries[0][0] = ni_htons(dp00); dp01 = (uint16_t)lrint(chroma_den * ni_q2d(p_src->display_primaries[1][1])); - p_mdcv->display_primaries[0][1] = htons(dp01); + p_mdcv->display_primaries[0][1] = ni_htons(dp01); dp10 = (uint16_t)lrint(chroma_den * ni_q2d(p_src->display_primaries[2][0])); - p_mdcv->display_primaries[1][0] = htons(dp10); + p_mdcv->display_primaries[1][0] = ni_htons(dp10); dp11 = (uint16_t)lrint(chroma_den * ni_q2d(p_src->display_primaries[2][1])); - p_mdcv->display_primaries[1][1] = htons(dp11); + p_mdcv->display_primaries[1][1] = ni_htons(dp11); dp20 = (uint16_t)lrint(chroma_den * ni_q2d(p_src->display_primaries[0][0])); - p_mdcv->display_primaries[2][0] = htons(dp20); + p_mdcv->display_primaries[2][0] = ni_htons(dp20); dp21 = (uint16_t)lrint(chroma_den * ni_q2d(p_src->display_primaries[0][1])); - p_mdcv->display_primaries[2][1] = htons(dp21); + p_mdcv->display_primaries[2][1] = ni_htons(dp21); wpx = (uint16_t)lrint(chroma_den * ni_q2d(p_src->white_point[0])); - p_mdcv->white_point_x = htons(wpx); + p_mdcv->white_point_x = ni_htons(wpx); wpy = (uint16_t)lrint(chroma_den * ni_q2d(p_src->white_point[1])); - p_mdcv->white_point_y = htons(wpy); + p_mdcv->white_point_y = ni_htons(wpy); ni_log(NI_LOG_DEBUG, "mastering display color volume, primaries " @@ -1089,9 +1082,9 @@ void ni_enc_prep_aux_data(ni_session_context_t *p_enc_ctx, } uint16_t max_content_light_level = - htons(((ni_content_light_level_t *)aux_data->data)->max_cll); + ni_htons(((ni_content_light_level_t *)aux_data->data)->max_cll); uint16_t max_pic_average_light_level = - htons(((ni_content_light_level_t *)aux_data->data)->max_fall); + ni_htons(((ni_content_light_level_t *)aux_data->data)->max_fall); ni_log(NI_LOG_DEBUG, "content light level info, MaxCLL %u MaxFALL %u\n", ((ni_content_light_level_t *)aux_data->data)->max_cll, @@ -1666,9 +1659,9 @@ void ni_enc_prep_aux_data(ni_session_context_t *p_enc_ctx, p_enc_frame->extra_data_len += p_enc_ctx->roi_len; ni_log(NI_LOG_DEBUG, "ni_enc_prep_aux_data: supply QP map, cacheRoi %d " - "aux_data %d ctx->roi_map %d frame->roi_len %u\n", + "aux_data %d ctx->roi_map %d frame->roi_len %u ctx->roi_len %u\n", api_params->cacheRoi, aux_data != NULL, - p_enc_ctx->roi_map != NULL, p_enc_frame->roi_len); + p_enc_ctx->roi_map != NULL, p_enc_frame->roi_len, p_enc_ctx->roi_len); } // prep for NetInt long term reference frame support setting: when this has @@ -1743,6 +1736,85 @@ void ni_enc_prep_aux_data(ni_session_context_t *p_enc_ctx, ni_log(NI_LOG_DEBUG, "%s(): API force IDR frame\n", __func__); } + // prep for NetInt VUI reconfiguration support: when VUI HRD + // setting has been requested by both frame and API, API takes priority + ni_vui_hrd_t vui = {0}; + aux_data = ni_frame_get_aux_data(p_dec_frame, NI_FRAME_AUX_DATA_VUI); + if (aux_data) + { + ni_vui_hrd_t *aux_vui_ptr = (ni_vui_hrd_t *)aux_data->data; + + if (aux_vui_ptr->colorDescPresent < 0 || aux_vui_ptr->colorDescPresent > 1) + { + ni_log(NI_LOG_ERROR, "ERROR: %s(): invalid colorDescPresent in aux data %d\n", + __func__, aux_vui_ptr->colorDescPresent); + } + else + { + vui.colorDescPresent = aux_vui_ptr->colorDescPresent; + } + + if((aux_vui_ptr->aspectRatioWidth > NI_MAX_ASPECTRATIO) || (aux_vui_ptr->aspectRatioHeight > NI_MAX_ASPECTRATIO)) + { + ni_log(NI_LOG_ERROR, "ERROR: %s(): invalid aspect ratio in aux data %dx%d\n", + __func__, aux_vui_ptr->aspectRatioWidth, aux_vui_ptr->aspectRatioHeight); + } + else + { + vui.colorDescPresent = aux_vui_ptr->colorDescPresent; + vui.colorPrimaries = aux_vui_ptr->colorPrimaries; + vui.colorTrc = aux_vui_ptr->colorTrc; + vui.colorSpace = aux_vui_ptr->colorSpace; + vui.aspectRatioWidth = aux_vui_ptr->aspectRatioWidth; + vui.aspectRatioHeight = aux_vui_ptr->aspectRatioHeight; + } + + if (aux_vui_ptr->videoFullRange < 0 || aux_vui_ptr->videoFullRange > 1) + { + ni_log(NI_LOG_ERROR, "ERROR: %s(): invalid videoFullRange in aux data %d\n", + __func__, aux_vui_ptr->videoFullRange); + } + else + { + vui.videoFullRange = aux_vui_ptr->videoFullRange; + } + } + + if (p_enc_ctx->vui.aspectRatioWidth > 0) + { + vui = p_enc_ctx->vui; + p_enc_ctx->vui.colorDescPresent = + p_enc_ctx->vui.colorPrimaries = + p_enc_ctx->vui.colorTrc = + p_enc_ctx->vui.colorSpace = + p_enc_ctx->vui.aspectRatioWidth = + p_enc_ctx->vui.aspectRatioHeight = + p_enc_ctx->vui.videoFullRange = 0; + ni_log(NI_LOG_DEBUG, "%s(): API set VUI " + "colorDescPresent %d colorPrimaries %d " + "colorTrc %d colorSpace %d aspectRatioWidth %d " + "aspectRatioHeight %d videoFullRange %d\n", + __func__, vui.colorDescPresent, + vui.colorPrimaries, vui.colorTrc, + vui.colorSpace, vui.aspectRatioWidth, + vui.aspectRatioHeight, vui.videoFullRange); + } + + if (vui.aspectRatioWidth > 0) + { + p_enc_ctx->enc_change_params->enable_option |= + NI_SET_CHANGE_PARAM_VUI_HRD_PARAM; + + p_enc_ctx->enc_change_params->colorDescPresent = vui.colorDescPresent; + p_enc_ctx->enc_change_params->colorPrimaries = vui.colorPrimaries; + p_enc_ctx->enc_change_params->colorTrc = vui.colorTrc; + p_enc_ctx->enc_change_params->colorSpace = vui.colorSpace; + p_enc_ctx->enc_change_params->aspectRatioWidth = vui.aspectRatioWidth; + p_enc_ctx->enc_change_params->aspectRatioHeight = vui.aspectRatioHeight; + p_enc_ctx->enc_change_params->videoFullRange = vui.videoFullRange; + p_enc_frame->reconf_len = sizeof(ni_encoder_change_params_t); + } + // prep for NetInt long term reference interval reconfiguration support: // when LTR has been requested by both frame and API, API takes priority int32_t ltr_interval = -1; diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_av_codec.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_av_codec.h index bb18e079..9e5ed8a1 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_av_codec.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_av_codec.h @@ -449,29 +449,6 @@ LIB_API int ni_should_send_sei_with_frame(ni_session_context_t *p_enc_ctx, ni_pic_type_t pic_type, ni_xcoder_params_t *p_param); -/*!***************************************************************************** - * \brief Set SPS VUI part of encoded stream header - * - * \param[in/out] p_param encoder parameters, its VUI data member will be - * updated. - * \param[in] color_primaries color primaries - * \param[in] color_trc color transfer characteristic - * \param[in] color_space YUV colorspace type - * \param[in] video_full_range_flag - * \param[in] sar_num/sar_den sample aspect ration in numerator/denominator - * \param[in] codec_format H.264 or H.265 - * \param[out] hrd_params struct for HRD parameters, may be updated. - * - * \return NONE - ******************************************************************************/ -LIB_API void ni_set_vui(ni_xcoder_params_t *p_param, - ni_color_primaries_t color_primaries, - ni_color_transfer_characteristic_t color_trc, - ni_color_space_t color_space, int video_full_range_flag, - int sar_num, int sar_den, - ni_codec_format_t codec_format, - ni_hrd_params_t *hrd_params); - /*!***************************************************************************** * \brief Retrieve auxiliary data (close caption, various SEI) associated with * this frame that is returned by decoder, convert them to appropriate diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_bitstream.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_bitstream.h index a3b80a62..c88eb189 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_bitstream.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_bitstream.h @@ -43,6 +43,20 @@ extern "C" { #endif +#ifdef _WIN32 + #ifdef XCODER_DLL + #ifdef LIB_EXPORTS + #define LIB_API_BITSTREAM __declspec(dllexport) + #else + #define LIB_API_BITSTREAM __declspec(dllimport) + #endif + #else + #define LIB_API_BITSTREAM + #endif +#elif __linux__ || __APPLE__ + #define LIB_API_BITSTREAM +#endif + // the following is for bitstream put operations #define NI_DATA_CHUNK_SIZE 4096 @@ -112,26 +126,26 @@ typedef struct _ni_bitstream_reader_t } ni_bitstream_reader_t; // bitstream reader init -void ni_bitstream_reader_init(ni_bitstream_reader_t *br, const uint8_t *data, +LIB_API_BITSTREAM void ni_bitstream_reader_init(ni_bitstream_reader_t *br, const uint8_t *data, int bit_size); // return number of bits already parsed -int ni_bs_reader_bits_count(ni_bitstream_reader_t *br); +LIB_API_BITSTREAM int ni_bs_reader_bits_count(ni_bitstream_reader_t *br); // return number of bits left to parse -int ni_bs_reader_get_bits_left(ni_bitstream_reader_t *br); +LIB_API_BITSTREAM int ni_bs_reader_get_bits_left(ni_bitstream_reader_t *br); // skip a number of bits ahead in the bitstream reader -void ni_bs_reader_skip_bits(ni_bitstream_reader_t *br, int n); +LIB_API_BITSTREAM void ni_bs_reader_skip_bits(ni_bitstream_reader_t *br, int n); // read bits (up to 32) from the bitstream reader, after reader init -uint32_t ni_bs_reader_get_bits(ni_bitstream_reader_t *br, int n); +LIB_API_BITSTREAM uint32_t ni_bs_reader_get_bits(ni_bitstream_reader_t *br, int n); // read an unsigned Exp-Golomb code ue(v) -uint32_t ni_bs_reader_get_ue(ni_bitstream_reader_t *br); +LIB_API_BITSTREAM uint32_t ni_bs_reader_get_ue(ni_bitstream_reader_t *br); // read a signed Exp-Golomb code se(v) -int32_t ni_bs_reader_get_se(ni_bitstream_reader_t *br); +LIB_API_BITSTREAM int32_t ni_bs_reader_get_se(ni_bitstream_reader_t *br); #ifdef __cplusplus } diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_defs.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_defs.h index 8f23aefc..69a08ad0 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_defs.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_defs.h @@ -32,11 +32,14 @@ #include #include #include -#elif __linux__ +#elif __linux__ || __APPLE__ +#if __linux__ #include +#endif #include #include #include +#include #endif #include @@ -56,15 +59,44 @@ extern "C" { #endif -// NI_XCODER_REVISION[0:2] = SW version -// NI_XCODER_REVISION[3] = API semantic major version -// NI_XCODER_REVISION[4] = API semantic minor version +#if !defined(NI_WARN_AS_ERROR) && !defined(__clang__) && defined(__GNUC__) + #define NI_DEPRECATED __attribute__((deprecated)) + #define NI_DEPRECATED_MACRO \ + _Pragma("GCC warning \"A Netint macro on this line is deprecated\"") + #define NI_DEPRECATE_MACRO(X) +#elif !defined(NI_WARN_AS_ERROR) && !defined(__clang__) && defined(_MSC_VER) + #define NI_DEPRECATED __declspec(deprecated) + #define NI_DEPRECATED_MACRO + #define NI_DEPRECATE_MACRO(X) __pragma(deprecated(X)) +#else + #define NI_DEPRECATED + #define NI_DEPRECATED_MACRO + #define NI_DEPRECATE_MACRO(X) +#endif + +// NI_XCODER_REVISION can be read to determine release package version and FW to +// SW compatibility. Recommend using ni_get_*_ver() functions in ni_util.h to +// read correct version numbers if updating libxcoder but not linked apps. +// NI_XCODER_REVISION[0:2] = SW release version +// NI_XCODER_REVISION[3] = compatible FW API semantic major version +// NI_XCODER_REVISION[4] = compatible FW API semantic minor version // NI_XCODER_REVISION[5:7] = optional // reference: https://netint.atlassian.net/l/c/woqFMHES -#define NI_XCODER_REVISION "30052rc2" +#define NI_XCODER_REVISION "40064rcB" #define NI_XCODER_REVISION_API_MAJOR_VER_IDX 3 #define NI_XCODER_REVISION_API_MINOR_VER_IDX 4 +// LIBXCODER_API_VERSION can be read to determine libxcoder to linked apps/APIs +// compatibility. Recommend using ni_get_*_ver() functions in ni_util.h to +// read correct version numbers if updating libxcoder but not linked apps. +// reference: https://netint.atlassian.net/l/c/fVEGmYEZ +#define MACRO_TO_STR(s) #s +#define MACROS_TO_VER_STR(a, b) MACRO_TO_STR(a.b) +#define LIBXCODER_API_VERSION_MAJOR 2 // Libxcoder API semantic major version +#define LIBXCODER_API_VERSION_MINOR 4 // Libxcoder API semantic minor version +#define LIBXCODER_API_VERSION MACROS_TO_VER_STR(LIBXCODER_API_VERSION_MAJOR, \ + LIBXCODER_API_VERSION_MINOR) + #define NI_LITTLE_ENDIAN_PLATFORM 0 /*!!< platform is little endian */ #define NI_BIG_ENDIAN_PLATFORM 1 /*!!< platform is big endian */ @@ -100,7 +132,7 @@ typedef HANDLE ni_lock_handle_t; #define NI_INVALID_DEVICE_HANDLE (INVALID_HANDLE_VALUE) #define NI_INVALID_EVENT_HANDLE (NULL) #define NI_INVALID_LOCK_HANDLE (NULL) -#ifdef LIB_DLL +#ifdef XCODER_DLL #ifdef LIB_EXPORTS #define LIB_API __declspec(dllexport) #else @@ -142,6 +174,23 @@ typedef int32_t ni_lock_handle_t; MIN_NVME_DEV_NAME_LEN + 10) #define DEFAULT_IO_TRANSFER_SIZE 520192 #define MAX_IO_TRANSFER_SIZE 3133440 + +#elif __APPLE__ +typedef pthread_t ni_pthread_t; +typedef pthread_mutex_t ni_pthread_mutex_t; +typedef pthread_cond_t ni_pthread_cond_t; +typedef pthread_attr_t ni_pthread_attr_t; +typedef pthread_condattr_t ni_pthread_condattr_t; +typedef pthread_mutexattr_t ni_pthread_mutexattr_t; +typedef sigset_t ni_sigset_t; +typedef int32_t ni_device_handle_t; +typedef int32_t ni_event_handle_t; +typedef int32_t ni_lock_handle_t; +#define NI_INVALID_DEVICE_HANDLE (-1) +#define NI_INVALID_EVENT_HANDLE (-1) +#define NI_INVALID_LOCK_HANDLE (-1) +#define LIB_API +#define MAX_IO_TRANSFER_SIZE 3133440 #endif /* _WIN32 */ // number of system last error @@ -175,11 +224,26 @@ typedef int32_t ni_lock_handle_t; #define NI_MEM_PAGE_ALIGNMENT 0x1000 -#define NI_MAX_HWDESC_FRAME_INDEX 2681 +#define NI_MAX_DR_HWDESC_FRAME_INDEX 5363 + // If P2P area changes in firmware these constants must be updated +#define NI_MIN_HWDESC_P2P_BUF_ID 5364 +#define NI_MAX_HWDESC_P2P_BUF_ID 5525 +#define NI_MAX_SR_HWDESC_FRAME_INDEX 2457 // If P2P area changes in firmware these constants must be updated -#define NI_MIN_HWDESC_P2P_BUF_ID 2682 -#define NI_MAX_HWDESC_P2P_BUF_ID 2828 +#define NI_MIN_SR_HWDESC_P2P_BUF_ID 2458 +#define NI_MAX_SR_HWDESC_P2P_BUF_ID 2619 + + //Feed this ni_session_context_t->ddr_config +#define NI_GET_MIN_HWDESC_P2P_BUF_ID(x) (x==1?NI_MIN_SR_HWDESC_P2P_BUF_ID:NI_MIN_HWDESC_P2P_BUF_ID) +#define NI_GET_MAX_HWDESC_P2P_BUF_ID(x) (x==1?NI_MAX_SR_HWDESC_P2P_BUF_ID:NI_MAX_HWDESC_P2P_BUF_ID) + +//use NI_MAX_DR_HWDESC_FRAME_INDEX or NI_GET_MAX_HWDESC_FRAME_INDEX +NI_DEPRECATE_MACRO(NI_MAX_HWDESC_FRAME_INDEX) +#define NI_MAX_HWDESC_FRAME_INDEX NI_DEPRECATED_MACRO NI_MAX_DR_HWDESC_FRAME_INDEX + +//input param is DDR config of target device +#define NI_GET_MAX_HWDESC_FRAME_INDEX(x) (x==1?NI_MAX_SR_HWDESC_FRAME_INDEX:NI_MAX_DR_HWDESC_FRAME_INDEX) #define NI_MAX_UPLOAD_INSTANCE_FRAMEPOOL 100 @@ -197,6 +261,9 @@ typedef int32_t ni_lock_handle_t; // invalid sei type #define NI_INVALID_SEI_TYPE (-1) +// max count of custom sei per packet +#define NI_MAX_CUSTOM_SEI_CNT 10 + //bytes size of meta data sent together with YUV: from f/w decoder to app #define NI_FW_META_DATA_SZ 104 //metadataDecFrame on dec FW (including hwdesc x3) // size of meta data sent together with YUV data: from app to f/w encoder @@ -352,6 +419,7 @@ inline int is_supported_xcoder(int x) -60, /*!!< invalid lookahead depth */ NI_RETCODE_PARAM_ERROR_FILLER = -61, NI_RETCODE_PARAM_ERROR_PICSKIP = -62, + NI_RETCODE_ERROR_UNSUPPORTED_FW_VERSION = -63, NI_RETCODE_PARAM_WARN = 0x100, /*!! +#endif #include #include #include @@ -59,6 +61,7 @@ #include "ni_util.h" #include "ni_rsrc_api.h" #include "ni_rsrc_priv.h" +#include "ni_lat_meas.h" #ifndef _WIN32 #include "ni_p2p_ioctl.h" #endif @@ -73,7 +76,7 @@ const char *const g_xcoder_log_names[NI_XCODER_LOG_NAMES_ARRAY_LEN] = { NI_XCODER_LOG_NAME_DEBUG, NI_XCODER_LOG_NAME_FULL, 0}; -#ifdef __linux__ +#if __linux__ || __APPLE__ static struct stat g_nvme_stat = { 0 }; #endif @@ -92,12 +95,14 @@ ni_session_context_t *ni_device_session_context_alloc_init(void) if (!p_ctx) { ni_log(NI_LOG_ERROR, - "ERROR: Failed to allocate memory for session context\n"); + "ERROR: %s() Failed to allocate memory for session context\n", + __func__); } else { if (ni_device_session_context_init(p_ctx) != NI_RETCODE_SUCCESS) { - ni_log(NI_LOG_ERROR, "ERROR: Failed to init session context\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Failed to init session context\n", + __func__); ni_device_session_context_free(p_ctx); return NULL; } @@ -117,6 +122,12 @@ void ni_device_session_context_free(ni_session_context_t *p_ctx) if (p_ctx) { ni_device_session_context_clear(p_ctx); +#ifdef MEASURE_LATENCY + if (p_ctx->frame_time_q) + { + ni_lat_meas_q_destroy(p_ctx->frame_time_q); + } +#endif // cppcheck-suppress uselessAssignmentPtrArg ni_aligned_free(p_ctx); } @@ -162,6 +173,7 @@ ni_retcode_t ni_device_session_context_init(ni_session_context_t *p_ctx) p_ctx->xcoder_state = NI_XCODER_IDLE_STATE; p_ctx->keep_alive_thread = (ni_pthread_t){0}; p_ctx->keep_alive_timeout = NI_DEFAULT_KEEP_ALIVE_TIMEOUT; + p_ctx->decoder_low_delay = 0; #ifdef MY_SAVE p_ctx->debug_write_ptr = NULL; p_ctx->debug_write_index_ptr = NULL; @@ -169,7 +181,7 @@ ni_retcode_t ni_device_session_context_init(ni_session_context_t *p_ctx) #endif #ifdef MEASURE_LATENCY - p_ctx->frame_time_q = ni_lat_meas_q_create(2000); + p_ctx->frame_time_q = (void *)ni_lat_meas_q_create(2000); p_ctx->prev_read_frame_time = 0; #endif return NI_RETCODE_SUCCESS; @@ -197,7 +209,6 @@ ni_event_handle_t ni_create_event() { #ifdef _WIN32 ni_event_handle_t event_handle = NI_INVALID_EVENT_HANDLE; - DWORD retval; // Input-0 determines whether the returned handle can be inherited by the child process.If lpEventAttributes is NULL, this handle cannot be inherited. // Input-1 specifies whether the event object is created to be restored manually or automatically.If set to FALSE, when a thread waits for an event signal, the system automatically restores the event state to a non-signaled state. @@ -206,8 +217,8 @@ ni_event_handle_t ni_create_event() event_handle = CreateEvent(NULL, FALSE, FALSE, NULL); if (event_handle == NULL) { - retval = NI_ERRNO; - ni_log(NI_LOG_ERROR, "ERROR %d: create event failed\n", retval); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() create event failed\n", + NI_ERRNO, __func__); return NI_INVALID_EVENT_HANDLE; } return event_handle; @@ -333,14 +344,23 @@ ni_device_handle_t ni_device_open(const char * p_dev, uint32_t * p_max_io_size_o if (*p_max_io_size_out == NI_INVALID_IO_SIZE) { - *p_max_io_size_out = ni_get_kernel_max_io_size(p_dev); + #if __linux__ + *p_max_io_size_out = ni_get_kernel_max_io_size(p_dev); + #elif __APPLE__ + *p_max_io_size_out = MAX_IO_TRANSFER_SIZE; + #endif } ni_log(NI_LOG_DEBUG, "%s: opening regular-io enabled %s\n", __func__, p_dev); //O_SYNC is added to ensure that data is written to the card when the pread/pwrite function returns - //O_DIRECT is added to ensure that data can be sent directly to the card instead of to cache memory - fd = open(p_dev, O_RDWR | O_SYNC | O_DIRECT); + #if __linux__ + //O_DIRECT is added to ensure that data can be sent directly to the card instead of to cache memory + fd = open(p_dev, O_RDWR | O_SYNC | O_DIRECT); + #elif __APPLE__ + //O_DIRECT isn't available, so instead we use F_NOCACHE below + fd = open(p_dev, O_RDWR | O_SYNC); + #endif if (fd < 0) { @@ -350,6 +370,19 @@ ni_device_handle_t ni_device_open(const char * p_dev, uint32_t * p_max_io_size_o LRETURN; } + #if __APPLE__ + //F_NOCACHE is set to ensure that data can be sent directly to the card instead of to cache memory + retval = fcntl(fd, F_NOCACHE, 1); + if (retval < 0) + { + ni_log(NI_LOG_ERROR, "ERROR: fnctl() failed on %s\n", p_dev); + ni_log(NI_LOG_ERROR, "ERROR: ni_device_open() failed!\n"); + close(fd); + fd = NI_INVALID_DEVICE_HANDLE; + LRETURN; + } + #endif + retval = fstat(fd, &g_nvme_stat); if (retval < 0) { @@ -477,7 +510,8 @@ ni_retcode_t ni_device_capability_query(ni_device_handle_t device_handle, ni_dev if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_NVME_IDENTITY_CMD_DATA_SZ)) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): Cannot allocate buffer.\n", __func__); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer.\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -537,7 +571,7 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, int least_model_load = 0; int least_instance = 0; int guid = -1; - int num_sw_instances = 0; + uint32_t num_sw_instances = 0; int user_handles = false; ni_lock_handle_t lock = NI_INVALID_LOCK_HANDLE; ni_device_handle_t handle = NI_INVALID_DEVICE_HANDLE; @@ -558,7 +592,9 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, if (NI_INVALID_SESSION_ID != p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: trying to overwrite existing session\n"); + ni_log(NI_LOG_ERROR, "ERROR: trying to overwrite existing session, " + "device_type %d, session id %d\n", + device_type, p_ctx->session_id); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -581,6 +617,13 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, p_ctx->ltr_frame_ref_invalid = -1; p_ctx->framerate.framerate_num = 0; p_ctx->framerate.framerate_denom = 0; + p_ctx->vui.colorDescPresent = 0; + p_ctx->vui.colorPrimaries = 0; + p_ctx->vui.colorTrc = 0; + p_ctx->vui.colorSpace = 0; + p_ctx->vui.aspectRatioWidth = 0; + p_ctx->vui.aspectRatioHeight = 0; + p_ctx->vui.videoFullRange = 0; p_ctx->keep_alive_thread_args = NULL; @@ -645,6 +688,7 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, if (((handle = ni_device_open(rsrc_ctx->p_device_info->blk_name, &dummy_io_size)) == NI_INVALID_DEVICE_HANDLE) || ((handle1 = ni_device_open(rsrc_ctx->p_device_info->blk_name, &p_ctx->max_nvme_io_size)) == NI_INVALID_DEVICE_HANDLE)) { + ni_rsrc_free_device_context(rsrc_ctx); retval = NI_RETCODE_ERROR_OPEN_DEVICE; LRETURN; } else @@ -705,6 +749,7 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, if (NI_INVALID_DEVICE_HANDLE == p_session_context.device_handle) { ni_log(NI_LOG_ERROR, "Error open device"); + ni_rsrc_free_device_context(p_device_context); continue; } @@ -721,6 +766,7 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, device_type_str[query_type], p_device_context->p_device_info->dev_name, p_device_context->p_device_info->hw_id); + ni_rsrc_free_device_context(p_device_context); continue; } ni_rsrc_update_record(p_device_context, &p_session_context); @@ -815,6 +861,27 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, p_ctx->dev_xcoder_name, p_ctx->blk_xcoder_name, p_ctx->hw_id, p_ctx->device_handle, p_ctx->blk_io_handle); + // get FW API version + p_device_context = ni_rsrc_get_device_context(device_type, p_ctx->hw_id); + if (p_device_context == NULL) + { + ni_log(NI_LOG_ERROR, + "ERROR: %s() ni_rsrc_get_device_context() failed\n", + __func__); + retval = NI_RETCODE_ERROR_OPEN_DEVICE; + LRETURN; + } + memcpy(p_ctx->fw_rev , p_device_context->p_device_info->fw_rev, 8); + + retval = ni_device_get_ddr_configuration(p_ctx); + if (retval != NI_RETCODE_SUCCESS) + { + ni_log(NI_LOG_ERROR, + "ERROR: %s() cannot retrieve DDR configuration\n", + __func__); + LRETURN; + } + switch (device_type) { case NI_DEVICE_TYPE_DECODER: @@ -939,7 +1006,8 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, } } retval = NI_RETCODE_INVALID_PARAM; - ni_log(NI_LOG_ERROR, "Unrecognized device type: %d", device_type); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unrecognized device type: %d", + __func__, device_type); LRETURN; } } @@ -969,6 +1037,7 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } + memset(p_ctx->keep_alive_thread_args->p_buffer, 0, NI_DATA_BUFFER_LEN); if (0 != ni_pthread_create(&p_ctx->keep_alive_thread, NULL, @@ -996,6 +1065,8 @@ ni_retcode_t ni_device_session_open(ni_session_context_t *p_ctx, END: + ni_rsrc_free_device_context(p_device_context); + if (p_device_pool) { ni_rsrc_free_device_pool(p_device_pool); @@ -1097,8 +1168,8 @@ ni_retcode_t ni_device_session_close(ni_session_context_t *p_ctx, default: { retval = NI_RETCODE_INVALID_PARAM; - ni_log(NI_LOG_ERROR, "ERROR: Unrecognized device type: %d\n", - device_type); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unrecognized device type: %d", + __func__, device_type); break; } } @@ -1172,7 +1243,8 @@ ni_retcode_t ni_device_session_flush(ni_session_context_t* p_ctx, ni_device_type default: { retval = NI_RETCODE_INVALID_PARAM; - ni_log(NI_LOG_ERROR, "ERROR: Unrecognized device type: %d", device_type); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unrecognized device type: %d", + __func__, device_type); break; } } @@ -1364,7 +1436,7 @@ int ni_device_session_write(ni_session_context_t *p_ctx, ni_session_data_io_t *p #ifdef _WIN32 (p_ctx->keep_alive_thread.handle && #else - (p_ctx->keep_alive_thread && + (p_ctx->keep_alive_thread && #endif p_ctx->keep_alive_thread_args->close_thread)) { @@ -1395,7 +1467,8 @@ int ni_device_session_write(ni_session_context_t *p_ctx, ni_session_data_io_t *p default: { retval = NI_RETCODE_INVALID_PARAM; - ni_log(NI_LOG_ERROR, "ERROR: Unrecognized device type: %d", device_type); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unrecognized device type: %d", + __func__, device_type); break; } } @@ -1466,7 +1539,7 @@ int ni_device_session_read(ni_session_context_t *p_ctx, ni_session_data_io_t *p_ #ifdef _WIN32 (p_ctx->keep_alive_thread.handle && #else - (p_ctx->keep_alive_thread && + (p_ctx->keep_alive_thread && #endif p_ctx->keep_alive_thread_args->close_thread)) { @@ -1553,7 +1626,8 @@ int ni_device_session_read(ni_session_context_t *p_ctx, ni_session_data_io_t *p_ default: { retval = NI_RETCODE_INVALID_PARAM; - ni_log(NI_LOG_ERROR, "ERROR: Unrecognized device type: %d", device_type); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unrecognized device type: %d", + __func__, device_type); break; } } @@ -1598,7 +1672,8 @@ ni_retcode_t ni_device_session_query(ni_session_context_t* p_ctx, ni_device_type } else { retval = NI_RETCODE_INVALID_PARAM; - ni_log(NI_LOG_ERROR, "ERROR: Unrecognized device type: %d", device_type); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unrecognized device type: %d", + __func__, device_type); } return retval; @@ -1643,8 +1718,9 @@ ni_retcode_t ni_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, || (video_width>NI_MAX_RESOLUTION_WIDTH) || (video_width<=0) || (video_height>NI_MAX_RESOLUTION_HEIGHT) || (video_height<=0)) { - ni_log(NI_LOG_ERROR, "ERROR: %s passed parameters are null, return\n", - __func__); + ni_log(NI_LOG_ERROR, "ERROR: %s passed parameters are null or not supported, " + "factor %d, video_width %d, video_height %d\n", + __func__, factor, video_width, video_height); return NI_RETCODE_INVALID_PARAM; } @@ -1733,7 +1809,8 @@ ni_retcode_t ni_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, { if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate p_frame buffer.\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -1765,10 +1842,10 @@ ni_retcode_t ni_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, p_frame->data_len[3] = 0;//unused by hwdesc } - p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer; - p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + p_frame->data_len[0]; - p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + p_frame->data_len[1]; - p_frame->p_data[3] = (uint8_t*)p_frame->p_data[2] + p_frame->data_len[2]; //hwdescriptor + p_frame->p_data[0] = p_frame->p_buffer; + p_frame->p_data[1] = p_frame->p_data[0] + p_frame->data_len[0]; + p_frame->p_data[2] = p_frame->p_data[1] + p_frame->data_len[1]; + p_frame->p_data[3] = p_frame->p_data[2] + p_frame->data_len[2]; //hwdescriptor // init p_data[3] to 0 so that ni_frame_buffer_free frees only valid DMA buf // fd in hw frame read from fw @@ -1794,6 +1871,192 @@ ni_retcode_t ni_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, return retval; } +/*!***************************************************************************** + * \brief Allocate preliminary memory for the frame buffer based on provided + * parameters. + * + * \param[in] p_frame Pointer to a caller allocated + * ni_frame_t struct + * \param[in] video_width Width of the video frame + * \param[in] video_height Height of the video frame + * \param[in] alignment Allignment requirement + * \param[in] pixel_format Format for input + * + * \return On success + * NI_RETCODE_SUCCESS + * On failure + * NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_MEM_ALOC + ******************************************************************************/ +ni_retcode_t ni_frame_buffer_alloc_dl(ni_frame_t *p_frame, int video_width, + int video_height, int pixel_format) +{ + void *p_buffer = NULL; + int retval = NI_RETCODE_SUCCESS; + int width_aligned = video_width; + int height_aligned = video_height; + int buffer_size; + int luma_size; + int chroma_b_size; + int chroma_r_size; + + if ((!p_frame) || (video_width > NI_MAX_RESOLUTION_WIDTH) || + (video_width <= 0) || (video_height > NI_MAX_RESOLUTION_HEIGHT) || + (video_height <= 0)) + { + ni_log(NI_LOG_ERROR, + "ERROR: %s passed parameters are null or not supported, " + "video_width %d, video_height %d\n", + __func__, video_width, video_height); + return NI_RETCODE_INVALID_PARAM; + } + + switch (pixel_format) + { + case NI_PIX_FMT_YUV420P: + width_aligned = NI_VPU_ALIGN128(video_width); + height_aligned = NI_VPU_CEIL(video_height, 2); + + luma_size = width_aligned * height_aligned; + chroma_b_size = + NI_VPU_ALIGN128(video_width / 2) * height_aligned / 2; + chroma_r_size = chroma_b_size; + break; + case NI_PIX_FMT_YUV420P10LE: + width_aligned = NI_VPU_ALIGN128(video_width * 2) / 2; + height_aligned = NI_VPU_CEIL(video_height, 2); + + luma_size = width_aligned * height_aligned * 2; + chroma_b_size = NI_VPU_ALIGN128(video_width) * height_aligned / 2; + chroma_r_size = chroma_b_size; + break; + case NI_PIX_FMT_NV12: + width_aligned = NI_VPU_ALIGN128(video_width); + height_aligned = NI_VPU_CEIL(video_height, 2); + + luma_size = width_aligned * height_aligned; + chroma_b_size = width_aligned * height_aligned / 2; + chroma_r_size = 0; + break; + case NI_PIX_FMT_P010LE: + width_aligned = NI_VPU_ALIGN128(video_width * 2) / 2; + height_aligned = NI_VPU_CEIL(video_height, 2); + + luma_size = width_aligned * height_aligned * 2; + chroma_b_size = NI_VPU_ALIGN128(video_width) * height_aligned; + chroma_r_size = 0; + break; + case NI_PIX_FMT_NV16: + width_aligned = video_width; + height_aligned = video_height; + + luma_size = video_width * video_height; + chroma_b_size = luma_size; + chroma_r_size = 0; + break; + case NI_PIX_FMT_YUYV422: + case NI_PIX_FMT_UYVY422: + width_aligned = NI_VPU_ALIGN16(video_width); + height_aligned = video_height; + + luma_size = width_aligned * height_aligned * 2; + chroma_b_size = 0; + chroma_r_size = 0; + break; + case NI_PIX_FMT_RGBA: + case NI_PIX_FMT_BGRA: + case NI_PIX_FMT_ARGB: + case NI_PIX_FMT_ABGR: + case NI_PIX_FMT_BGR0: + width_aligned = NI_VPU_ALIGN16(video_width); + height_aligned = video_height; + + luma_size = width_aligned * height_aligned * 4; + chroma_b_size = 0; + chroma_r_size = 0; + break; + case NI_PIX_FMT_BGRP: + width_aligned = video_width; + height_aligned = video_height; + + luma_size = NI_VPU_ALIGN32(width_aligned * height_aligned); + chroma_b_size = luma_size; + chroma_r_size = luma_size; + break; + default: + ni_log(NI_LOG_ERROR, "Unknown pixel format %d\n", pixel_format); + return NI_RETCODE_INVALID_PARAM; + } + + /* Allocate local memory to hold a software ni_frame */ + buffer_size = luma_size + chroma_b_size + chroma_r_size; + + /* Round up to nearest 4K block */ + buffer_size = NI_VPU_ALIGN4096(buffer_size); + + ni_log(NI_LOG_DEBUG, "%s: Rlen %d Glen %d Blen %d buffer_size %d\n", + __func__, luma_size, chroma_b_size, chroma_r_size, buffer_size); + + /* If the frame has changed, reallocate it */ + if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0)) + { + ni_log(NI_LOG_DEBUG, + "%s: free current p_frame, p_frame->buffer_size=%u\n", __func__, + p_frame->buffer_size); + ni_frame_buffer_free(p_frame); + } + + /* Check if need to reallocate */ + if (p_frame->buffer_size != buffer_size) + { + ni_log(NI_LOG_DEBUG, "%s: Allocate new p_frame buffer\n", __func__); + if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) + { + ni_log(NI_LOG_ERROR, + "ERROR %d: %s() Cannot allocate p_frame buffer.\n", NI_ERRNO, + __func__); + retval = NI_RETCODE_ERROR_MEM_ALOC; + LRETURN; + } + } else + { + ni_log(NI_LOG_DEBUG, "%s: reuse p_frame buffer\n", __func__); + } + + // init once after allocation + // memset(p_buffer, 0, buffer_size); + + p_frame->buffer_size = buffer_size; + p_frame->p_buffer = p_buffer; + + p_frame->data_len[0] = luma_size; + p_frame->data_len[1] = chroma_b_size; + p_frame->data_len[2] = chroma_r_size; + p_frame->data_len[3] = 0; + + p_frame->p_data[0] = (uint8_t *)p_frame->p_buffer; + p_frame->p_data[1] = (uint8_t *)p_frame->p_data[0] + p_frame->data_len[0]; + p_frame->p_data[2] = (uint8_t *)p_frame->p_data[1] + p_frame->data_len[1]; + p_frame->p_data[3] = (uint8_t *)p_frame->p_data[2] + p_frame->data_len[2]; + + // init p_data[3] to 0 so that ni_frame_buffer_free frees only valid DMA buf + // fd in hw frame read from fw + p_frame->video_width = width_aligned; + p_frame->video_height = height_aligned; + + // ni_log(NI_LOG_DEBUG, "ni_frame_buffer_alloc: p_buffer %p p_data [%p %p %p %p] data_len [%d %d %d %d] video_width %d video_height %d\n", p_frame->p_buffer, p_frame->p_data[0], p_frame->p_data[1], p_frame->p_data[2], p_frame->p_data[3], p_frame->data_len[0], p_frame->data_len[1], p_frame->data_len[2], p_frame->data_len[3], p_frame->video_width, p_frame->video_height); + ni_log(NI_LOG_DEBUG, "%s: success: p_frame->buffer_size=%u\n", __func__, + p_frame->buffer_size); +END: + + if (NI_RETCODE_SUCCESS != retval) + { + ni_aligned_free(p_buffer); + } + + return retval; +} + /*!***************************************************************************** * \brief Allocate memory for decoder frame buffer based on provided * parameters; the memory is retrieved from a buffer pool and will be @@ -1833,8 +2096,9 @@ ni_retcode_t ni_decoder_frame_buffer_alloc(ni_buf_pool_t *p_pool, || (video_width > NI_MAX_RESOLUTION_WIDTH) || (video_width <= 0) || (video_height > NI_MAX_RESOLUTION_HEIGHT) || (video_height <= 0)) { - ni_log(NI_LOG_ERROR, "ERROR: %s passed parameters are null, return\n", - __func__); + ni_log(NI_LOG_ERROR, "ERROR: %s passed parameters are null or not supported, " + "factor %d, video_width %d, video_height %d\n", + __func__, factor, video_width, video_height); return NI_RETCODE_INVALID_PARAM; } @@ -1912,16 +2176,17 @@ ni_retcode_t ni_decoder_frame_buffer_alloc(ni_buf_pool_t *p_pool, } else { - p_frame->dec_buf = p_frame->p_buffer = NULL; + p_frame->dec_buf = NULL; + p_frame->p_buffer = NULL; ni_log(NI_LOG_DEBUG, "%s: NOT alloc mem buffer\n", __func__); } if (p_frame->p_buffer) { - p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer; - p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + luma_size; - p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + chroma_b_size; - p_frame->p_data[3] = (uint8_t*)p_frame->p_data[2] + chroma_r_size; + p_frame->p_data[0] = p_frame->p_buffer; + p_frame->p_data[1] = p_frame->p_data[0] + luma_size; + p_frame->p_data[2] = p_frame->p_data[1] + chroma_b_size; + p_frame->p_data[3] = p_frame->p_data[2] + chroma_r_size; } else { @@ -1956,7 +2221,8 @@ ni_retcode_t ni_decoder_frame_buffer_alloc(ni_buf_pool_t *p_pool, * \param[in] video_height Height of the video frame * \param[in] linesize Picture line size * \param[in] alignment Allignment requirement - * \param[in] extra_len Extra data size (incl. meta data) + * \param[in] extra_len Extra data size (incl. meta data). < 0 means not + * to allocate any buffer (zero-copy from existing) * \param[in] alignment_2pass_wa set alignment to work with 2pass encode * * \return On success @@ -1974,12 +2240,13 @@ ni_retcode_t ni_encoder_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, int height_aligned; int retval = NI_RETCODE_SUCCESS; - if ((!p_frame) || (!linesize)|| (linesize[0]<=0) || (linesize[0]>NI_MAX_RESOLUTION_LINESIZE) + if ((!p_frame) || (!linesize) || (linesize[0]<=0) || (linesize[0]>NI_MAX_RESOLUTION_LINESIZE) || (video_width>NI_MAX_RESOLUTION_WIDTH) || (video_width<=0) || (video_height>NI_MAX_RESOLUTION_HEIGHT) || (video_height<=0)) { - ni_log(NI_LOG_ERROR, "ERROR: %s passed parameters are null, return\n", - __func__); + ni_log(NI_LOG_ERROR, "ERROR: %s passed parameters are null or not supported, " + "p_frame %p, linesize %p, video_width %d, video_height %d\n", + __func__, p_frame, linesize, video_width, video_height); return NI_RETCODE_INVALID_PARAM; } @@ -2027,46 +2294,53 @@ ni_retcode_t ni_encoder_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, chroma_b_size = luma_size / 4; chroma_r_size = luma_size / 4; } - int buffer_size = luma_size + chroma_b_size + chroma_r_size + extra_len; - - buffer_size = ((buffer_size + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT + NI_MEM_PAGE_ALIGNMENT; - - //Check if Need to free - if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0)) + if(extra_len >= 0) { - ni_log(NI_LOG_DEBUG, - "%s: free current p_frame, " - "p_frame->buffer_size=%u\n", - __func__, p_frame->buffer_size); - ni_frame_buffer_free(p_frame); - } + int buffer_size = luma_size + chroma_b_size + chroma_r_size + extra_len; - //Check if need to realocate - if (p_frame->buffer_size != buffer_size) - { - if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) + buffer_size = ((buffer_size + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT + NI_MEM_PAGE_ALIGNMENT; + + //Check if Need to free + if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n"); - retval = NI_RETCODE_ERROR_MEM_ALOC; - LRETURN; + ni_log(NI_LOG_DEBUG, + "%s: free current p_frame, " + "p_frame->buffer_size=%u\n", + __func__, p_frame->buffer_size); + ni_frame_buffer_free(p_frame); } - // init once after allocation - memset(p_buffer, 0, buffer_size); - p_frame->buffer_size = buffer_size; - p_frame->p_buffer = p_buffer; + //Check if need to realocate + if (p_frame->buffer_size != buffer_size) + { + if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) + { + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate p_frame buffer.\n", + NI_ERRNO, __func__); + retval = NI_RETCODE_ERROR_MEM_ALOC; + LRETURN; + } - ni_log(NI_LOG_DEBUG, "%s: allocated new p_frame buffer\n", __func__); + // init once after allocation + memset(p_buffer, 0, buffer_size); + p_frame->buffer_size = buffer_size; + p_frame->p_buffer = p_buffer; + + ni_log(NI_LOG_DEBUG, "%s: allocated new p_frame buffer\n", __func__); + } + else + { + ni_log(NI_LOG_DEBUG, "%s: reuse p_frame buffer\n", __func__); + } + p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer; + p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + luma_size; + p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + chroma_b_size; } else { - ni_log(NI_LOG_DEBUG, "%s: reuse p_frame buffer\n", __func__); + p_frame->buffer_size = 0; //no ownership } - p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer; - p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + luma_size; - p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + chroma_b_size; - p_frame->data_len[0] = luma_size; p_frame->data_len[1] = chroma_b_size; p_frame->data_len[2] = chroma_r_size; @@ -2090,6 +2364,94 @@ ni_retcode_t ni_encoder_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, return retval; } +/*!***************************************************************************** + * \brief allocate device destination frame from scaler hwframe pool + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +ni_retcode_t ni_scaler_dest_frame_alloc(ni_session_context_t *p_ctx, + ni_scaler_input_params_t scaler_params, + niFrameSurface1_t *p_surface) +{ + int ret = 0; + if (scaler_params.op != NI_SCALER_OPCODE_OVERLAY) + { + ret = ni_device_alloc_frame( + p_ctx, scaler_params.output_width, scaler_params.output_height, + scaler_params.output_format, NI_SCALER_FLAG_IO, + scaler_params.out_rec_width, scaler_params.out_rec_height, + scaler_params.out_rec_x, scaler_params.out_rec_y, + scaler_params.rgba_color, -1, NI_DEVICE_TYPE_SCALER); + } else + { + // in vf_overlay_ni.c: flags = (s->alpha_format ? NI_SCALER_FLAG_PA : 0) | NI_SCALER_FLAG_IO; + ret = ni_device_alloc_frame( + p_ctx, scaler_params.output_width, scaler_params.output_height, + scaler_params.output_format, NI_SCALER_FLAG_IO, + scaler_params.out_rec_width, scaler_params.out_rec_height, + scaler_params.out_rec_x, scaler_params.out_rec_y, + p_surface->ui32nodeAddress, p_surface->ui16FrameIdx, + NI_DEVICE_TYPE_SCALER); + } + return ret; +} + +/*!***************************************************************************** + * \brief allocate device input frame by hw descriptor. This call won't actually allocate + a frame but sends the incoming hardware frame index to the scaler manager + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +ni_retcode_t ni_scaler_input_frame_alloc(ni_session_context_t *p_ctx, + ni_scaler_input_params_t scaler_params, + niFrameSurface1_t *p_src_surface) +{ + int ret = 0; + + ret = ni_device_alloc_frame( + p_ctx, scaler_params.input_width, scaler_params.input_height, + scaler_params.input_format, 0, scaler_params.in_rec_width, + scaler_params.in_rec_height, scaler_params.in_rec_x, + scaler_params.in_rec_y, p_src_surface->ui32nodeAddress, + p_src_surface->ui16FrameIdx, NI_DEVICE_TYPE_SCALER); + return ret; +} + +/*!***************************************************************************** + * \brief init output pool of scaler frames + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +ni_retcode_t ni_scaler_frame_pool_alloc(ni_session_context_t *p_ctx, + ni_scaler_input_params_t scaler_params) +{ + int pool_size = 1; // set to 1 for this demo + + int rc = 0; + int options = NI_SCALER_FLAG_IO | NI_SCALER_FLAG_PC; + if (p_ctx->isP2P) + options |= NI_SCALER_FLAG_P2; + + /* Allocate a pool of frames by the scaler */ + rc = ni_device_alloc_frame(p_ctx, scaler_params.output_width, + scaler_params.output_height, + scaler_params.output_format, options, + 0, // rec width + 0, // rec height + 0, // rec X pos + 0, // rec Y pos + pool_size, // rgba color/pool size + 0, // frame index + NI_DEVICE_TYPE_SCALER); + return rc; +} + /*!***************************************************************************** * \brief Allocate memory for the frame buffer based on provided parameters * taking into account pic line size and extra data. @@ -2100,7 +2462,8 @@ ni_retcode_t ni_encoder_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, * \param[in] video_width Width of the video frame * \param[in] video_height Height of the video frame * \param[in] linesize Picture line size -* \param[in] extra_len Extra data size (incl. meta data) +* \param[in] extra_len Extra data size (incl. meta data). < 0 means not +* to allocate any buffer (zero-copy from existing) * \param[in] alignment_2pass_wa set alignment to work with 2pass encode * * \return On success @@ -2121,8 +2484,9 @@ ni_retcode_t ni_frame_buffer_alloc_nv(ni_frame_t *p_frame, int video_width, || (video_width>NI_MAX_RESOLUTION_WIDTH) || (video_width <= 0) || (video_height>NI_MAX_RESOLUTION_HEIGHT) || (video_height <= 0)) { - ni_log(NI_LOG_ERROR, "ERROR: %s passed parameters are null, return\n", - __func__); + ni_log(NI_LOG_ERROR, "ERROR: %s passed parameters are null or not supported, " + "p_frame %p, linesize %p, video_width %d, video_height %d\n", + __func__, p_frame, linesize, video_width, video_height); return NI_RETCODE_INVALID_PARAM; } @@ -2146,45 +2510,51 @@ ni_retcode_t ni_frame_buffer_alloc_nv(ni_frame_t *p_frame, int video_width, // for 2-pass encode output mismatch WA, need to extend (and pad) CbCr plane height, because 1st pass assume input 32 align chroma_br_size = linesize[0] * ((((height_aligned + 31) / 32) * 32) / 2); } - - int buffer_size = luma_size + chroma_br_size + extra_len; - - buffer_size = ((buffer_size + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT + NI_MEM_PAGE_ALIGNMENT; - - //Check if Need to free - if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0)) + if (extra_len >= 0) { - ni_log(NI_LOG_DEBUG, "%s: free current p_frame->buffer_size=%u\n", - __func__, p_frame->buffer_size); - ni_frame_buffer_free(p_frame); - } - - //Check if need to realocate - if (p_frame->buffer_size != buffer_size) - { - if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) + int buffer_size = luma_size + chroma_br_size + extra_len; + + buffer_size = ((buffer_size + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT + NI_MEM_PAGE_ALIGNMENT; + + //Check if Need to free + if ((p_frame->buffer_size != buffer_size) && (p_frame->buffer_size > 0)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n"); - retval = NI_RETCODE_ERROR_MEM_ALOC; - LRETURN; + ni_log(NI_LOG_DEBUG, "%s: free current p_frame->buffer_size=%u\n", + __func__, p_frame->buffer_size); + ni_frame_buffer_free(p_frame); } - - // init once after allocation - memset(p_buffer, 0, buffer_size); - p_frame->buffer_size = buffer_size; - p_frame->p_buffer = p_buffer; - - ni_log(NI_LOG_DEBUG, "%s: allocated new p_frame buffer\n", __func__); + + //Check if need to realocate + if (p_frame->buffer_size != buffer_size) + { + if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) + { + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate p_frame buffer.\n", + NI_ERRNO, __func__); + retval = NI_RETCODE_ERROR_MEM_ALOC; + LRETURN; + } + + // init once after allocation + memset(p_buffer, 0, buffer_size); + p_frame->buffer_size = buffer_size; + p_frame->p_buffer = p_buffer; + + ni_log(NI_LOG_DEBUG, "%s: allocated new p_frame buffer\n", __func__); + } + else + { + ni_log(NI_LOG_DEBUG, "%s: reuse p_frame buffer\n", __func__); + } + + p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer; + p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + luma_size; + p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + chroma_br_size; } else { - ni_log(NI_LOG_DEBUG, "%s: reuse p_frame buffer\n", __func__); + p_frame->buffer_size = 0; //no ownership } - - p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer; - p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + luma_size; - p_frame->p_data[2] = (uint8_t*)p_frame->p_data[1] + chroma_br_size; - p_frame->data_len[0] = luma_size; p_frame->data_len[1] = chroma_br_size; p_frame->data_len[2] = 0; @@ -2205,6 +2575,57 @@ ni_retcode_t ni_frame_buffer_alloc_nv(ni_frame_t *p_frame, int video_width, return retval; } +/*!***************************************************************************** + * \brief This API is a wrapper for ni_encoder_frame_buffer_alloc(), used + * for planar pixel formats, and ni_frame_buffer_alloc_nv(), used for + * semi-planar pixel formats. This API is meant to combine the + * functionality for both individual format APIs. + * Allocate memory for the frame buffer for encoding based on given + * parameters, taking into account pic line size and extra data. + * Applicable to YUV420p(8 or 10 bit/pixel) or nv12 AVFrame. + * Cb/Cr size matches that of Y. + * + * \param[in] planar true: if planar: + * pixel_format == (NI_PIX_FMT_YUV420P || + * NI_PIX_FMT_YUV420P10LE ||NI_PIX_FMT_RGBA). + * false: semi-planar: + * pixel_format == (NI_PIX_FMT_NV12 || + * NI_PIX_FMT_P010LE). + * \param[in] p_frame Pointer to a caller allocated ni_frame_t struct + * \param[in] video_width Width of the video frame + * \param[in] video_height Height of the video frame + * \param[in] linesize Picture line size + * \param[in] alignment Allignment requirement. Only used for planar format. + * \param[in] extra_len Extra data size (incl. meta data). < 0 means not + * to allocate any buffer (zero-copy from existing) + * \param[in] alignment_2pass_wa set alignment to work with 2pass encode + * + * \return On success + * NI_RETCODE_SUCCESS + * On failure + * NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_MEM_ALOC + *****************************************************************************/ +ni_retcode_t ni_encoder_sw_frame_buffer_alloc(bool planar, ni_frame_t *p_frame, + int video_width, int video_height, + int linesize[], int alignment, + int extra_len, + bool alignment_2pass_wa) +{ + if (true == planar) + { + return ni_encoder_frame_buffer_alloc(p_frame, video_width, video_height, + linesize, alignment, extra_len, + alignment_2pass_wa); + } + else + { + return ni_frame_buffer_alloc_nv(p_frame, video_width, video_height, + linesize, extra_len, + alignment_2pass_wa); + } +} + /*!***************************************************************************** * \brief Free frame buffer that was previously allocated with either * ni_frame_buffer_alloc or ni_encoder_frame_buffer_alloc or @@ -2301,8 +2722,8 @@ ni_retcode_t ni_decoder_frame_buffer_free(ni_frame_t *p_frame) ni_log(NI_LOG_DEBUG, "%s(): NO mem buf returned !\n", __func__); } - p_frame->dec_buf = p_frame->p_buffer = NULL; - + p_frame->dec_buf = NULL; + p_frame->p_buffer = NULL; p_frame->buffer_size = 0; for (i = 0; i < NI_MAX_NUM_DATA_POINTERS; i++) { @@ -2354,7 +2775,7 @@ ni_retcode_t ni_packet_buffer_alloc(ni_packet_t* p_packet, int packet_size) int buffer_size = (((packet_size + metadata_size) / NI_MAX_PACKET_SZ) + 1) * NI_MAX_PACKET_SZ; - ni_log(NI_LOG_DEBUG, "%s: packet_size=%d\n", __func__, + ni_log(NI_LOG_TRACE, "%s: packet_size=%d\n", __func__, packet_size + metadata_size); if (!p_packet || !packet_size) @@ -2392,8 +2813,8 @@ ni_retcode_t ni_packet_buffer_alloc(ni_packet_t* p_packet, int packet_size) if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: %s: Cannot allocate p_frame buffer.\n", - __func__); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate p_packet buffer.\n", + NI_ERRNO, __func__); ni_log(NI_LOG_TRACE, "%s: exit: p_packet->buffer_size=%u\n", __func__, p_packet->buffer_size); return NI_RETCODE_ERROR_MEM_ALOC; @@ -2409,6 +2830,63 @@ ni_retcode_t ni_packet_buffer_alloc(ni_packet_t* p_packet, int packet_size) return NI_RETCODE_SUCCESS; } +/*!***************************************************************************** + * \brief Allocate packet buffer using a user provided pointer, the memory + * is expected to have already been allocated. + * + * For ideal performance memory should be 4k aligned. If it is not 4K aligned + * then a temporary 4k aligned memory will be used to copy data to and from + * when writing and reading. This will negatively impact performance. + * + * This API will overwrite p_packet->buffer_size, p_packet->p_buffer and + * p_packet->p_data fields in p_packet. + * + * This API will not free any memory associated with p_packet->p_buffer and + * p_packet->p_data fields in p_packet. + * Common use case could be, + * 1. Allocate memory to pointer + * 2. Call ni_custom_packet_buffer_alloc() with allocated pointer. + * 3. Use p_packet as required. + * 4. Call ni_packet_buffer_free() to free up the memory. + * + * \param[in] p_buffer User provided pointer to be used for buffer + * \param[in] p_packet Pointer to a caller allocated + * ni_packet_t struct + * \param[in] buffer_size Buffer size + * + * \return On success + * NI_RETCODE_SUCCESS + * On failure + * NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_MEM_ALOC + ******************************************************************************/ +ni_retcode_t ni_custom_packet_buffer_alloc(void *p_buffer, + ni_packet_t *p_packet, + int buffer_size) +{ + ni_log(NI_LOG_TRACE, "%s(): enter buffer_size=%d\n", __func__, buffer_size); + + if (!p_buffer || !p_packet || !buffer_size) + { + ni_log(NI_LOG_ERROR, "ERROR: %s: null pointer parameters passed\n", + __func__); + return NI_RETCODE_INVALID_PARAM; + } + if (((uintptr_t)p_buffer) % NI_MEM_PAGE_ALIGNMENT) + { + ni_log(NI_LOG_INFO, "Info: %s: Warning buffer not 4k aligned = %p!. Will do an extra copy\n", + __func__, p_buffer); + } + + p_packet->buffer_size = buffer_size; + p_packet->p_buffer = p_buffer; + p_packet->p_data = p_packet->p_buffer; + + ni_log(NI_LOG_TRACE, "%s: exit: \n", __func__); + + return NI_RETCODE_SUCCESS; +} + /*!***************************************************************************** * \brief Free packet buffer that was previously allocated with * ni_packet_buffer_alloc @@ -2553,18 +3031,20 @@ int ni_packet_copy(void* p_destination, const void* const p_source, int cur_size p_dst += prev_size; - memcpy(p_dst, p_src, total_size); + memcpy(p_dst, p_src, cur_size); if (padding_size) { - p_dst += total_size; + p_dst += cur_size; memset(p_dst, 0, padding_size); } - *p_prev_size = 0; + ni_log(NI_LOG_TRACE, + "%s(): exit, cur_size=%d, copy_size=%d, " + "prev_size=%d, padding_size=%d\n", __func__, cur_size, + copy_size, *p_prev_size, padding_size); - ni_log(NI_LOG_TRACE, "%s(): exit, cur_size=%d, copy_size=%d, prev_size=%d\n", - __func__, cur_size, copy_size, *p_prev_size); + *p_prev_size = 0; return copy_size; } @@ -2824,7 +3304,7 @@ ni_retcode_t ni_encoder_init_default_params(ni_xcoder_params_t *p_param, p_enc->custom_gop_params.pic_param[i].pic_type = PIC_TYPE_I; p_enc->custom_gop_params.pic_param[i].poc_offset = 0; p_enc->custom_gop_params.pic_param[i].pic_qp = 0; - p_enc->custom_gop_params.pic_param[i].num_ref_pic_L0 = 0; // syed todo: check this initial value, added for T408 5 + p_enc->custom_gop_params.pic_param[i].num_ref_pic_L0 = 0; p_enc->custom_gop_params.pic_param[i].ref_poc_L0 = 0; p_enc->custom_gop_params.pic_param[i].ref_poc_L1 = 0; p_enc->custom_gop_params.pic_param[i].temporal_id = 0; @@ -2911,6 +3391,7 @@ ni_retcode_t ni_encoder_init_default_params(ni_xcoder_params_t *p_param, p_enc->ltrNextInterval = 1; p_enc->multicoreJointMode = 0; p_enc->qlevel = -1; + p_enc->maxFrameSize = 0; p_enc->chromaQpOffset = 0; p_enc->tolCtbRcInter = (float)0.1; p_enc->tolCtbRcIntra = (float)0.1; @@ -2921,9 +3402,20 @@ ni_retcode_t ni_encoder_init_default_params(ni_xcoder_params_t *p_param, p_enc->aspectRatioWidth = 0; p_enc->aspectRatioHeight = 1; p_enc->keep_alive_timeout = NI_DEFAULT_KEEP_ALIVE_TIMEOUT; + p_enc->enable_ssim = 0; if (codec_format == NI_CODEC_FORMAT_AV1) { + if (p_param->source_width < NI_PARAM_AV1_MIN_WIDTH) + { + retval = NI_RETCODE_PARAM_ERROR_WIDTH_TOO_SMALL; + LRETURN; + } + if (p_param->source_height < NI_PARAM_AV1_MIN_HEIGHT) + { + retval = NI_RETCODE_PARAM_ERROR_HEIGHT_TOO_SMALL; + LRETURN; + } if (p_param->source_width > NI_PARAM_AV1_MAX_WIDTH) { retval = NI_RETCODE_PARAM_ERROR_WIDTH_TOO_BIG; @@ -2940,14 +3432,29 @@ ni_retcode_t ni_encoder_init_default_params(ni_xcoder_params_t *p_param, retval = NI_RETCODE_PARAM_ERROR_AREA_TOO_BIG; LRETURN; } + // AV1 8x8 alignment HW limitation is now worked around by FW cropping input resolution if (p_param->source_width % NI_PARAM_AV1_ALIGN_WIDTH_HEIGHT) { - retval = NI_RETCODE_PARAM_ERROR_PIC_WIDTH; - LRETURN; + ni_log(NI_LOG_ERROR, "AV1 Picture Width not aligned to %d - picture will be cropped\n", + NI_PARAM_AV1_ALIGN_WIDTH_HEIGHT); } if (p_param->source_height % NI_PARAM_AV1_ALIGN_WIDTH_HEIGHT) { - retval = NI_RETCODE_PARAM_ERROR_PIC_HEIGHT; + ni_log(NI_LOG_ERROR, "AV1 Picture Height not aligned to %d - picture will be cropped\n", + NI_PARAM_AV1_ALIGN_WIDTH_HEIGHT); + } + } + + if (codec_format == NI_CODEC_FORMAT_JPEG) + { + if (p_param->source_width < NI_PARAM_JPEG_MIN_WIDTH) + { + retval = NI_RETCODE_PARAM_ERROR_WIDTH_TOO_SMALL; + LRETURN; + } + if (p_param->source_height < NI_PARAM_JPEG_MIN_HEIGHT) + { + retval = NI_RETCODE_PARAM_ERROR_HEIGHT_TOO_SMALL; LRETURN; } } @@ -3051,6 +3558,7 @@ ni_retcode_t ni_decoder_init_default_params(ni_xcoder_params_t *p_param, } p_dec->keep_alive_timeout = NI_DEFAULT_KEEP_ALIVE_TIMEOUT; + p_dec->decoder_low_delay = 0; //-------init unused param start---------- @@ -3199,7 +3707,7 @@ ni_retcode_t ni_decoder_params_set_value(ni_xcoder_params_t *p_params, const char delim[2] = ","; const char xdelim[2] = "x"; char *chunk;//for parsing out multi param input - int i,j,k; + int i, j, k; ni_log(NI_LOG_TRACE, "%s(): enter\n", __func__); @@ -3212,7 +3720,7 @@ ni_retcode_t ni_decoder_params_set_value(ni_xcoder_params_t *p_params, if (!name) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): Null pointer parameters passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s(): Null name pointer parameters passed\n", __func__); return NI_RETCODE_PARAM_INVALID_NAME; } @@ -3490,6 +3998,18 @@ ni_retcode_t ni_decoder_params_set_value(ni_xcoder_params_t *p_params, } OPT(NI_DEC_PARAM_SCALE_0) { + chunk = value; + i = 0; // 'x' character counter + while (*chunk++) { + if (*chunk == xdelim[0]) { + i++; + } + } + if (i != 1) { + return NI_RETCODE_PARAM_INVALID_VALUE; + } + chunk = NULL; + chunk = strtok(value, xdelim); for (i = 0; i < 2; i++) { @@ -3518,6 +4038,18 @@ ni_retcode_t ni_decoder_params_set_value(ni_xcoder_params_t *p_params, } OPT(NI_DEC_PARAM_SCALE_1) { + chunk = value; + i = 0; // 'x' character counter + while (*chunk++) { + if (*chunk == xdelim[0]) { + i++; + } + } + if (i != 1) { + return NI_RETCODE_PARAM_INVALID_VALUE; + } + chunk = NULL; + chunk = strtok(value, xdelim); for (i = 0; i < 2; i++) { @@ -3546,6 +4078,18 @@ ni_retcode_t ni_decoder_params_set_value(ni_xcoder_params_t *p_params, } OPT(NI_DEC_PARAM_SCALE_2) { + chunk = value; + i = 0; // 'x' character counter + while (*chunk++) { + if (*chunk == xdelim[0]) { + i++; + } + } + if (i != 1) { + return NI_RETCODE_PARAM_INVALID_VALUE; + } + chunk = NULL; + chunk = strtok(value, xdelim); for (i = 0; i < 2; i++) { @@ -3597,6 +4141,15 @@ ni_retcode_t ni_decoder_params_set_value(ni_xcoder_params_t *p_params, } p_dec->keep_alive_timeout = atoi(value); } + OPT(NI_DEC_PARAM_LOW_DELAY) + { + if ((atoi(value) != 0) && + (atoi(value) != 1)) + { + return NI_RETCODE_PARAM_ERROR_OOR; + } + p_dec->decoder_low_delay = atoi(value); + } else { return NI_RETCODE_PARAM_INVALID_NAME; @@ -3653,7 +4206,7 @@ ni_retcode_t ni_encoder_params_set_value(ni_xcoder_params_t *p_params, if ( !name ) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): Null pointer parameters passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s(): Null name pointer parameters passed\n", __func__); return NI_RETCODE_PARAM_INVALID_NAME; } @@ -3978,10 +4531,20 @@ ni_retcode_t ni_encoder_params_set_value(ni_xcoder_params_t *p_params, } OPT( NI_ENC_PARAM_ENABLE_PIC_SKIP ) { - // Disabled for GCA release. Will be enabled once QDFW-1785/1958 is resolved - //p_enc->rc.enable_pic_skip = atoi(value); - p_enc->rc.enable_pic_skip = 0; - ni_log(NI_LOG_ERROR, "%s: picSkip option has been temporarily disabled\n", __func__); + if (0 != atoi(value) && 1 != atoi(value)) + { + return NI_RETCODE_PARAM_ERROR_OOR; + } + // Currenly pic skip is supported for low delay gops only - pic skip issues tracked by QDFW-1785/1958 + p_enc->rc.enable_pic_skip = atoi(value); + } + OPT(NI_ENC_PARAM_MAX_FRAME_SIZE_LOW_DELAY) + { + if (atoi(value) < NI_MIN_FRAME_SIZE) + { + return NI_RETCODE_PARAM_ERROR_OOR; + } + p_enc->maxFrameSize = (atoi(value) > NI_MAX_FRAME_SIZE) ? NI_MAX_FRAME_SIZE : atoi(value); } OPT ( NI_ENC_PARAM_FORCED_HEADER_ENABLE ) { @@ -4412,6 +4975,22 @@ ni_retcode_t ni_encoder_params_set_value(ni_xcoder_params_t *p_params, } p_enc->keep_alive_timeout = atoi(value); } + OPT(NI_ENC_PARAM_ENABLE_VFR) + { + if (atoi(value) != 0 && atoi(value) != 1) + { + return NI_RETCODE_PARAM_ERROR_OOR; + } + p_params->enable_vfr = atoi(value); + } + OPT(NI_ENC_ENABLE_SSIM) + { + if ((atoi(value) != 0) && (atoi(value) != 1)) + { + return NI_RETCODE_PARAM_ERROR_OOR; + } + p_enc->enable_ssim = atoi(value); + } else { return NI_RETCODE_PARAM_INVALID_NAME; } #undef OPT @@ -4462,9 +5041,16 @@ ni_retcode_t ni_encoder_gop_params_set_value(ni_xcoder_params_t *p_params, ni_log(NI_LOG_TRACE, "%s(): enter\n", __func__); - if ( (!p_params) || (!name) ) + if (!p_params) + { + ni_log(NI_LOG_ERROR, "ERROR: %s(): Null pointer parameters passed\n", + __func__); + return NI_RETCODE_INVALID_PARAM; + } + + if ( !name ) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): Null pointer parameters passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s(): Null name pointer parameters passed\n", __func__); return NI_RETCODE_PARAM_INVALID_NAME; } @@ -5304,7 +5890,8 @@ int ni_device_session_read_hwdesc(ni_session_context_t *p_ctx, ni_session_data_i ni_retcode_t retval = NI_RETCODE_SUCCESS; if ((!p_ctx) || (!p_data)) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } @@ -5314,7 +5901,7 @@ int ni_device_session_read_hwdesc(ni_session_context_t *p_ctx, ni_session_data_i #ifdef _WIN32 (p_ctx->keep_alive_thread.handle && #else - (p_ctx->keep_alive_thread && + (p_ctx->keep_alive_thread && #endif p_ctx->keep_alive_thread_args->close_thread)) { @@ -5412,7 +5999,8 @@ int ni_device_session_read_hwdesc(ni_session_context_t *p_ctx, ni_session_data_i default: { retval = NI_RETCODE_INVALID_PARAM; - ni_log(NI_LOG_ERROR, "ERROR: Unrecognized device type: %d", device_type); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unrecognized device type: %d", + __func__, device_type); break; } } @@ -5445,7 +6033,8 @@ int ni_device_session_hwdl(ni_session_context_t* p_ctx, ni_session_data_io_t *p_ ni_retcode_t retval = NI_RETCODE_SUCCESS; if ((!hwdesc) || (!p_data)) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } ni_pthread_mutex_lock(p_ctx->xcoder_mutex); @@ -5489,7 +6078,8 @@ int ni_device_session_hwup(ni_session_context_t* p_ctx, ni_session_data_io_t *p_ ni_retcode_t retval = NI_RETCODE_SUCCESS; if ((!hwdesc) || (!p_src_data)) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } ni_pthread_mutex_lock(p_ctx->xcoder_mutex); @@ -5528,7 +6118,8 @@ ni_retcode_t ni_frame_buffer_alloc_hwenc(ni_frame_t* p_frame, int video_width, if (!p_frame) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } @@ -5554,7 +6145,8 @@ ni_retcode_t ni_frame_buffer_alloc_hwenc(ni_frame_t* p_frame, int video_width, { if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate p_frame buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate p_frame buffer.\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -5571,7 +6163,7 @@ ni_retcode_t ni_frame_buffer_alloc_hwenc(ni_frame_t* p_frame, int video_width, ni_log(NI_LOG_DEBUG, "%s: reuse p_frame buffer\n", __func__); } - p_frame->p_data[3] = (uint8_t*)p_frame->p_buffer; + p_frame->p_data[3] = p_frame->p_buffer; p_frame->p_data[0] = NULL; p_frame->p_data[1] = NULL; p_frame->p_data[2] = NULL; @@ -5647,16 +6239,17 @@ int ni_device_session_init_framepool(ni_session_context_t *p_ctx, uint32_t pool_size, uint32_t pool) { ni_retcode_t retval = NI_RETCODE_SUCCESS; - if (pool_size == 0 || pool_size > NI_MAX_UPLOAD_INSTANCE_FRAMEPOOL) + if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid poolsize == 0 or > 100\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } - if (!p_ctx) + if (pool_size == 0 || pool_size > NI_MAX_UPLOAD_INSTANCE_FRAMEPOOL) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: Invalid poolsize == 0 or > 100\n"); return NI_RETCODE_INVALID_PARAM; - } + } if (pool != 0 && pool != 1) { ni_log(NI_LOG_ERROR, "ERROR: bad pool number %u\n", pool); @@ -5724,7 +6317,7 @@ ni_retcode_t ni_scaler_set_params(ni_session_context_t *p_ctx, * \param[in] rectangle_y vertical position of clipping rectangle * \param[in] rgba_color RGBA fill colour (for padding only) * \param[in] rgba_color RGBA fill colour (for padding only) - * \param[in] frame_index input hwdesc index + * \param[in] frame_index input hwdesc index * \param[in] device_type only NI_DEVICE_TYPE_SCALER * and NI_DEVICE_TYPE_AI (only needs p_ctx and frame_index) * @@ -5791,7 +6384,6 @@ ni_retcode_t ni_device_alloc_frame(ni_session_context_t* p_ctx, * * \param[in] p_ctx pointer to session context * \param[in] p_cfg pointer to frame configuration - * and NI_DEVICE_TYPE_AI (only needs p_ctx and frame_index) * * \return NI_RETCODE_INVALID_PARAM * NI_RETCODE_ERROR_INVALID_SESSION @@ -5831,6 +6423,54 @@ ni_retcode_t ni_device_config_frame(ni_session_context_t *p_ctx, return retval; } +/*!***************************************************************************** + * \brief Configure the 2D engine to work based on provided parameters + * + * \param[in] p_ctx pointer to session context + * \param[in] p_cfg_in pointer to input frame configuration + * \param[in] numInCfgs number of input frame configurations + * \param[in] p_cfg_out pointer to output frame configuration + * + * \return NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_INVALID_SESSION + * NI_RETCODE_ERROR_NVME_CMD_FAILED + * NI_RETCODE_ERROR_MEM_ALOC + ******************************************************************************/ +ni_retcode_t ni_device_multi_config_frame(ni_session_context_t *p_ctx, + ni_frame_config_t p_cfg_in[], + int numInCfgs, + ni_frame_config_t *p_cfg_out) +{ + ni_retcode_t retval = NI_RETCODE_SUCCESS; + + if (!p_ctx || !p_cfg_in) + { + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null, return\n", + __func__); + return NI_RETCODE_INVALID_PARAM; + } + + ni_pthread_mutex_lock(p_ctx->xcoder_mutex); + p_ctx->xcoder_state |= NI_XCODER_GENERAL_STATE; + + switch (p_ctx->device_type) + { + case NI_DEVICE_TYPE_SCALER: + retval = ni_scaler_multi_config_frame(p_ctx, p_cfg_in, numInCfgs, p_cfg_out); + break; + + default: + ni_log(NI_LOG_ERROR, "Bad device type %d\n", p_ctx->device_type); + retval = NI_RETCODE_INVALID_PARAM; + break; + } + + p_ctx->xcoder_state &= ~NI_XCODER_GENERAL_STATE; + ni_pthread_mutex_unlock(p_ctx->xcoder_mutex); + + return retval; +} + /*!***************************************************************************** * \brief Calculate the total size of a frame based on the upload * context attributes and includes rounding up to the page size @@ -5950,7 +6590,9 @@ ni_retcode_t ni_frame_buffer_alloc_pixfmt(ni_frame_t *p_frame, int pixel_format, void *p_buffer = NULL; int retval = NI_RETCODE_SUCCESS; int height_aligned; - int luma_size, chroma_b_size, chroma_r_size; + int luma_size = 0; + int chroma_b_size = 0; + int chroma_r_size = 0; if (!p_frame) { @@ -5964,37 +6606,49 @@ ni_retcode_t ni_frame_buffer_alloc_pixfmt(ni_frame_t *p_frame, int pixel_format, case NI_PIX_FMT_YUV420P10LE: case NI_PIX_FMT_NV12: case NI_PIX_FMT_P010LE: - if ((video_width < 0) || (video_width > NI_MAX_RESOLUTION_WIDTH)) - { - ni_log(NI_LOG_ERROR, "Video resolution width %d out of range\n",video_width); - return NI_RETCODE_INVALID_PARAM; - } + case NI_PIX_FMT_NV16: + case NI_PIX_FMT_YUYV422: + case NI_PIX_FMT_UYVY422: + if ((video_width < 0) || (video_width > NI_MAX_RESOLUTION_WIDTH)) + { + ni_log(NI_LOG_ERROR, "Video resolution width %d out of range\n", + video_width); + return NI_RETCODE_INVALID_PARAM; + } - if ((video_height < 0) || (video_height > NI_MAX_RESOLUTION_HEIGHT)) - { - ni_log(NI_LOG_ERROR, "Video resolution height %d out of range\n",video_width); - return NI_RETCODE_INVALID_PARAM; - } - break; + if ((video_height < 0) || (video_height > NI_MAX_RESOLUTION_HEIGHT)) + { + ni_log(NI_LOG_ERROR, "Video resolution height %d out of range\n", + video_width); + return NI_RETCODE_INVALID_PARAM; + } + break; case NI_PIX_FMT_RGBA: - /* - * For 2D engine using RGBA, the minimum width is 32. There is no - * height restriction. The 2D engine supports a height/width of up to - * 32K but but we will limit the max height and width to 8K. - */ - if ((video_width < 32) && (video_width > NI_MAX_RESOLUTION_WIDTH)) - { - ni_log(NI_LOG_ERROR, "Video resolution width %d out of range\n",video_width); - return NI_RETCODE_INVALID_PARAM; - } + case NI_PIX_FMT_BGRA: + case NI_PIX_FMT_ARGB: + case NI_PIX_FMT_ABGR: + case NI_PIX_FMT_BGR0: + case NI_PIX_FMT_BGRP: + /* + * For 2D engine using RGBA, the minimum width is 32. There is no + * height restriction. The 2D engine supports a height/width of up to + * 32K but but we will limit the max height and width to 8K. + */ + if ((video_width < 32) && (video_width > NI_MAX_RESOLUTION_WIDTH)) + { + ni_log(NI_LOG_ERROR, "Video resolution width %d out of range\n", + video_width); + return NI_RETCODE_INVALID_PARAM; + } - if ((video_height <= 0) || (video_height > NI_MAX_RESOLUTION_HEIGHT)) - { - ni_log(NI_LOG_ERROR, "Video resolution height %d out of range\n",video_height); - return NI_RETCODE_INVALID_PARAM; - } - break; + if ((video_height <= 0) || (video_height > NI_MAX_RESOLUTION_HEIGHT)) + { + ni_log(NI_LOG_ERROR, "Video resolution height %d out of range\n", + video_height); + return NI_RETCODE_INVALID_PARAM; + } + break; default: ni_log(NI_LOG_ERROR, "Unknown pixel format %d\n",pixel_format); @@ -6033,13 +6687,17 @@ ni_retcode_t ni_frame_buffer_alloc_pixfmt(ni_frame_t *p_frame, int pixel_format, chroma_b_size = luma_size / 4; chroma_r_size = luma_size / 4; } - - buffer_size = luma_size + chroma_b_size + chroma_r_size + extra_len; break; case NI_PIX_FMT_RGBA: - buffer_size = video_width * video_height * 4 + extra_len; - break; + case NI_PIX_FMT_BGRA: + case NI_PIX_FMT_ARGB: + case NI_PIX_FMT_ABGR: + case NI_PIX_FMT_BGR0: + luma_size = linesize[0] * video_height; + chroma_b_size = 0; + chroma_r_size = 0; + break; case NI_PIX_FMT_NV12: case NI_PIX_FMT_P010LE: @@ -6048,16 +6706,41 @@ ni_retcode_t ni_frame_buffer_alloc_pixfmt(ni_frame_t *p_frame, int pixel_format, luma_size = linesize[0] * height_aligned; chroma_b_size = linesize[1] * height_aligned / 2; chroma_r_size = 0; - - buffer_size = luma_size + chroma_b_size + chroma_r_size + extra_len; break; } - /*fall through*/ + case NI_PIX_FMT_NV16: + if (QUADRA) + { + luma_size = linesize[0] * video_height; + chroma_b_size = linesize[1] * video_height; + chroma_r_size = 0; + break; + } + case NI_PIX_FMT_YUYV422: + case NI_PIX_FMT_UYVY422: + if (QUADRA) + { + luma_size = linesize[0] * video_height; + chroma_b_size = 0; + chroma_r_size = 0; + break; + } + case NI_PIX_FMT_BGRP: + if (QUADRA) + { + luma_size = NI_VPU_ALIGN32(linesize[0] * video_height); + chroma_b_size = NI_VPU_ALIGN32(linesize[1] * video_height); + chroma_r_size = NI_VPU_ALIGN32(linesize[2] * video_height); + break; + } + /*fall through*/ default: ni_log(NI_LOG_ERROR, "Error: unsupported pixel format %d\n",pixel_format); return NI_RETCODE_INVALID_PARAM; } + buffer_size = luma_size + chroma_b_size + chroma_r_size + extra_len; + /* Allocate a buffer size that is page aligned for the host */ buffer_size = NI_VPU_CEIL(buffer_size,NI_MEM_PAGE_ALIGNMENT) + NI_MEM_PAGE_ALIGNMENT; @@ -6092,9 +6775,9 @@ ni_retcode_t ni_frame_buffer_alloc_pixfmt(ni_frame_t *p_frame, int pixel_format, { case NI_PIX_FMT_YUV420P: case NI_PIX_FMT_YUV420P10LE: - p_frame->p_data[0] = (uint8_t*) p_frame->p_buffer; - p_frame->p_data[1] = (uint8_t*) p_frame->p_data[0] + luma_size; - p_frame->p_data[2] = (uint8_t*) p_frame->p_data[1] + chroma_b_size; + p_frame->p_data[0] = p_frame->p_buffer; + p_frame->p_data[1] = p_frame->p_data[0] + luma_size; + p_frame->p_data[2] = p_frame->p_data[1] + chroma_b_size; p_frame->p_data[3] = NULL; p_frame->data_len[0] = luma_size; @@ -6105,35 +6788,85 @@ ni_retcode_t ni_frame_buffer_alloc_pixfmt(ni_frame_t *p_frame, int pixel_format, break; case NI_PIX_FMT_RGBA: - p_frame->p_data[0] = (uint8_t*) p_frame->p_buffer; - p_frame->p_data[1] = NULL; - p_frame->p_data[2] = NULL; - p_frame->p_data[3] = NULL; - - p_frame->data_len[0] = video_height * video_width * 4; - p_frame->data_len[1] = 0; - p_frame->data_len[2] = 0; - p_frame->data_len[3] = 0; - break; - - case NI_PIX_FMT_NV12: - case NI_PIX_FMT_P010LE: - if (QUADRA) - { - p_frame->p_data[0] = (uint8_t*)p_frame->p_buffer; - p_frame->p_data[1] = (uint8_t*)p_frame->p_data[0] + luma_size; + case NI_PIX_FMT_BGRA: + case NI_PIX_FMT_ARGB: + case NI_PIX_FMT_ABGR: + case NI_PIX_FMT_BGR0: + p_frame->p_data[0] = (uint8_t *)p_frame->p_buffer; + p_frame->p_data[1] = NULL; p_frame->p_data[2] = NULL; p_frame->p_data[3] = NULL; p_frame->data_len[0] = luma_size; - p_frame->data_len[1] = chroma_b_size; + p_frame->data_len[1] = 0; p_frame->data_len[2] = 0; p_frame->data_len[3] = 0; - - video_width = NI_VPU_ALIGN128(video_width); + video_width = NI_VPU_ALIGN16(video_width); break; - } - /* fall through */ + + case NI_PIX_FMT_NV12: + case NI_PIX_FMT_P010LE: + if (QUADRA) + { + p_frame->p_data[0] = (uint8_t *)p_frame->p_buffer; + p_frame->p_data[1] = (uint8_t *)p_frame->p_data[0] + luma_size; + p_frame->p_data[2] = NULL; + p_frame->p_data[3] = NULL; + + p_frame->data_len[0] = luma_size; + p_frame->data_len[1] = chroma_b_size; + p_frame->data_len[2] = 0; + p_frame->data_len[3] = 0; + + video_width = NI_VPU_ALIGN128(video_width); + break; + } + case NI_PIX_FMT_NV16: + if (QUADRA) + { + p_frame->p_data[0] = (uint8_t *)p_frame->p_buffer; + p_frame->p_data[1] = (uint8_t *)p_frame->p_data[0] + luma_size; + p_frame->p_data[2] = NULL; + p_frame->p_data[3] = NULL; + + p_frame->data_len[0] = luma_size; + p_frame->data_len[1] = chroma_b_size; + p_frame->data_len[2] = 0; + p_frame->data_len[3] = 0; + break; + } + + case NI_PIX_FMT_YUYV422: + case NI_PIX_FMT_UYVY422: + if (QUADRA) + { + p_frame->p_data[0] = (uint8_t *)p_frame->p_buffer; + p_frame->p_data[1] = NULL; + p_frame->p_data[2] = NULL; + p_frame->p_data[3] = NULL; + + p_frame->data_len[0] = luma_size; + p_frame->data_len[1] = 0; + p_frame->data_len[2] = 0; + p_frame->data_len[3] = 0; + video_width = NI_VPU_ALIGN16(video_width); + break; + } + case NI_PIX_FMT_BGRP: + if (QUADRA) + { + p_frame->p_data[0] = (uint8_t *)p_frame->p_buffer; + p_frame->p_data[1] = (uint8_t *)p_frame->p_data[0] + luma_size; + p_frame->p_data[2] = (uint8_t *)p_frame->p_data[1] + chroma_b_size; + p_frame->p_data[3] = NULL; + + p_frame->data_len[0] = luma_size; + p_frame->data_len[1] = chroma_b_size; + p_frame->data_len[2] = chroma_r_size; + p_frame->data_len[3] = 0; + break; + } + /* fall through */ default: ni_log(NI_LOG_ERROR, "Error: unsupported pixel format %d\n",pixel_format); retval = NI_RETCODE_INVALID_PARAM; @@ -6306,7 +7039,7 @@ ni_retcode_t ni_ai_frame_buffer_alloc(ni_frame_t *p_frame, ni_log(NI_LOG_DEBUG, "%s(): reuse p_frame buffer\n", __func__); } - p_frame->p_data[0] = (uint8_t *)p_frame->p_buffer; + p_frame->p_data[0] = p_frame->p_buffer; p_frame->p_data[1] = NULL; p_frame->p_data[2] = NULL; p_frame->p_data[3] = NULL; @@ -6381,8 +7114,8 @@ ni_retcode_t ni_ai_packet_buffer_alloc(ni_packet_t *p_packet, if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): Cannot allocate p_frame buffer.\n", - __func__); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate p_packet buffer.\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -6440,6 +7173,55 @@ ni_retcode_t ni_reconfig_bitrate(ni_session_context_t *p_ctx, int32_t bitrate) return NI_RETCODE_SUCCESS; } +/*!***************************************************************************** + * \brief Reconfigure VUI HRD dynamically during encoding. + * + * \param[in] p_ctx Pointer to caller allocated ni_session_context_t + * \param[in] bitrate Target bitrate to set + * + * \return On success NI_RETCODE_SUCCESS + * On failure NI_RETCODE_INVALID_PARAM + ******************************************************************************/ +ni_retcode_t ni_reconfig_vui(ni_session_context_t *p_ctx, ni_vui_hrd_t *vui) +{ + if (!p_ctx || vui->colorDescPresent < 0 || vui->colorDescPresent > 1) + { + ni_log(NI_LOG_ERROR, "ERROR: %s(): invalid colorDescPresent passed in %d\n", + __func__, vui->colorDescPresent); + return NI_RETCODE_INVALID_PARAM; + } + + if ((vui->aspectRatioWidth > NI_MAX_ASPECTRATIO) || (vui->aspectRatioHeight > NI_MAX_ASPECTRATIO)) + { + ni_log(NI_LOG_ERROR, "ERROR: %s(): invalid aspect ratio passed in (%dx%d)\n", + __func__, vui->aspectRatioWidth, vui->aspectRatioHeight); + return NI_RETCODE_INVALID_PARAM; + } + + if (vui->videoFullRange < 0 || vui->videoFullRange > 1) + { + ni_log(NI_LOG_ERROR, "ERROR: %s(): invalid videoFullRange passed in %d\n", + __func__, vui->videoFullRange); + return NI_RETCODE_INVALID_PARAM; + } + + ni_pthread_mutex_lock(p_ctx->xcoder_mutex); + p_ctx->xcoder_state |= NI_XCODER_GENERAL_STATE; + + p_ctx->vui.colorDescPresent = vui->colorDescPresent; + p_ctx->vui.colorPrimaries = vui->colorPrimaries; + p_ctx->vui.colorTrc = vui->colorTrc; + p_ctx->vui.colorSpace = vui->colorSpace; + p_ctx->vui.aspectRatioWidth = vui->aspectRatioWidth; + p_ctx->vui.aspectRatioHeight = vui->aspectRatioHeight; + p_ctx->vui.videoFullRange = vui->videoFullRange; + + p_ctx->xcoder_state &= ~NI_XCODER_GENERAL_STATE; + ni_pthread_mutex_unlock(p_ctx->xcoder_mutex); + + return NI_RETCODE_SUCCESS; +} + /*!***************************************************************************** * \brief Force next frame to be IDR frame during encoding. * @@ -6647,7 +7429,8 @@ int ni_device_session_acquire(ni_session_context_t *p_ctx, ni_frame_t *p_frame) if (p_ctx == NULL || p_frame == NULL || p_frame->p_data[3] == NULL) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } @@ -6667,7 +7450,7 @@ int ni_device_session_acquire(ni_session_context_t *p_ctx, ni_frame_t *p_frame) return retval; } - retval = ni_get_memory_offset(&hwdesc, &offset); + retval = ni_get_memory_offset(p_ctx, &hwdesc, &offset); if (retval != NI_RETCODE_SUCCESS) { ni_log(NI_LOG_ERROR, "ERROR: bad buffer id\n"); @@ -6895,13 +7678,48 @@ ni_retcode_t ni_hwframe_p2p_buffer_recycle(ni_frame_t *p_frame) if (p_surface == NULL) { - ni_log(NI_LOG_ERROR, "%s: Invalid frame\n", __func__); + ni_log(NI_LOG_ERROR, "%s: Invalid surface data\n", __func__); return NI_RETCODE_INVALID_PARAM; } rc = ni_hwframe_buffer_recycle(p_surface, p_surface->device_handle); return rc; } + +ni_retcode_t ni_scaler_p2p_frame_acquire(ni_session_context_t *p_ctx, + niFrameSurface1_t *p_surface, + int data_len) +{ + unsigned int offset; + int ret; + + ret = ni_get_memory_offset(p_ctx, p_surface, &offset); + if (ret != 0) + { + ni_log(NI_LOG_ERROR, "Error: bad buffer id\n"); + return NI_RETCODE_FAILURE; + } + p_surface->ui32nodeAddress = 0; + + struct netint_iocmd_export_dmabuf uexp; + uexp.fd = -1; + uexp.flags = 0; + uexp.offset = offset; + uexp.length = data_len; + uexp.domain = p_ctx->domain; + uexp.bus = p_ctx->bus; + uexp.dev = p_ctx->dev; + uexp.fn = p_ctx->fn; + uexp.bar = 4; + ret = ioctl(p_ctx->netint_fd, NETINT_IOCTL_EXPORT_DMABUF, &uexp); + if (ret < 0) + { + ni_log(NI_LOG_ERROR, "failed to export dmabuf: %s\n", strerror(errno)); + return NI_RETCODE_FAILURE; + } + p_surface->dma_buf_fd = uexp.fd; + return ret; +} #endif /*!***************************************************************************** @@ -7089,22 +7907,20 @@ int ni_encoder_session_read_stream_header(ni_session_context_t *p_ctx, { rx_size = ni_device_session_read(p_ctx, p_data, NI_DEVICE_TYPE_ENCODER); - if (rx_size > NI_FW_ENC_BITSTREAM_META_DATA_SIZE) + if (rx_size > (int)p_ctx->meta_size) { /* stream header has been read, return size */ - bytes_read += (rx_size - NI_FW_ENC_BITSTREAM_META_DATA_SIZE); + bytes_read += (rx_size - (int)p_ctx->meta_size); p_ctx->pkt_num = 1; ni_log(NI_LOG_DEBUG, "Got encoded stream header\n"); done = 1; - } - else if (rx_size != 0) + } else if (rx_size != 0) { ni_log(NI_LOG_ERROR, "Error: received rx_size = %d\n", rx_size); bytes_read = -1; done = 1; - } - else + } else { ni_log(NI_LOG_DEBUG, "No data, keep reading..\n"); continue; @@ -7113,3 +7929,98 @@ int ni_encoder_session_read_stream_header(ni_session_context_t *p_ctx, return bytes_read; } + +/*!***************************************************************************** + * \brief Get the DMA buffer file descriptor from the P2P frame + * + * \param[in] p_frame pointer to a P2P frame + * + * \return On success + * DMA buffer file descriptor + * On failure + * NI_RETCODE_INVALID_PARAM +*******************************************************************************/ +int32_t ni_get_dma_buf_file_descriptor(const ni_frame_t* p_frame) +{ + const niFrameSurface1_t *p_surface; + + if (p_frame == NULL) + { + ni_log(NI_LOG_ERROR, "%s: NULL frame\n", __func__); + return NI_RETCODE_INVALID_PARAM; + } + + p_surface = (niFrameSurface1_t *)p_frame->p_data[3]; + + if (p_surface == NULL) + { + ni_log(NI_LOG_ERROR, "%s: Invalid hw frame\n", __func__); + return NI_RETCODE_INVALID_PARAM; + } + + return p_surface->dma_buf_fd; +} + +/*!***************************************************************************** + * \brief Send sequence change information to device + * + * \param[in] p_ctx Pointer to a caller allocated + * ni_session_context_t struct + * \param[in] width input width + * \param[in] height input height + * \param[in] bit_depth_factor 1 for 8-bit YUV, 2 for 10-bit YUV + * \param[in] device_type device type (must be encoder) + * \return On success + * NI_RETCODE_SUCCESS + * On failure + * NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_MEM_ALOC + * NI_RETCODE_ERROR_NVME_CMD_FAILED + * NI_RETCODE_ERROR_INVALID_SESSION + ******************************************************************************/ +ni_retcode_t ni_device_session_sequence_change(ni_session_context_t *p_ctx, + int width, int height, int bit_depth_factor, ni_device_type_t device_type) +{ + ni_resolution_t resolution; + ni_retcode_t retval = NI_RETCODE_SUCCESS; + + // requires API version >= 54 + if (p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX] < (uint8_t)'5' || + (p_ctx->fw_rev[NI_XCODER_REVISION_API_MINOR_VER_IDX] < (uint8_t)'4' && + p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX] == (uint8_t)'5')) + { + ni_log(NI_LOG_ERROR, "Error: %s function not supported in FW API version %c%c\n", __func__, + (char)p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX], + (char)p_ctx->fw_rev[NI_XCODER_REVISION_API_MINOR_VER_IDX]); + return NI_RETCODE_ERROR_INVALID_SESSION; + } + + /* This function should be called only if sequence change is detected */ + if (p_ctx->session_run_state != SESSION_RUN_STATE_SEQ_CHANGE_DRAINING) + { + ni_log(NI_LOG_ERROR, "Error: stream header has already been read\n"); + return NI_RETCODE_ERROR_INVALID_SESSION; + } + + resolution.width = width; + resolution.height = height; + resolution.bit_depth_factor = bit_depth_factor; + + switch (device_type) + { + case NI_DEVICE_TYPE_ENCODER: + { + // config sequence change + retval = ni_encoder_session_sequence_change(p_ctx, &resolution); + break; + } + default: + { + retval = NI_RETCODE_INVALID_PARAM; + ni_log(NI_LOG_ERROR, "ERROR: Config sequence change not supported for device type: %d", device_type); + return retval; + } + } + return retval; +} + diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api.h old mode 100644 new mode 100755 index ad0f0d94..97ac951c --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api.h @@ -89,6 +89,7 @@ extern "C" #define NI_MIN_BITRATE 10000 #define NI_MAX_FRAMERATE 65535 +#define NI_MAX_ASPECTRATIO 65535 /*Values below used for VPU resolution range checking*/ #define NI_MAX_WIDTH 8192 @@ -96,12 +97,23 @@ extern "C" #define NI_MAX_HEIGHT 8192 #define NI_MIN_HEIGHT 128 +#define NI_2PASS_ENCODE_MIN_WIDTH 272 +#define NI_2PASS_ENCODE_MIN_HEIGHT 256 + +#define NI_MULTICORE_ENCODE_MIN_WIDTH 256 +#define NI_MULTICORE_ENCODE_MIN_HEIGHT 256 + /*Values below used for parameter resolution range checking*/ #define NI_PARAM_MAX_WIDTH 8192 #define NI_PARAM_MIN_WIDTH 32 #define NI_PARAM_MAX_HEIGHT 8192 #define NI_PARAM_MIN_HEIGHT 32 +#define NI_PARAM_JPEG_MIN_WIDTH 48 +#define NI_PARAM_JPEG_MIN_HEIGHT 48 + +#define NI_PARAM_AV1_MIN_WIDTH 144 +#define NI_PARAM_AV1_MIN_HEIGHT 128 #define NI_PARAM_AV1_MAX_WIDTH 4096 #define NI_PARAM_AV1_MAX_HEIGHT 4352 #define NI_PARAM_AV1_MAX_AREA (4096 * 2304) @@ -134,6 +146,8 @@ extern "C" #define NI_MAX_BIN 1 #define NI_MIN_BIN 0 #define NI_MAX_NUM_SESSIONS 32 +#define NI_MIN_FRAME_SIZE 0 +#define NI_MAX_FRAME_SIZE (7680*4320*3) #define RC_SUCCESS true #define RC_ERROR false @@ -148,10 +162,12 @@ extern "C" #define GC620_I420 0x103 #define GC620_P010_MSB 0x108 #define GC620_I010 0x10A -#define GC620_YUYV 0x100 -#define GC620_NV16 0x106 +#define GC620_YUYV 0x100 +#define GC620_UYVY 0x101 +#define GC620_NV16 0x106 #define GC620_RGBA8888 0 #define GC620_BGRA8888 4 +#define GC620_BGRX8888 5 #define GC620_ABGR8888 12 #define GC620_ARGB8888 15 #define GC620_RGB565 3 @@ -182,21 +198,31 @@ typedef enum typedef enum { - NI_PIX_FMT_YUV420P = 0, /* 8-bit YUV420 planar */ - NI_PIX_FMT_YUV420P10LE = 1, /* 10-bit YUV420 planar */ - NI_PIX_FMT_NV12 = 2, /* 8-bit YUV420 semi-planar */ - NI_PIX_FMT_P010LE = 3, /* 10-bit YUV420 semi-planar */ - NI_PIX_FMT_RGBA = 4, /* 32-bit RGBA packed */ - NI_PIX_FMT_NONE = 5, /* invalid format */ + NI_PIX_FMT_YUV420P = 0, /* 8-bit YUV420 planar */ + NI_PIX_FMT_YUV420P10LE = 1, /* 10-bit YUV420 planar */ + NI_PIX_FMT_NV12 = 2, /* 8-bit YUV420 semi-planar */ + NI_PIX_FMT_P010LE = 3, /* 10-bit YUV420 semi-planar */ + NI_PIX_FMT_RGBA = 4, /* 32-bit RGBA packed */ + NI_PIX_FMT_BGRA = 5, /* 32-bit BGRA packed */ + NI_PIX_FMT_ARGB = 6, /* 32-bit ARGB packed */ + NI_PIX_FMT_ABGR = 7, /* 32-bit ABGR packed */ + NI_PIX_FMT_BGR0 = 8, /* 32-bit RGB packed */ + NI_PIX_FMT_BGRP = 9, /* 24bit RGB packed */ + NI_PIX_FMT_NV16 = 10, /* 8-bit YUV422 semi-planar */ + NI_PIX_FMT_YUYV422 = 11, /* 8-bit YUV422 */ + NI_PIX_FMT_UYVY422 = 12, /* 8-bit YUV422 */ + NI_PIX_FMT_NONE = 13, /* invalid format */ } ni_pix_fmt_t; #define NI_SCALER_FLAG_IO 0x0001 /* 0 = source frame, 1 = destination frame */ #define NI_SCALER_FLAG_PC 0x0002 /* 0 = single allocation, 1 = create pool */ #define NI_SCALER_FLAG_PA 0x0004 /* 0 = straight alpha, 1 = premultiplied alpha */ +#define NI_SCALER_FLAG_P2 0x0008 /* 0 = normal allocation, 1 = P2P allocation */ +#define NI_SCALER_FLAG_FCE 0x0010 /* 0 = no fill color, 1 = fill color enabled */ #define NI_MAX_KEEP_ALIVE_TIMEOUT 100 #define NI_MIN_KEEP_ALIVE_TIMEOUT 1 -#define NI_DEFAULT_KEEP_ALIVE_TIMEOUT 15 +#define NI_DEFAULT_KEEP_ALIVE_TIMEOUT 3 // Picked from the xcoder firmware, commit e3b882e7 #define NI_VPU_CEIL(_data, _align) (((_data)+(_align-1))&~(_align-1)) @@ -378,6 +404,11 @@ typedef enum _ni_frame_aux_data_type // payload that indicates the new target bitrate value. NI_FRAME_AUX_DATA_BITRATE, + // NETINT: custom VUI adjustment, which is a struct of + // ni_long_term_ref_t that specifies a frame's support of long term + // reference frame. + NI_FRAME_AUX_DATA_VUI, + // NETINT: long term reference frame support, which is a struct of // ni_long_term_ref_t that specifies a frame's support of long term // reference frame. @@ -446,6 +477,35 @@ typedef struct _ni_region_of_interest ni_rational_t qoffset; } ni_region_of_interest_t; +// struct describing VUI HRD support. +typedef struct _ni_vui_hrd +{ + // Indicates the presence of color info such as primaries, trc etc. + int32_t colorDescPresent; + + // Indicates the chromaticity of RGB and white components of the + // displayed image (See Table E.3 of H.265 spec) + int32_t colorPrimaries; + + // The opto-electronic transfer characteristic of the source picture + // (See Table E.4 of H.265 spec) + int32_t colorTrc; + + // Method to represent brightness, luminance or luma and colour (e.g. RGB) + int32_t colorSpace; + + // Luma sample aspect ratio width. With aspectRatioHeight, translates + // into specific display ratios such as 16:9, 4:3, etc. + int32_t aspectRatioWidth; + + // Luma sample aspect ratio height + int32_t aspectRatioHeight; + + // Input video signal sample range [0,1]. + // 0 = Y range in [16..235] Cb,Cr in [16..240]. 1 = Y,Cb,Cr in [0..255] + int32_t videoFullRange; +} ni_vui_hrd_t; + // struct describing long term reference frame support. typedef struct _ni_long_term_ref { @@ -703,7 +763,7 @@ typedef enum _ni_param_change_flags NI_SET_CHANGE_PARAM_CUSTOM_MD = (1 << 21), NI_SET_CHANGE_PARAM_CUSTOM_LAMBDA = (1 << 22), NI_SET_CHANGE_PARAM_RC2 = (1 << 23), - //NI_SET_CHANGE_PARAM_VUI_HRD_PARAM = (1 << 24), // temporarily not supported + NI_SET_CHANGE_PARAM_VUI_HRD_PARAM = (1 << 24), NI_SET_CHANGE_PARAM_INVALID_REF_FRAME = (1 << 25), NI_SET_CHANGE_PARAM_LTR_INTERVAL = (1 << 26), NI_SET_CHANGE_PARAM_RC_FRAMERATE = (1 << 27), @@ -750,12 +810,16 @@ typedef struct _ni_encoder_change_params_t #ifdef QUADRA // NI_SET_CHANGE_PARAM_VUI_HRD_PARAM - int32_t colorDescPresent; - int32_t colorPrimaries; - int32_t colorTrc; - int32_t colorSpace; - int32_t aspectRatioWidth; - int32_t aspectRatioHeight; + uint8_t colorDescPresent; /**< Indicates the presence of color info such as primaries, trc etc. in VUI */ + uint8_t colorPrimaries; /**< Indicates the chromaticity of RGB and white components of the displayed image (See Table E.3 of H.265 spec) */ + uint8_t colorTrc; /**< The opto-electronic transfer characteristic of the source picture (See Table E.4 of H.265 spec) */ + uint8_t colorSpace; /**< Method to represent brightness, luminance or luma and colour (e.g. RGB) */ + uint16_t aspectRatioWidth; /**< Luma sample aspect ratio width. With aspectRatioHeight, translates into specific display ratios such as 16:9, 4:3, etc. */ + uint16_t aspectRatioHeight; /**< Luma sample aspect ratio height */ + uint8_t videoFullRange; /**< Input video signal sample range [0,1]. 0 = Y range in [16..235] Cb,Cr in [16..240]. 1 = Y,Cb,Cr in [0..255] */ + + // RESERVED FOR FUTURE USE + uint8_t reserved[15]; // NI_SET_CHANGE_PARAM_INVALID_REF_FRAME int32_t invalidFrameNum; @@ -763,12 +827,9 @@ typedef struct _ni_encoder_change_params_t // NI_SET_CHANGE_PARAM_LTR_INTERVAL int32_t ltrInterval; - // NI_SET_CHANGE_PARAM_LTR_INTERVAL + // NI_SET_CHANGE_PARAM_RC_FRAMERATE int32_t frameRateNum; int32_t frameRateDenom; - - // RESERVED FOR FUTURE USE - //int32_t reserved[2]; #else int32_t reserved[8]; #endif @@ -810,12 +871,37 @@ typedef struct _ni_enc_mastering_display_colour_volume uint32_t min_display_mastering_luminance; } ni_enc_mastering_display_colour_volume_t; +/*!* + * \brief This is an enumeration for illustrating the custom SEI locations. + */ +typedef enum _ni_custom_sei_location +{ + NI_CUSTOM_SEI_LOC_BEFORE_VCL = 0, + NI_CUSTOM_SEI_LOC_AFTER_VCL = 1 +} ni_custom_sei_location_t; + +/*!* + * \brief custom sei payload passthrough + */ +typedef struct _ni_custom_sei +{ + uint8_t type; + ni_custom_sei_location_t location; + uint32_t size; + uint8_t data[NI_MAX_SEI_DATA]; +} ni_custom_sei_t; + +typedef struct _ni_custom_sei_set +{ + ni_custom_sei_t custom_sei[NI_MAX_CUSTOM_SEI_CNT]; + int count; +} ni_custom_sei_set_t; + /*!* * \brief hardware capability type */ typedef struct _ni_hw_capability { - uint8_t reserved; //alignment uint8_t hw_id; uint8_t max_number_of_contexts; uint8_t max_4k_fps; @@ -827,6 +913,7 @@ typedef struct _ni_hw_capability uint16_t min_video_height; uint8_t video_profile; uint8_t video_level; + uint8_t reserved; // 16B alignment. Unnecessary? } ni_hw_capability_t; /*!* @@ -841,6 +928,7 @@ typedef struct _ni_device_capability ni_hw_capability_t xcoder_devices[NI_MAX_DEVICES_PER_HW_INSTANCE]; uint8_t serial_number[20]; + uint8_t model_number[40]; uint8_t fw_rev[8]; // space right filled ASCII array, not a string uint8_t fw_branch_name[256]; @@ -861,7 +949,6 @@ typedef enum _ni_session_run_state SESSION_RUN_STATE_RESETTING = 3, } ni_session_run_state_t; - typedef struct _ni_context_query { uint32_t context_id : 8; //07:00 SW Instance ID (0 to Max number of instances) @@ -920,11 +1007,6 @@ typedef struct _ni_buf_pool_t ni_buf_t *p_used_tail; } ni_buf_pool_t; -typedef struct _ni_serial_num_t -{ - uint8_t ai8Sn[20]; -} ni_serial_num; - typedef struct _ni_queue_node_t { uint64_t timestamp; @@ -960,8 +1042,10 @@ typedef struct _ni_timestamp_table_t typedef struct _ni_session_context { - /*! LATENCY MEASUREMENT queue */ - ni_lat_meas_q_t *frame_time_q; + /*! MEASURE_LATENCY queue */ + /* frame_time_q is pointer to ni_lat_meas_q_t but reserved as void pointer + here as ni_lat_meas_q_t is part of private API */ + void *frame_time_q; uint64_t prev_read_frame_time; /*! close-caption/HDR10+ header and trailer template, used for encoder */ @@ -994,16 +1078,14 @@ typedef struct _ni_session_context int64_t pts_correction_last_dts; int pts_correction_num_faulty_pts; int64_t pts_correction_last_pts; + NI_DEPRECATED int64_t start_dts_offset; /* store pts values to create an accurate pts offset */ int64_t pts_offsets[NI_FIFO_SZ]; int pkt_index; uint64_t pkt_offsets_index[NI_FIFO_SZ]; uint64_t pkt_offsets_index_min[NI_FIFO_SZ]; - uint8_t *pkt_custom_sei[NI_FIFO_SZ]; - uint32_t pkt_custom_sei_len[NI_FIFO_SZ]; - uint8_t *last_pkt_custom_sei; - uint32_t last_pkt_custom_sei_len; + ni_custom_sei_set_t *pkt_custom_sei_set[NI_FIFO_SZ]; /*! if session is on a decoder handling incoming pkt 512-aligned */ int is_dec_pkt_512_aligned; @@ -1050,7 +1132,7 @@ typedef struct _ni_session_context ni_load_query_t load_query; /*! Leftover Buffer */ - void *p_leftover; + uint8_t *p_leftover; int prev_size; uint32_t sent_size; @@ -1058,11 +1140,6 @@ typedef struct _ni_session_context uint8_t *p_hdr_buf; uint8_t hdr_buf_size; - /*! for decoder: buffer for lone SEI as a single packet, to be sent along - with next frame */ - uint8_t buf_lone_sei[NI_MAX_SEI_DATA]; - int lone_sei_size; - /*! PTS Table */ ni_timestamp_table_t *pts_table; @@ -1110,6 +1187,9 @@ typedef struct _ni_session_context ni_queue_buffer_pool_t *buffer_pool; ni_buf_pool_t *dec_fme_buf_pool; + // original resolution this stream started with, this is used by encoder sequence change + int ori_width, ori_height, ori_bit_depth_factor, ori_pix_fmt; + // a muxter for Xcoder API, to keep the thread-safety. ni_pthread_mutex_t *xcoder_mutex; @@ -1125,13 +1205,15 @@ typedef struct _ni_session_context // ROI data int roi_side_data_size; - ni_region_of_interest_t - *av_rois; // last passed in ni_region_of_interest_t + // last passed in ni_region_of_interest_t + ni_region_of_interest_t *av_rois; int nb_rois; ni_enc_quad_roi_custom_map *roi_map; // actual AVC/HEVC QP map // encoder reconfig parameters ni_encoder_change_params_t *enc_change_params; + // decoder lowDelay mode for All I packets or IPPP packets + int decoder_low_delay; // wrapper API request data, to be sent out once with the next input frame // to encoder @@ -1141,6 +1223,7 @@ typedef struct _ni_session_context int32_t ltr_interval; // LTR interval to set int32_t ltr_frame_ref_invalid; // frame after which all ref to be invalid ni_framerate_t framerate; // framerate to reconfig, 0 if inactive + ni_vui_hrd_t vui; // vui to reconfig // path of decoder input pkt saving folder char stream_dir_name[256]; @@ -1158,6 +1241,30 @@ typedef struct _ni_session_context unsigned short bus; unsigned short dev; unsigned short fn; + + // the FW API version of device that opened + uint8_t fw_rev[8]; + uint8_t ddr_config; + + ///Params used in VFR mode Start/// + /*! Numerator and denominator of frame rate, + * used framerate change for VFR mode*/ + uint32_t prev_fps; + /*! The last setting bitrate in the VFR mode*/ + uint64_t prev_pts; + uint32_t last_change_framenum; + uint32_t fps_change_detect_count; + ///Params used in VFR mode Done/// + + uint32_t meta_size; + int64_t last_dts_interval; + int pic_reorder_delay; + + // flags_array to save packet flags + int flags_array[NI_FIFO_SZ]; + + // for decoder: store currently returned decoded frame's pkt offset + uint64_t frame_pkt_offset; } ni_session_context_t; typedef struct _ni_split_context_t @@ -1178,7 +1285,7 @@ typedef enum _ni_reconfig XCODER_TEST_RECONF_OFF = 0, XCODER_TEST_RECONF_BR = 1, //XCODER_TEST_RECONF_INTRAPRD = 2, // not required by customer - //XCODER_TEST_RECONF_VUI_HRD = 3, // temporarily not supported + XCODER_TEST_RECONF_VUI_HRD = 3, XCODER_TEST_RECONF_LONG_TERM_REF = 4, //XCODER_TEST_RECONF_RC = 5, // // not required by customer //XCODER_TEST_RECONF_RC_MIN_MAX_QP = 6, // // not required by customer @@ -1188,6 +1295,7 @@ typedef enum _ni_reconfig XCODER_TEST_RECONF_FRAMERATE = 9, XCODER_TEST_FORCE_IDR_FRAME = 100, // force IDR through libxcoder API XCODER_TEST_RECONF_BR_API = 101, // reconfig BR through libxcoder API + XCODER_TEST_RECONF_VUI_HRD_API = 103, // reconfig VUI through libxcoder API XCODER_TEST_RECONF_LTR_API = 104, // reconfig LTR through libxcoder API XCODER_TEST_RECONF_LTR_INTERVAL_API = 107, // reconf LTR interval thru API XCODER_TEST_INVALID_REF_FRAME_API = 108, // invalidate ref frame thru API @@ -1600,6 +1708,7 @@ typedef struct _ni_encoder_cfg_params #define NI_ENC_PARAM_VBV_BUFFER_SIZE "vbvBufferSize" #define NI_ENC_PARAM_ENABLE_FILLER "fillerEnable" #define NI_ENC_PARAM_ENABLE_PIC_SKIP "picSkip" +#define NI_ENC_PARAM_MAX_FRAME_SIZE_LOW_DELAY "maxFrameSize" #define NI_ENC_PARAM_LTR_REF_INTERVAL "ltrRefInterval" #define NI_ENC_PARAM_LTR_REF_QPOFFSET "ltrRefQpOffset" #define NI_ENC_PARAM_LTR_FIRST_GAP "ltrFirstGap" @@ -1617,7 +1726,6 @@ typedef struct _ni_encoder_cfg_params #define NI_ENC_PARAM_LONG_TERM_REFERENCE_ENABLE "longTermReferenceEnable" #define NI_ENC_PARAM_LONG_TERM_REFERENCE_COUNT "longTermReferenceCount" #define NI_ENC_PARAM_LONG_TERM_REFERENCE_INTERVAL "longTermReferenceInterval" - // stream color info #define NI_ENC_PARAM_COLOR_PRIMARY "colorPri" #define NI_ENC_PARAM_COLOR_TRANSFER_CHARACTERISTIC "colorTrc" @@ -1627,12 +1735,16 @@ typedef struct _ni_encoder_cfg_params #define NI_ENC_PARAM_SAR_DENOM "sarDenom" // video_full_range_flag #define NI_ENC_PARAM_VIDEO_FULL_RANGE_FLAG "videoFullRangeFlag" +// VFR related +#define NI_ENC_PARAM_ENABLE_VFR "enableVFR" +#define NI_ENC_ENABLE_SSIM "enableSSIM" //----- Start supported by all codecs ----- int frame_rate; int aspectRatioWidth; int aspectRatioHeight; int planar; + int maxFrameSize; //----- End supported by all codecs ----- //----- Start supported by AV1, AVC, HEVC only ----- @@ -1753,7 +1865,8 @@ typedef struct _ni_encoder_cfg_params int trans_rate; int enable_mb_level_rc; } rc; - int keep_alive_timeout; /* keep alive timeout setting */ + int keep_alive_timeout; /* keep alive timeout setting */ + int enable_ssim; } ni_encoder_cfg_params_t; typedef struct _ni_decoder_input_params_t @@ -1778,6 +1891,7 @@ typedef struct _ni_decoder_input_params_t #define NI_DEC_PARAM_SCALE_2 "scale2" #define NI_DEC_PARAM_MULTICORE_JOINT_MODE "multicoreJointMode" #define NI_DEC_PARAM_SAVE_PKT "savePkt" +#define NI_DEC_PARAM_LOW_DELAY "lowDelay" int hwframes; int enable_out1; @@ -1796,11 +1910,36 @@ typedef struct _ni_decoder_input_params_t [NI_MAX_PPU_PARAM_EXPR_CHAR + 1]; /*cut-out of expression to be parsed*/ int keep_alive_timeout; /* keep alive timeout setting */ + // decoder lowDelay mode for All I packets or IPPP packets + int decoder_low_delay; } ni_decoder_input_params_t; +typedef struct _ni_scaler_input_params_t +{ + int input_format; + int32_t input_width; + int32_t input_height; + int32_t in_rec_width; + int32_t in_rec_height; + int32_t in_rec_x; + int32_t in_rec_y; + + int output_format; + int32_t output_width; + int32_t output_height; + int32_t out_rec_width; + int32_t out_rec_height; + int32_t out_rec_x; + int32_t out_rec_y; + + uint32_t rgba_color; + ni_scaler_opcode_t op; +} ni_scaler_input_params_t; + typedef struct _ni_scaler_params_t { int filterblit; + int nb_inputs; } ni_scaler_params_t; typedef struct _ni_frame @@ -1865,10 +2004,10 @@ typedef struct _ni_frame // frame chunk index uint32_t frame_chunk_idx; - void *p_data[NI_MAX_NUM_DATA_POINTERS]; + uint8_t *p_data[NI_MAX_NUM_DATA_POINTERS]; uint32_t data_len[NI_MAX_NUM_DATA_POINTERS]; - void *p_buffer; + uint8_t *p_buffer; uint32_t buffer_size; ni_buf_t @@ -1876,8 +2015,7 @@ typedef struct _ni_frame uint8_t preferred_characteristics_data_len; int pixel_format; - uint8_t *p_custom_sei; - uint32_t custom_sei_len; + ni_custom_sei_set_t *p_custom_sei_set; // frame auxiliary data ni_aux_data_t *aux_data[NI_MAX_NUM_AUX_DATA_PER_FRAME]; @@ -1894,6 +2032,8 @@ typedef struct _ni_frame uint16_t sar_height; uint32_t vui_num_units_in_tick; uint32_t vui_time_scale; + + int flags; // flags of demuxed packet } ni_frame_t; typedef struct _ni_xcoder_params @@ -1951,6 +2091,7 @@ typedef struct _ni_xcoder_params ni_encoder_cfg_params_t cfg_enc_params; ni_decoder_input_params_t dec_input_params; }; + // NETINT_INTERNAL - currently only for internal testing of reconfig, saving // key:val1,val2,val3,...val9 (max 9 values) in the demo reconfig data file // this supports max 100 lines in reconfig file, max 10 key/values per line @@ -1958,6 +2099,8 @@ typedef struct _ni_xcoder_params int hwframes; int rootBufId; ni_frame_t *p_first_frame; + + int enable_vfr; //enable the vfr } ni_xcoder_params_t; typedef struct _niFrameSurface1 @@ -1993,7 +2136,6 @@ typedef struct _ni_frame_config typedef struct _ni_packet { - long long dts; long long pts; long long pos; @@ -2010,17 +2152,16 @@ typedef struct _ni_packet void* p_buffer; uint32_t buffer_size; uint32_t avg_frame_qp; // average frame QP reported by VPU - void *av1_p_buffer[MAX_AV1_ENCODER_GOP_NUM]; - void *av1_p_data[MAX_AV1_ENCODER_GOP_NUM]; + uint8_t *av1_p_buffer[MAX_AV1_ENCODER_GOP_NUM]; + uint8_t *av1_p_data[MAX_AV1_ENCODER_GOP_NUM]; uint32_t av1_buffer_size[MAX_AV1_ENCODER_GOP_NUM]; uint32_t av1_data_len[MAX_AV1_ENCODER_GOP_NUM]; int av1_buffer_index; int av1_show_frame; - uint8_t *p_custom_sei; - uint32_t custom_sei_len; - //this packet contains custom SEI payload but slice payload if set. - int no_slice; + int flags; // flags of demuxed packet + + ni_custom_sei_set_t *p_custom_sei_set; } ni_packet_t; typedef struct _ni_session_data_io @@ -2046,8 +2187,8 @@ typedef struct _ni_session_data_io #define NI_XCODER_LOG_NAME_DEBUG "debug" #define NI_XCODER_LOG_NAME_FULL "full" -extern const char* const g_xcoder_preset_names[NI_XCODER_PRESET_NAMES_ARRAY_LEN]; -extern const char* const g_xcoder_log_names[NI_XCODER_LOG_NAMES_ARRAY_LEN]; +extern LIB_API const char* const g_xcoder_preset_names[NI_XCODER_PRESET_NAMES_ARRAY_LEN]; +extern LIB_API const char* const g_xcoder_log_names[NI_XCODER_LOG_NAMES_ARRAY_LEN]; /*!***************************************************************************** * \brief Allocate and initialize a new ni_session_context_t struct @@ -2363,6 +2504,10 @@ LIB_API ni_retcode_t ni_frame_buffer_alloc(ni_frame_t *p_frame, int video_width, int metadata_flag, int factor, int hw_frame_count, int is_planar); +LIB_API ni_retcode_t ni_frame_buffer_alloc_dl(ni_frame_t *p_frame, + int video_width, int video_height, + int pixel_format); + /*!***************************************************************************** * \brief Allocate memory for decoder frame buffer based on provided * parameters; the memory is retrieved from a buffer pool and will be @@ -2402,7 +2547,8 @@ LIB_API ni_retcode_t ni_decoder_frame_buffer_alloc( * \param[in] video_height Height of the video frame * \param[in] linesize Picture line size * \param[in] alignment Allignment requirement - * \param[in] extra_len Extra data size (incl. meta data) + * \param[in] extra_len Extra data size (incl. meta data). < 0 means not + * to allocate any buffer (zero-copy from existing) * \param[in] alignment_2pass_wa set alignment to work with 2pass encode * * \return On success @@ -2415,6 +2561,17 @@ LIB_API ni_retcode_t ni_encoder_frame_buffer_alloc( ni_frame_t *pframe, int video_width, int video_height, int linesize[], int alignment, int extra_len, bool alignment_2pass_wa); +LIB_API ni_retcode_t ni_scaler_dest_frame_alloc( + ni_session_context_t *p_ctx, ni_scaler_input_params_t scaler_params, + niFrameSurface1_t *p_surface); + +LIB_API ni_retcode_t ni_scaler_input_frame_alloc( + ni_session_context_t *p_ctx, ni_scaler_input_params_t scaler_params, + niFrameSurface1_t *p_src_surface); + +LIB_API ni_retcode_t ni_scaler_frame_pool_alloc( + ni_session_context_t *p_ctx, ni_scaler_input_params_t scaler_params); + /*!***************************************************************************** * \brief Allocate memory for the frame buffer based on provided parameters * taking into account pic line size and extra data. @@ -2425,7 +2582,8 @@ LIB_API ni_retcode_t ni_encoder_frame_buffer_alloc( * \param[in] video_width Width of the video frame * \param[in] video_height Height of the video frame * \param[in] linesize Picture line size -* \param[in] extra_len Extra data size (incl. meta data) +* \param[in] extra_len Extra data size (incl. meta data). < 0 means not +* to allocate any buffer (zero-copy from existing) * \param[in] alignment_2pass_wa set alignment to work with 2pass encode * * \return On success @@ -2439,6 +2597,43 @@ LIB_API ni_retcode_t ni_frame_buffer_alloc_nv(ni_frame_t *p_frame, int linesize[], int extra_len, bool alignment_2pass_wa); +/*!***************************************************************************** + * \brief This API is a wrapper for ni_encoder_frame_buffer_alloc(), used + * for planar pixel formats, and ni_frame_buffer_alloc_nv(), used for + * semi-planar pixel formats. This API is meant to combine the + * functionality for both formats. + * Allocate memory for the frame buffer for encoding based on given + * parameters, taking into account pic line size and extra data. + * Applicable to YUV420p(8 or 10 bit/pixel) or nv12 AVFrame. + * Cb/Cr size matches that of Y. + * + * \param[in] planar true: if planar: + * pixel_format == (NI_PIX_FMT_YUV420P || + * NI_PIX_FMT_YUV420P10LE ||NI_PIX_FMT_RGBA). + * false: semi-planar: + * pixel_format == (NI_PIX_FMT_NV12 || + * NI_PIX_FMT_P010LE). + * \param[in] p_frame Pointer to a caller allocated ni_frame_t struct + * \param[in] video_width Width of the video frame + * \param[in] video_height Height of the video frame + * \param[in] linesize Picture line size + * \param[in] alignment Allignment requirement. Only used for planar format. + * \param[in] extra_len Extra data size (incl. meta data). < 0 means not + * to allocate any buffer (zero-copy from existing) + * \param[in] alignment_2pass_wa set alignment to work with 2pass encode + * + * \return On success + * NI_RETCODE_SUCCESS + * On failure + * NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_MEM_ALOC + *****************************************************************************/ +LIB_API ni_retcode_t ni_encoder_sw_frame_buffer_alloc(bool planar, ni_frame_t *p_frame, + int video_width, int video_height, + int linesize[], int alignment, + int extra_len, + bool alignment_2pass_wa); + /*!***************************************************************************** * \brief Free frame buffer that was previously allocated with either * ni_frame_buffer_alloc or ni_encoder_frame_buffer_alloc or @@ -2490,6 +2685,40 @@ ni_decoder_frame_buffer_pool_return_buf(ni_buf_t *buf, LIB_API ni_retcode_t ni_packet_buffer_alloc(ni_packet_t *ppacket, int packet_size); +/*!***************************************************************************** + * \brief Allocate packet buffer using a user provided pointer, the memory + * is expected to have already been allocated. + * + * For ideal performance memory should be 4k aligned. If it is not 4K aligned + * then a temporary 4k aligned memory will be used to copy data to and from + * when writing and reading. This will negatively impact performance. + * + * This API will overwrite p_packet->buffer_size, p_packet->p_buffer and + * p_packet->p_data fields in p_packet. + * + * This API will not free any memory associated with p_packet->p_buffer and + * p_packet->p_data fields in p_packet. + * Common use case could be, + * 1. Allocate memory to pointer + * 2. Call ni_custom_packet_buffer_alloc() with allocated pointer. + * 3. Use p_packet as required. + * 4. Call ni_packet_buffer_free() to free up the memory. + * + * \param[in] p_buffer User provided pointer to be used for buffer + * \param[in] p_packet Pointer to a caller allocated + * ni_packet_t struct + * \param[in] buffer_size Buffer size + * + * \return On success + * NI_RETCODE_SUCCESS + * On failure + * NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_MEM_ALOC + ******************************************************************************/ +ni_retcode_t ni_custom_packet_buffer_alloc(void *p_buffer, + ni_packet_t *p_packet, + int buffer_size); + /*!***************************************************************************** * \brief Free packet buffer that was previously allocated with * ni_packet_buffer_alloc @@ -2885,6 +3114,25 @@ LIB_API ni_retcode_t ni_device_alloc_frame(ni_session_context_t* p_ctx, LIB_API ni_retcode_t ni_device_config_frame(ni_session_context_t *p_ctx, ni_frame_config_t *p_cfg); +/*!***************************************************************************** + * \brief Config multiple frame on the device for 2D engined + * to work on based on provided parameters + * + * \param[in] p_ctx pointer to session context + * \param[in] p_cfg_in input frame config array + * \param[in] numInCfgs number of frame config entries in the p_cfg_in array + * \param[in] p_cfg_out output frame config + * + * \return NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_INVALID_SESSION + * NI_RETCODE_ERROR_NVME_CMD_FAILED + * NI_RETCODE_ERROR_MEM_ALOC + ******************************************************************************/ +LIB_API ni_retcode_t ni_device_multi_config_frame(ni_session_context_t *p_ctx, + ni_frame_config_t p_cfg_in[], + int numInCfgs, + ni_frame_config_t *p_cfg_out); + /*!***************************************************************************** * \brief Allocate memory for the frame buffer based on provided parameters * taking into account the pixel format, width, height, stride, @@ -2971,6 +3219,18 @@ LIB_API ni_retcode_t ni_ai_packet_buffer_alloc(ni_packet_t *p_packet, LIB_API ni_retcode_t ni_reconfig_bitrate(ni_session_context_t *p_ctx, int32_t bitrate); +/*!***************************************************************************** + * \brief Reconfigure VUI dynamically during encoding. + * + * \param[in] p_ctx Pointer to caller allocated ni_session_context_t + * \param[in] bitrate Target bitrate to set + * + * \return On success NI_RETCODE_SUCCESS + * On failure NI_RETCODE_INVALID_PARAM + ******************************************************************************/ +LIB_API ni_retcode_t ni_reconfig_vui(ni_session_context_t *p_ctx, + ni_vui_hrd_t *vui); + /*!***************************************************************************** * \brief Force next frame to be IDR frame during encoding. * @@ -3134,6 +3394,10 @@ LIB_API ni_retcode_t ni_uploader_set_frame_format(ni_session_context_t *p_upl_ctx, int width, int height, ni_pix_fmt_t pixel_format, int isP2P); +LIB_API ni_retcode_t ni_scaler_p2p_frame_acquire(ni_session_context_t *p_ctx, + niFrameSurface1_t *p_surface, + int data_len); + /*!***************************************************************************** * \brief Recycle hw P2P frames * @@ -3148,7 +3412,6 @@ ni_uploader_set_frame_format(ni_session_context_t *p_upl_ctx, int width, LIB_API ni_retcode_t ni_hwframe_p2p_buffer_recycle(ni_frame_t *p_frame); #endif - /*!***************************************************************************** * \brief Read encoder stream header from the device * @@ -3167,6 +3430,41 @@ LIB_API ni_retcode_t ni_hwframe_p2p_buffer_recycle(ni_frame_t *p_frame); LIB_API int ni_encoder_session_read_stream_header(ni_session_context_t *p_ctx, ni_session_data_io_t *p_data); + +/*!***************************************************************************** + * \brief Get the DMA buffer file descriptor from the P2P frame + * + * \param[in] p_frame pointer to a P2P frame + * + * \return On success + * DMA buffer file descriptor + * On failure + * NI_RETCODE_FAILURE +*******************************************************************************/ +LIB_API int32_t ni_get_dma_buf_file_descriptor(const ni_frame_t* p_frame); + + +/*!***************************************************************************** + * \brief Send sequence change information to device + * + * \param[in] p_ctx Pointer to a caller allocated + * ni_session_context_t struct + * \param[in] width input width + * \param[in] height input height + * \param[in] bit_depth_factor 1 for 8-bit YUV, 2 for 10-bit YUV + * \param[in] device_type device type (must be encoder) + * \return On success + * NI_RETCODE_SUCCESS + * On failure + * NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_MEM_ALOC + * NI_RETCODE_ERROR_NVME_CMD_FAILED + * NI_RETCODE_ERROR_INVALID_SESSION + ******************************************************************************/ +LIB_API ni_retcode_t ni_device_session_sequence_change(ni_session_context_t *p_ctx, + int width, int height, int bit_depth_factor, ni_device_type_t device_type); + + #ifdef __cplusplus } #endif diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api_priv.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api_priv.c index b649df0f..8f776cdd 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api_priv.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api_priv.c @@ -28,8 +28,10 @@ #ifdef _WIN32 #include -#elif __linux__ +#elif __linux__ || __APPLE__ +#if __linux__ #include +#endif #include #include #include @@ -63,7 +65,7 @@ #include "ni_device_api.h" #include "ni_device_api_priv.h" #include "ni_util.h" -#include "ni_rsrc_api.h" +#include "ni_lat_meas.h" typedef enum _ni_t35_sei_mesg_type { @@ -203,7 +205,7 @@ static uint8_t g_sei_trailer[NI_CC_SEI_TRAILER_LEN] = { } \ } -#elif __linux__ +#elif __linux__ || __APPLE__ static struct stat g_nvme_stat = {0}; #ifdef XCODER_SELF_KILL_ERR @@ -333,7 +335,7 @@ static struct stat g_nvme_stat = {0}; static void decoder_dump_dir_open(ni_session_context_t *p_ctx) { #ifdef _WIN32 -#elif __linux__ +#elif __linux__ || __APPLE__ FILE *fp; char dir_name[128] = {0}; char file_name[512] = {0}; @@ -497,6 +499,21 @@ static void decoder_dump_dir_open(ni_session_context_t *p_ctx) #endif } +// check if fw_rev is higher than the specified +static uint32_t is_fw_rev_higher(ni_session_context_t* p_ctx, uint8_t major, uint8_t minor) +{ + if ((p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX] > major) || + ((p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX] == major) && + (p_ctx->fw_rev[NI_XCODER_REVISION_API_MINOR_VER_IDX] > minor))) + { + return 1; + } + else + { + return 0; + } +} + /*!****************************************************************************** * \brief Open a xcoder decoder instance * @@ -525,7 +542,6 @@ ni_retcode_t ni_decoder_session_open(ni_session_context_t* p_ctx) //Create the session if the create session flag is set if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - int i; p_ctx->device_type = NI_DEVICE_TYPE_DECODER; p_ctx->pts_table = NULL; p_ctx->dts_queue = NULL; @@ -534,7 +550,6 @@ ni_retcode_t ni_decoder_session_open(ni_session_context_t* p_ctx) p_ctx->dec_fme_buf_pool = NULL; p_ctx->prev_size = 0; p_ctx->sent_size = 0; - p_ctx->lone_sei_size = 0; p_ctx->status = 0; p_ctx->key_frame_type = 0; p_ctx->ready_to_close = 0; @@ -545,14 +560,7 @@ ni_retcode_t ni_decoder_session_open(ni_session_context_t* p_ctx) p_ctx->session_timestamp = 0; p_ctx->is_dec_pkt_512_aligned = 0; p_ctx->p_all_zero_buf = NULL; - - for (i = 0; i < NI_FIFO_SZ; i++) - { - p_ctx->pkt_custom_sei[i] = NULL; - p_ctx->pkt_custom_sei_len[i] = 0; - } - p_ctx->last_pkt_custom_sei = NULL; - p_ctx->last_pkt_custom_sei_len = 0; + memset(p_ctx->pkt_custom_sei_set, 0, NI_FIFO_SZ * sizeof(ni_custom_sei_set_t *)); //malloc zero data buffer if (ni_posix_memalign(&p_ctx->p_all_zero_buf, sysconf(_SC_PAGESIZE), @@ -633,6 +641,35 @@ ni_retcode_t ni_decoder_session_open(ni_session_context_t* p_ctx) LRETURN; } + // Send SW version to FW if FW version is higher than major 6 minor 1 + if (is_fw_rev_higher(p_ctx, (uint8_t)'6', (uint8_t)'1')) + { + // Send SW version to session manager + memset(p_buffer, 0, NI_DATA_BUFFER_LEN); + memcpy(p_buffer, NI_XCODER_REVISION, sizeof(uint64_t)); + ni_log(NI_LOG_DEBUG, "%s sw_version major %c minor %c fw_rev major %c minor %c\n", __func__, + NI_XCODER_REVISION[NI_XCODER_REVISION_API_MAJOR_VER_IDX], + NI_XCODER_REVISION[NI_XCODER_REVISION_API_MINOR_VER_IDX], + p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX], + p_ctx->fw_rev[NI_XCODER_REVISION_API_MINOR_VER_IDX]); + ui32LBA = CONFIG_SESSION_SWVersion_W(p_ctx->session_id); + retval = ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, + p_buffer, NI_DATA_BUFFER_LEN, ui32LBA); + CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config, p_ctx->device_type, + p_ctx->hw_id, &(p_ctx->session_id)); + CHECK_VPU_RECOVERY(retval); + + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_ERROR, + "ERROR %s(): nvme write sw_version command " + "failed, blk_io_handle: %" PRIx64 ", hw_id, %d\n", + __func__, (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id); + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + LRETURN; + } + } + //VP9 requires a scaler session to be opened internally and attached as //well if(p_ctx->codec_format == NI_CODEC_FORMAT_VP9) @@ -678,8 +715,11 @@ ni_retcode_t ni_decoder_session_open(ni_session_context_t* p_ctx) // init for frame pts calculation p_ctx->is_first_frame = 1; - p_ctx->last_pts = 0; - p_ctx->last_dts = 0; + p_ctx->last_pts = NI_NOPTS_VALUE; + p_ctx->last_dts = NI_NOPTS_VALUE; + p_ctx->last_dts_interval = 0; + p_ctx->pts_correction_last_dts = INT64_MIN; + p_ctx->pts_correction_last_pts = INT64_MIN; //p_ctx->p_leftover = malloc(NI_MAX_PACKET_SZ * 2); p_ctx->p_leftover = malloc(p_ctx->max_nvme_io_size * 2); @@ -859,7 +899,7 @@ ni_retcode_t ni_decoder_session_close(ni_session_context_t* p_ctx, int eos_recie if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR %s(): Cannot allocate leftover buffer.\n", + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; @@ -943,13 +983,9 @@ ni_retcode_t ni_decoder_session_close(ni_session_context_t* p_ctx, int eos_recie for (i = 0; i < NI_FIFO_SZ; i++) { - ni_aligned_free(p_ctx->pkt_custom_sei[i]); - p_ctx->pkt_custom_sei_len[i] = 0; + ni_aligned_free(p_ctx->pkt_custom_sei_set[i]); } - ni_aligned_free(p_ctx->last_pkt_custom_sei); - p_ctx->last_pkt_custom_sei_len = 0; - ni_log(NI_LOG_DEBUG, "%s(): CTX[Card:%" PRIx64 " / HW:%d / INST:%d]\n", __func__, (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id); @@ -986,13 +1022,14 @@ int ni_decoder_session_write(ni_session_context_t* p_ctx, ni_packet_t* p_packet) if ((!p_ctx) || (!p_packet)) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } if ((NI_INVALID_SESSION_ID == p_ctx->session_id)) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): xcoder instance id < 0, return\n", + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; @@ -1002,7 +1039,8 @@ int ni_decoder_session_write(ni_session_context_t* p_ctx, ni_packet_t* p_packet) if ((p_packet->dts != NI_NOPTS_VALUE) && (p_ctx->frame_time_q != NULL)) { abs_time_ns = ni_gettime_ns(); - ni_lat_meas_q_add_entry(p_ctx->frame_time_q, abs_time_ns, p_packet->dts); + ni_lat_meas_q_add_entry((ni_lat_meas_q_t *)p_ctx->frame_time_q, + abs_time_ns, p_packet->dts); } #endif @@ -1025,10 +1063,8 @@ int ni_decoder_session_write(ni_session_context_t* p_ctx, ni_packet_t* p_packet) { p_ctx->biggest_bitstream_buffer_allocated = buf_info.buf_avail_size; } - if (p_ctx->frame_num && p_ctx->biggest_bitstream_buffer_allocated < packet_size) + if (p_ctx->biggest_bitstream_buffer_allocated < packet_size) { - // Aside from the first frame, - // we got ourselves a sequence change to a bigger picture! // Reallocate decoder bitstream buffers to accomodate. retval = ni_config_instance_set_decoder_params(p_ctx, packet_size); if (NI_RETCODE_SUCCESS != retval) @@ -1184,6 +1220,7 @@ int ni_decoder_session_write(ni_session_context_t* p_ctx, ni_packet_t* p_packet) if (p_ctx->is_first_frame && (p_ctx->pkt_index != -1)) { p_ctx->pts_offsets[p_ctx->pkt_index] = p_packet->pts; + p_ctx->flags_array[p_ctx->pkt_index] = p_packet->flags; p_ctx->pkt_offsets_index[p_ctx->pkt_index] = current_pkt_size/512; // assuming packet_size is 512 aligned ni_log(NI_LOG_DEBUG, "%s: pkt_index %d pkt_offsets_index %" PRIu64 @@ -1206,6 +1243,7 @@ int ni_decoder_session_write(ni_session_context_t* p_ctx, ni_packet_t* p_packet) else { p_ctx->pts_offsets[p_ctx->pkt_index % NI_FIFO_SZ] = p_packet->pts; + p_ctx->flags_array[p_ctx->pkt_index % NI_FIFO_SZ] = p_packet->flags; if (p_ctx->pkt_index == 0) { p_ctx->pkt_offsets_index_min[p_ctx->pkt_index % NI_FIFO_SZ] = 0; @@ -1253,16 +1291,15 @@ int ni_decoder_session_write(ni_session_context_t* p_ctx, ni_packet_t* p_packet) } /* if this wrap-around pkt_offset_index spot is about to be overwritten, free the previous one. */ - ni_aligned_free(p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_FIFO_SZ]); + ni_aligned_free(p_ctx->pkt_custom_sei_set[p_ctx->pkt_index % NI_FIFO_SZ]); - if (p_packet->p_custom_sei) + if (p_packet->p_custom_sei_set) { - p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_FIFO_SZ] = malloc(p_packet->custom_sei_len); - if (p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_FIFO_SZ]) + p_ctx->pkt_custom_sei_set[p_ctx->pkt_index % NI_FIFO_SZ] = malloc(sizeof(ni_custom_sei_set_t)); + if (p_ctx->pkt_custom_sei_set[p_ctx->pkt_index % NI_FIFO_SZ]) { - memcpy(p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_FIFO_SZ], p_packet->p_custom_sei, - p_packet->custom_sei_len); - p_ctx->pkt_custom_sei_len[p_ctx->pkt_index % NI_FIFO_SZ] = p_packet->custom_sei_len; + ni_custom_sei_set_t *p_custom_sei_set = p_ctx->pkt_custom_sei_set[p_ctx->pkt_index % NI_FIFO_SZ]; + memcpy(p_custom_sei_set, p_packet->p_custom_sei_set, sizeof(ni_custom_sei_set_t)); } else { @@ -1271,52 +1308,13 @@ int ni_decoder_session_write(ni_session_context_t* p_ctx, ni_packet_t* p_packet) "Error %s: failed to allocate custom SEI buffer for pkt.\n", __func__); } - - if (p_packet->no_slice) - { - /* this pkt contains custom sei data, but no slice data. - * store it for the next pkt which contains slice data. */ - p_ctx->last_pkt_custom_sei = malloc(p_packet->custom_sei_len); - if (p_ctx->last_pkt_custom_sei) - { - memcpy(p_ctx->last_pkt_custom_sei, p_packet->p_custom_sei, p_packet->custom_sei_len); - p_ctx->last_pkt_custom_sei_len = p_packet->custom_sei_len; - } - else - { - /* warn and lose the sei data. */ - ni_log(NI_LOG_ERROR, - "Error %s: failed to allocate custom SEI buffer for pkt.\n", - __func__); - } - } - else - { - if (p_ctx->last_pkt_custom_sei) - { - /* this pkt contains slice data and sei data. lose the previous sei data. */ - ni_aligned_free(p_ctx->last_pkt_custom_sei); - p_ctx->last_pkt_custom_sei_len = 0; - } - } - } - else if (p_ctx->last_pkt_custom_sei) - { - /* last pkt contains sei data without slice data, this pkt does't contain sei data, - * take the last stored pkt sei as this pkt's sei data - * and insert into this pkt_offset_index spot. */ - p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_FIFO_SZ] = p_ctx->last_pkt_custom_sei; - p_ctx->pkt_custom_sei_len[p_ctx->pkt_index % NI_FIFO_SZ] = p_ctx->last_pkt_custom_sei_len; - p_ctx->last_pkt_custom_sei = NULL; - p_ctx->last_pkt_custom_sei_len = 0; } else { - p_ctx->pkt_custom_sei[p_ctx->pkt_index % NI_FIFO_SZ] = NULL; - p_ctx->pkt_custom_sei_len[p_ctx->pkt_index % NI_FIFO_SZ] = 0; + p_ctx->pkt_custom_sei_set[p_ctx->pkt_index % NI_FIFO_SZ] = NULL; } - p_ctx->pkt_index ++; + p_ctx->pkt_index++; } retval = ni_timestamp_register(p_ctx->buffer_pool, p_ctx->dts_queue, p_packet->dts, 0); @@ -1326,7 +1324,6 @@ int ni_decoder_session_write(ni_session_context_t* p_ctx, ni_packet_t* p_packet) "ERROR %s(): ni_timestamp_register() for dts returned %d\n", __func__, retval); } - END: if (NI_RETCODE_SUCCESS == retval) @@ -1390,12 +1387,68 @@ static int64_t guess_correct_pts(ni_session_context_t* p_ctx, int64_t reordered_ } else { - pts = dts; + if ((NI_NOPTS_VALUE == reordered_pts) || + (NI_NOPTS_VALUE == p_ctx->last_pts) || (dts >= p_ctx->last_pts)) + { + pts = dts; + } else + { + pts = reordered_pts; + } + ni_log(NI_LOG_DEBUG, "%s: (dts) pts %" PRId64 "\n", __func__, pts); } return pts; } +static int rotated_array_binary_search(uint64_t *lefts, uint64_t *rights, + int32_t size, uint64_t target) +{ + int lo = 0; + int hi = size - 1; + while (lo <= hi) + { + int mid = lo + (hi - lo) / 2; + if (lefts[mid] <= target && target < rights[mid]) + { + return mid; + } + + if (rights[mid] == 0) + { + // empty in (mid, hi) + hi = mid - 1; + continue; + } + + if (rights[lo] <= rights[mid]) + { + if (lefts[lo] <= target && target < lefts[mid]) + { + // Elements are all monotonous in (lo, mid) + hi = mid - 1; + } else + { + // Rotation in (lo, mid) + lo = mid + 1; + } + } else + { + if (rights[mid] < target && target < rights[hi]) + { + // Elements are all monotonous in (lo, mid) + lo = mid + 1; + } else + { + // Rotation in (lo, mid) + hi = mid - 1; + } + } + } + + return -1; +} + /*!****************************************************************************** * \brief Retrieve a YUV p_frame from decoder * @@ -1424,7 +1477,8 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) int query_retry = 0; uint32_t ui32LBA = 0; unsigned int bytes_read_so_far = 0; -#ifdef MEASURE_LATENCY + int query_type = INST_BUF_INFO_RW_READ; +#ifdef MEASURE_LATENCY uint64_t abs_time_ns; #endif @@ -1448,15 +1502,27 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) // p_frame->p_data[] can be NULL before actual resolution is returned by // decoder and buffer pool is allocated, so no checking here. - total_bytes_to_read = p_frame->data_len[0] + p_frame->data_len[1] + p_frame->data_len[2] + metadata_hdr_size; - ni_log(NI_LOG_DEBUG, "Total bytes to read %u\n", total_bytes_to_read); + ni_log(NI_LOG_DEBUG, "Total bytes to read %u, low_delay %u\n", + total_bytes_to_read, p_ctx->decoder_low_delay); + if (p_ctx->decoder_low_delay > 0 && !p_ctx->ready_to_close) + { + ni_log(NI_LOG_DEBUG, "frame_num = %" PRIu64 ", pkt_num = %" PRIu64 "\n", + p_ctx->frame_num, p_ctx->pkt_num); + if (p_ctx->frame_num >= p_ctx->pkt_num) + { + //nothing to query, leave + retval = NI_RETCODE_SUCCESS; + LRETURN; + } + query_type = INST_BUF_INFO_RW_READ_BUSY; + } for (;;) { query_retry++; - retval = ni_query_instance_buf_info(p_ctx, INST_BUF_INFO_RW_READ, + retval = ni_query_instance_buf_info(p_ctx, query_type, NI_DEVICE_TYPE_DECODER, &buf_info); CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query, p_ctx->device_type, p_ctx->hw_id, @@ -1510,26 +1576,42 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) ni_log(NI_LOG_TRACE, "Dec read available buf size == 0. retry=%d, eos=%d" "\n", query_retry, p_frame->end_of_stream); - if (NI_RETCODE_NVME_SC_WRITE_BUFFER_FULL == p_ctx->status && - query_retry < 1000/2) + query_retry < 1000 / 2) { ni_usleep(25); continue; } else { + if(p_ctx->decoder_low_delay>0) + { + ni_log(NI_LOG_ERROR, "Warning: low_delay mode non sequential input? Disabling LD\n"); + p_ctx->decoder_low_delay = -1; + } ni_log(NI_LOG_DEBUG, "Warning: dec read failed %d retries. rc=%d; eos=%d\n", query_retry, p_ctx->status, p_frame->end_of_stream); ni_log(NI_LOG_DEBUG, "Warning: dec read query failed %d retries. rc=%d" "\n", query_retry, retval); } - retval = NI_RETCODE_SUCCESS; LRETURN; } else { + // We have to ensure there are adequate number of DTS for picture + // reorder delay otherwise wait for more packets to be sent to decoder. + ni_timestamp_table_t *p_dts_queue = p_ctx->dts_queue; + if ((int)p_dts_queue->list.count < p_ctx->pic_reorder_delay + 1 && + !p_ctx->ready_to_close) + { + retval = NI_RETCODE_SUCCESS; + ni_log(NI_LOG_DEBUG, + "At least %d packets should be sent before reading the " + "first frame!\n", + p_ctx->pic_reorder_delay + 1); + LRETURN; + } // get actual YUV transfer size if this is the stream's very first read if (0 == p_ctx->active_video_width || 0 == p_ctx->active_video_height) { @@ -1552,6 +1634,7 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) (p_ctx->pixel_format == NI_PIX_FMT_YUV420P10LE); p_ctx->bit_depth_factor = ni_get_bitdepth_factor_from_pixfmt(p_ctx->pixel_format); //p_ctx->bit_depth_factor = data.transfer_frame_stride / data.picture_width; + p_ctx->is_first_frame = 1; ni_log(NI_LOG_DEBUG, "Info dec YUV, adjust frame size from %ux%u to " "%ux%u format = %d\n", p_frame->video_width, p_frame->video_height, @@ -1661,6 +1744,7 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) // and recv to catch and recover from a loop condition rx_size = ni_create_frame(p_frame, bytes_read_so_far, &frame_offset, false); + p_ctx->frame_pkt_offset = frame_offset; if (rx_size > 0) { @@ -1671,7 +1755,44 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) XCODER_FRAME_OFFSET_DIFF_THRES, 0, p_ctx->buffer_pool) != NI_RETCODE_SUCCESS) { - p_frame->dts = NI_NOPTS_VALUE; + if (p_ctx->last_dts != NI_NOPTS_VALUE && !p_ctx->ready_to_close) + { + p_ctx->pic_reorder_delay++; + p_frame->dts = p_ctx->last_dts + p_ctx->last_dts_interval; + ni_log(NI_LOG_DEBUG, "Padding DTS: %" PRId64 "\n", p_frame->dts); + } else + { + p_frame->dts = NI_NOPTS_VALUE; + } + } + + if (p_ctx->is_first_frame) + { + for (i = 0; i < p_ctx->pic_reorder_delay; i++) + { + if (p_ctx->last_pts == NI_NOPTS_VALUE && + p_ctx->last_dts == NI_NOPTS_VALUE) + { + // If the p_frame->pts is unknown in the very beginning we assume + // p_frame->pts == 0 as well as DTS less than PTS by 1000 * 1/timebase + if (p_frame->pts >= p_frame->dts && + p_frame->pts - p_frame->dts < 1000) + { + break; + } + } + + if (ni_timestamp_get_with_threshold( + p_ctx->dts_queue, 0, (int64_t *)&p_frame->dts, + XCODER_FRAME_OFFSET_DIFF_THRES, + p_ctx->frame_num % 500 == 0, + p_ctx->buffer_pool) != NI_RETCODE_SUCCESS) + { + p_frame->dts = NI_NOPTS_VALUE; + } + } + // Reset for DTS padding counting + p_ctx->pic_reorder_delay = 0; } if (p_ctx->is_dec_pkt_512_aligned) @@ -1683,7 +1804,6 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) if (p_frame->dts == NI_NOPTS_VALUE) { p_frame->pts = NI_NOPTS_VALUE; - p_ctx->last_dts = p_ctx->last_pts = NI_NOPTS_VALUE; } // if not a bitstream retrieve the pts of the frame corresponding to the first YUV output else if((p_ctx->pts_offsets[0] != NI_NOPTS_VALUE) && (p_ctx->pkt_index != -1)) @@ -1723,10 +1843,8 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) if ((idx != NI_MAX_DEC_REJECT) && bFound) { p_frame->pts = p_ctx->pts_offsets[idx]; - if (idx) - p_ctx->last_pts = p_ctx->pts_offsets[idx - 1]; - else - p_ctx->last_pts = p_frame->pts; + p_frame->flags = p_ctx->flags_array[idx]; + p_ctx->last_pts = p_frame->pts; p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (first frame) idx %d last_dts %" PRId64 "" @@ -1741,6 +1859,7 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) "adjusting ts.\n", __func__, p_ctx->session_id); p_frame->pts = p_ctx->pts_offsets[idx]; + p_frame->flags = p_ctx->flags_array[idx]; p_ctx->last_pts = p_frame->pts; p_ctx->last_dts = p_frame->dts; p_ctx->session_run_state = SESSION_RUN_STATE_NORMAL; @@ -1748,8 +1867,6 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) else // use pts = 0 as offset { p_frame->pts = 0; - p_ctx->last_pts = 0; - p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (zero default) dts %" PRId64 " pts " "%" PRId64 "\n", @@ -1759,8 +1876,6 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) else { p_frame->pts = 0; - p_ctx->last_pts = 0; - p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (not bitstream) dts %" PRId64 " pts " "%" PRId64 "\n", @@ -1772,8 +1887,6 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) int64_t pts_delta = p_frame->dts - p_ctx->last_dts; p_frame->pts = p_ctx->last_pts + pts_delta; - p_ctx->last_pts = p_frame->pts; - p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (!is_first_frame idx) last_dts %" PRId64 "" "dts %" PRId64 " pts_delta %" PRId64 " last_pts " @@ -1786,118 +1899,52 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) { ni_log(NI_LOG_DEBUG, "%s: frame_offset %" PRIu64 "\n", __func__, frame_offset); - //ignore timestamps if bitstream - if (p_frame->dts == NI_NOPTS_VALUE) - { - p_frame->pts = NI_NOPTS_VALUE; - p_ctx->last_dts = p_ctx->last_pts = NI_NOPTS_VALUE; - ni_log(NI_LOG_DEBUG, - "%s: (dts NI_NOPTS_VALUE) dts %" PRId64 " " - "pts %" PRId64 "\n", - __func__, p_frame->dts, p_frame->pts); - } else - { if (p_ctx->is_first_frame) { - p_ctx->is_first_frame = 0; + p_ctx->is_first_frame = 0; } - if (frame_offset == 0) + // search for the pkt_offsets of received frame according to frame_offset. + // here we get the index(i) which promises (p_ctx->pkt_offsets_index_min[i] <= frame_offset && p_ctx->pkt_offsets_index[i] > frame_offset) + // i = -1 if not found + i = rotated_array_binary_search(p_ctx->pkt_offsets_index_min, + p_ctx->pkt_offsets_index, NI_FIFO_SZ, + frame_offset); + if (i >= 0) { - if (p_ctx->pts_offsets[0] == NI_NOPTS_VALUE) - { - p_frame->pts = NI_NOPTS_VALUE; - p_ctx->last_dts = p_ctx->last_pts = NI_NOPTS_VALUE; - ni_log(NI_LOG_DEBUG, - "%s: (first frame pts NI_NOPTS_VALUE not " - "bitstream) dts %" PRId64 " pts %" PRId64 "\n", - __func__, p_frame->dts, p_frame->pts); - } - else - { - p_frame->pts = p_ctx->pts_offsets[0]; + p_frame->pts = p_ctx->pts_offsets[i]; + p_frame->flags = p_ctx->flags_array[i]; p_ctx->last_pts = p_frame->pts; p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, - "%s: (first frame) dts %" PRId64 " pts " - "%" PRId64 "\n", - __func__, p_frame->dts, p_frame->pts); - } - - if (p_ctx->pkt_custom_sei[0]) - { - p_frame->p_custom_sei = p_ctx->pkt_custom_sei[0]; - p_frame->custom_sei_len = p_ctx->pkt_custom_sei_len[0]; - p_ctx->pkt_custom_sei[0] = NULL; - p_ctx->pkt_custom_sei_len[0] = 0; - } - } - else + "%s: (found pts) dts %" PRId64 " pts " + "%" PRId64 " frame_offset %" PRIu64 " i %d " + "pkt_offsets_index_min %" PRIu64 " pkt_offsets_index " + "%" PRIu64 "\n", + __func__, p_frame->dts, p_frame->pts, frame_offset, i, + p_ctx->pkt_offsets_index_min[i], + p_ctx->pkt_offsets_index[i]); + + p_frame->p_custom_sei_set = p_ctx->pkt_custom_sei_set[i]; + p_ctx->pkt_custom_sei_set[i] = NULL; + } else { - for (i = 0 ; i < NI_FIFO_SZ ; i++) - { - if ((frame_offset >= p_ctx->pkt_offsets_index_min[i]) - &&(frame_offset < p_ctx->pkt_offsets_index[i])) - { - if (p_ctx->pts_offsets[i] == NI_NOPTS_VALUE) - { - //bitstream case - p_frame->pts = NI_NOPTS_VALUE; - p_ctx->last_dts = p_ctx->last_pts = NI_NOPTS_VALUE; - ni_log( - NI_LOG_DEBUG, - "%s: (pts NI_NOPTS_VALUE not bitstream) " - "dts %" PRId64 " pts %" PRId64 " frame_offset %" PRIu64 " " - "i %d pkt_offsets_index_min %" PRIu64 " pkt_offsets_index " - "%" PRIu64 "\n", - __func__, p_frame->dts, p_frame->pts, frame_offset, i, - p_ctx->pkt_offsets_index_min[i], - p_ctx->pkt_offsets_index[i]); - } - else - { - p_frame->pts = p_ctx->pts_offsets[i]; - p_ctx->last_pts = p_frame->pts; - p_ctx->last_dts = p_frame->dts; - ni_log(NI_LOG_DEBUG, - "%s: (found pts) dts %" PRId64 " pts " - "%" PRId64 " frame_offset %" PRIu64 " i %d " - "pkt_offsets_index_min %" PRIu64 " pkt_offsets_index " - "%" PRIu64 "\n", - __func__, p_frame->dts, p_frame->pts, frame_offset, i, - p_ctx->pkt_offsets_index_min[i], - p_ctx->pkt_offsets_index[i]); - } - - if (p_ctx->pkt_custom_sei[i % NI_FIFO_SZ]) - { - p_frame->p_custom_sei = p_ctx->pkt_custom_sei[i % NI_FIFO_SZ]; - p_frame->custom_sei_len = p_ctx->pkt_custom_sei_len[i % NI_FIFO_SZ]; - p_ctx->pkt_custom_sei[i % NI_FIFO_SZ] = NULL; - p_ctx->pkt_custom_sei_len[i % NI_FIFO_SZ] = 0; - } - break; - } - if (i == (NI_FIFO_SZ-1)) - { - //backup solution pts - p_frame->pts = p_ctx->last_pts + (p_frame->dts - p_ctx->last_dts); - p_ctx->last_pts = p_frame->pts; - p_ctx->last_dts = p_frame->dts; - ni_log(NI_LOG_ERROR, "ERROR: NO pts found consider increasing NI_FIFO_SZ!\n"); - ni_log(NI_LOG_DEBUG, - "%s: (not found use default) dts %" PRId64 " pts %" PRId64 - "\n", - __func__, p_frame->dts, p_frame->pts); - } - } + //backup solution pts + p_frame->pts = p_ctx->last_pts + (p_frame->dts - p_ctx->last_dts); + ni_log(NI_LOG_ERROR, + "ERROR: NO pts found consider increasing NI_FIFO_SZ!\n"); + ni_log(NI_LOG_DEBUG, + "%s: (not found use default) dts %" PRId64 " pts %" PRId64 + "\n", + __func__, p_frame->dts, p_frame->pts); } - } } - - int64_t best_effort_timestamp = guess_correct_pts(p_ctx, p_frame->pts, p_frame->dts); - p_frame->pts = best_effort_timestamp; + p_frame->pts = guess_correct_pts(p_ctx, p_frame->pts, p_frame->dts); + p_ctx->last_pts = p_frame->pts; + if (p_frame->dts != NI_NOPTS_VALUE && p_ctx->last_dts != NI_NOPTS_VALUE) + p_ctx->last_dts_interval = p_frame->dts - p_ctx->last_dts; + p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (best_effort_timestamp) pts %" PRId64 "\n", - __func__, best_effort_timestamp); + __func__, p_frame->pts); p_ctx->frame_num++; #ifdef XCODER_DUMP_DATA @@ -1939,8 +1986,8 @@ int ni_decoder_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame) abs_time_ns = ni_gettime_ns(); ni_log(NI_LOG_INFO, "DTS:%lld,DELTA:%lu,dLAT:%lu;\n", p_frame->dts, abs_time_ns - p_ctx->prev_read_frame_time, - ni_lat_meas_q_check_latency(p_ctx->frame_time_q, abs_time_ns, - p_frame->dts)); + ni_lat_meas_q_check_latency((ni_lat_meas_q_t *)p_ctx->frame_time_q, + abs_time_ns, p_frame->dts)); p_ctx->prev_read_frame_time = abs_time_ns; } #endif @@ -1976,7 +2023,8 @@ int ni_xcoder_session_query(ni_session_context_t *p_ctx, if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -2036,7 +2084,7 @@ ni_retcode_t ni_encoder_session_open(ni_session_context_t* p_ctx) if (!p_ctx || !p_ctx->p_session_config) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): NULL pointer p_config passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; @@ -2060,7 +2108,6 @@ ni_retcode_t ni_encoder_session_open(ni_session_context_t* p_ctx) //Check if there is an instance or we need a new one if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - int i; p_ctx->device_type = NI_DEVICE_TYPE_ENCODER; p_ctx->pts_table = NULL; p_ctx->dts_queue = NULL; @@ -2083,15 +2130,7 @@ ni_retcode_t ni_encoder_session_open(ni_session_context_t* p_ctx) p_ctx->enc_pts_r_idx = 0; p_ctx->session_run_state = SESSION_RUN_STATE_NORMAL; p_ctx->session_timestamp = 0; - - for (i = 0; i < NI_FIFO_SZ; i++) - { - p_ctx->pkt_custom_sei[i] = NULL; - p_ctx->pkt_custom_sei_len[i] = 0; - } - p_ctx->last_pkt_custom_sei = NULL; - p_ctx->last_pkt_custom_sei_len = 0; - + memset(p_ctx->pkt_custom_sei_set, 0, NI_FIFO_SZ * sizeof(ni_custom_sei_set_t *)); memset(&(p_ctx->param_err_msg[0]), 0, sizeof(p_ctx->param_err_msg)); //malloc zero data buffer @@ -2170,6 +2209,43 @@ ni_retcode_t ni_encoder_session_open(ni_session_context_t* p_ctx) LRETURN; } + // Send SW version to FW if FW version is higher than major 6 minor 1 + if (is_fw_rev_higher(p_ctx, (uint8_t)'6', (uint8_t)'1')) + { + // Send SW version to session manager + memset(p_buffer, 0, NI_DATA_BUFFER_LEN); + memcpy(p_buffer, NI_XCODER_REVISION, sizeof(uint64_t)); + ni_log(NI_LOG_DEBUG, "%s sw_version major %c minor %c fw_rev major %c minor %c\n", __func__, + NI_XCODER_REVISION[NI_XCODER_REVISION_API_MAJOR_VER_IDX], + NI_XCODER_REVISION[NI_XCODER_REVISION_API_MINOR_VER_IDX], + p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX], + p_ctx->fw_rev[NI_XCODER_REVISION_API_MINOR_VER_IDX]); + ui32LBA = CONFIG_SESSION_SWVersion_W(p_ctx->session_id); + retval = ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, + p_buffer, NI_DATA_BUFFER_LEN, ui32LBA); + CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config, p_ctx->device_type, + p_ctx->hw_id, &(p_ctx->session_id)); + CHECK_VPU_RECOVERY(retval); + + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_ERROR, + "ERROR %s(): nvme write sw_version command " + "failed, blk_io_handle: %" PRIx64 ", hw_id, %d\n", + __func__, (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id); + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + LRETURN; + } + + // For FW rev 61 or newer, initialize with the most current size + p_ctx->meta_size = sizeof(ni_metadata_enc_bstream_t); + } + else + { + // For FW rev 60 or older, initialize with metadata size 32 + p_ctx->meta_size = NI_FW_ENC_BITSTREAM_META_DATA_SIZE; + } + ni_log(NI_LOG_DEBUG, "Open session completed\n"); } @@ -2308,14 +2384,16 @@ ni_retcode_t ni_encoder_session_flush(ni_session_context_t* p_ctx) ni_log(NI_LOG_TRACE, "%s(): enter\n", __func__); if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: session context is null, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session id, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -2328,7 +2406,7 @@ ni_retcode_t ni_encoder_session_flush(ni_session_context_t* p_ctx) if(NI_RETCODE_SUCCESS != retval) { - ni_log(NI_LOG_ERROR, "ERROR: ni_config_instance_eos(), return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s(), return\n", __func__); } END: @@ -2356,14 +2434,15 @@ ni_retcode_t ni_encoder_session_close(ni_session_context_t* p_ctx, int eos_recie if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); - ni_log(NI_LOG_TRACE, "%s(): exit\n", __func__); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -2450,13 +2529,9 @@ ni_retcode_t ni_encoder_session_close(ni_session_context_t* p_ctx, int eos_recie int i; for (i = 0; i < NI_FIFO_SZ; i++) { - ni_aligned_free(p_ctx->pkt_custom_sei[i]); - p_ctx->pkt_custom_sei_len[i] = 0; + ni_aligned_free(p_ctx->pkt_custom_sei_set[i]); } - ni_aligned_free(p_ctx->last_pkt_custom_sei); - p_ctx->last_pkt_custom_sei_len = 0; - ni_log(NI_LOG_DEBUG, "%s(): CTX[Card:%" PRIx64 " / HW:%d / INST:%d]\n", __func__, (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id); @@ -2513,14 +2588,16 @@ int ni_encoder_session_write(ni_session_context_t* p_ctx, ni_frame_t* p_frame) if (!p_ctx || !p_frame) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invlid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -2529,7 +2606,8 @@ int ni_encoder_session_write(ni_session_context_t* p_ctx, ni_frame_t* p_frame) if ((p_frame->dts != NI_NOPTS_VALUE) && (p_ctx->frame_time_q != NULL)) { abs_time_ns = ni_gettime_ns(); - ni_lat_meas_q_add_entry(p_ctx->frame_time_q, abs_time_ns, p_frame->dts); + ni_lat_meas_q_add_entry((ni_lat_meas_q_t *)p_ctx->frame_time_q, + abs_time_ns, p_frame->dts); } #endif @@ -2555,6 +2633,8 @@ int ni_encoder_session_write(ni_session_context_t* p_ctx, ni_frame_t* p_frame) retval = NI_RETCODE_PARAM_INVALID_VALUE; LRETURN; } + // record actual width (in pixels / without padding) for sequnce change detection + p_ctx->actual_video_width = p_frame->video_width; /*!************ Sequence Change related stuff end*************************/ /*!********************************************************************/ @@ -2789,6 +2869,7 @@ int ni_encoder_session_read(ni_session_context_t* p_ctx, ni_packet_t* p_packet) int query_type = INST_BUF_INFO_RW_READ; uint32_t ui32LBA = 0; ni_metadata_enc_bstream_t *p_meta = NULL; + ni_metadata_enc_bstream_rev61_t *p_meta_rev61 = NULL; ni_instance_buf_info_t buf_info = { 0 }; #ifdef MEASURE_LATENCY uint64_t abs_time_ns; @@ -2798,14 +2879,16 @@ int ni_encoder_session_read(ni_session_context_t* p_ctx, ni_packet_t* p_packet) if (!p_ctx || !p_packet || !p_packet->p_data) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_DEBUG, "xcoder instance id == 0, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -2929,13 +3012,39 @@ int ni_encoder_session_read(ni_session_context_t* p_ctx, ni_packet_t* p_packet) LRETURN; } - p_meta = (ni_metadata_enc_bstream_t *)p_packet->p_data; - p_packet->pts = (int64_t)(p_meta->frame_tstamp); - p_packet->frame_type = p_meta->frame_type; - p_packet->avg_frame_qp = p_meta->avg_frame_qp; - p_packet->recycle_index = p_meta->recycle_index; - p_packet->av1_show_frame = p_meta->av1_show_frame; - ni_log(NI_LOG_DEBUG, "RECYCLE INDEX = %u!!!\n", p_meta->recycle_index); + // SSIM is supported if fw_rev is higher than major 6 minor 1. + if (is_fw_rev_higher(p_ctx, (uint8_t)'6', (uint8_t)'1')) + { + p_meta = (ni_metadata_enc_bstream_t *)p_packet->p_data; + p_packet->pts = (int64_t)(p_meta->frame_tstamp); + p_packet->frame_type = p_meta->frame_type; + p_packet->avg_frame_qp = p_meta->avg_frame_qp; + p_packet->recycle_index = p_meta->recycle_index; + p_packet->av1_show_frame = p_meta->av1_show_frame; + ni_log(NI_LOG_DEBUG, "%s RECYCLE INDEX = %u!!!\n", __FUNCTION__, p_meta->recycle_index); + + p_ctx->meta_size = p_meta->metadata_size; + + if (p_meta->ssimY != 0) + { + // The SSIM Y, U, V values returned by FW are 4 decimal places multiplied by 10000. + //Divide by 10000 to get the original value. + ni_log(NI_LOG_DEBUG, "%s: ssim Y %.4f U %.4f V %.4f\n", __FUNCTION__, + (float)p_meta->ssimY/10000, (float)p_meta->ssimU/10000, (float)p_meta->ssimV/10000); + } + } + else + { + // Up to fw_rev major 6 and minor 1, use the old meta data structure + p_meta_rev61 = (ni_metadata_enc_bstream_rev61_t *)p_packet->p_data; + p_packet->pts = (int64_t)(p_meta_rev61->frame_tstamp); + p_packet->frame_type = p_meta_rev61->frame_type; + p_packet->avg_frame_qp = p_meta_rev61->avg_frame_qp; + p_packet->recycle_index = p_meta_rev61->recycle_index; + p_packet->av1_show_frame = p_meta_rev61->av1_show_frame; + ni_log(NI_LOG_DEBUG, "%s RECYCLE INDEX = %u!!!\n", __FUNCTION__, p_meta_rev61->recycle_index); + + } p_packet->data_len = to_read_size; @@ -2999,8 +3108,8 @@ int ni_encoder_session_read(ni_session_context_t* p_ctx, ni_packet_t* p_packet) abs_time_ns = ni_gettime_ns(); ni_log(NI_LOG_INFO, "DTS:%lld,DELTA:%lu,eLAT:%lu;\n", p_packet->dts, abs_time_ns - p_ctx->prev_read_frame_time, - ni_lat_meas_q_check_latency(p_ctx->frame_time_q, abs_time_ns, - p_packet->dts)); + ni_lat_meas_q_check_latency((ni_lat_meas_q_t *)p_ctx->frame_time_q, + abs_time_ns, p_packet->dts)); p_ctx->prev_read_frame_time = abs_time_ns; } #endif @@ -3012,6 +3121,40 @@ int ni_encoder_session_read(ni_session_context_t* p_ctx, ni_packet_t* p_packet) return retval; } +/*!****************************************************************************** + * \brief Send sequnce change to a xcoder encoder instance + * + * \param + * + * \return + *******************************************************************************/ +ni_retcode_t ni_encoder_session_sequence_change(ni_session_context_t* p_ctx, ni_resolution_t *p_resolution) +{ + ni_retcode_t retval = NI_RETCODE_SUCCESS; + + ni_log(NI_LOG_TRACE, "%s(): enter\n", __func__); + + //Configure encoder sequence change + retval = ni_config_instance_set_sequence_change(p_ctx, NI_DEVICE_TYPE_ENCODER, + p_resolution); + CHECK_ERR_RC(p_ctx, retval, nvme_config_xcoder_config_set_sequence_change, + p_ctx->device_type, p_ctx->hw_id, + &(p_ctx->session_id)); + CHECK_VPU_RECOVERY(retval); + if (retval < 0) + { + ni_log(NI_LOG_ERROR, "ERROR %s(): config encoder sequence change command failed\n", + __func__); + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + } + +END: + + ni_log(NI_LOG_TRACE, "%s(): exit\n", __func__); + + return retval; +} + /*!****************************************************************************** * \brief Open a xcoder scaler instance * @@ -3036,6 +3179,21 @@ int ni_scaler_session_open(ni_session_context_t* p_ctx) LRETURN; } + if (p_ctx->scaler_operation == NI_SCALER_OPCODE_STACK) + { + if ((p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX] < '6') || + ((p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX] == '6') && + (p_ctx->fw_rev[NI_XCODER_REVISION_API_MINOR_VER_IDX] < '4'))) + { + ni_log(NI_LOG_ERROR, "ERROR: " + "FW revision %c%c is less then the minimum required 64\n", + p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX], + p_ctx->fw_rev[NI_XCODER_REVISION_API_MINOR_VER_IDX] + ); + return NI_RETCODE_ERROR_UNSUPPORTED_FW_VERSION; + } + } + if (p_ctx->session_id == NI_INVALID_SESSION_ID) { p_ctx->device_type = NI_DEVICE_TYPE_SCALER; @@ -3084,9 +3242,16 @@ int ni_scaler_session_open(ni_session_context_t* p_ctx) ui32LBA = OPEN_SESSION_CODEC(NI_DEVICE_TYPE_SCALER, ni_htonl(p_ctx->scaler_operation), 0); retval = ni_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, NI_DATA_BUFFER_LEN, ui32LBA); + if (retval != NI_RETCODE_SUCCESS) + { + ni_log(NI_LOG_ERROR, "ERROR ni_nvme_send_read_cmd\n"); + LRETURN; + } //Open will return a session status structure with a valid session id if it worked. //Otherwise the invalid session id set before the open command will stay p_ctx->session_id = ni_ntohs(((ni_session_stats_t *)p_buffer)->ui16SessionId); + p_ctx->session_timestamp = + ni_htonll(((ni_session_stats_t *)p_buffer)->ui64Session_timestamp); if (NI_INVALID_SESSION_ID == p_ctx->session_id) { ni_log(NI_LOG_ERROR, @@ -3103,25 +3268,169 @@ int ni_scaler_session_open(ni_session_context_t* p_ctx) ", p_ctx->hw_id=%d, p_ctx->session_id=%d\n", __func__, (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id); - } - - // init for frame pts calculation - p_ctx->is_first_frame = 1; - p_ctx->last_pts = 0; - p_ctx->last_dts = 0; - p_ctx->active_video_width = 0; - p_ctx->active_video_height = 0; - p_ctx->actual_video_width = 0; - -END: - - ni_aligned_free(p_buffer); - return retval; -} -/*!****************************************************************************** - * \brief close a scaler session - * + //Send keep alive timeout Info + uint64_t keep_alive_timeout = + p_ctx->keep_alive_timeout * 1000000; //send us to FW + memset(p_buffer, 0, NI_DATA_BUFFER_LEN); + memcpy(p_buffer, &keep_alive_timeout, sizeof(keep_alive_timeout)); + ni_log(NI_LOG_DEBUG, "%s keep_alive_timeout %" PRIx64 "\n", __func__, + keep_alive_timeout); + ui32LBA = CONFIG_SESSION_KeepAliveTimeout_W(p_ctx->session_id); + retval = ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, + p_buffer, NI_DATA_BUFFER_LEN, ui32LBA); + CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config, p_ctx->device_type, + p_ctx->hw_id, &(p_ctx->session_id)); + CHECK_VPU_RECOVERY(retval); + + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_ERROR, + "ERROR %s(): nvme write keep_alive_timeout command " + "failed, blk_io_handle: %" PRIx64 ", hw_id, %d\n", + __func__, (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id); + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + LRETURN; + } + + // Send SW version to FW if FW version is higher than major 6 minor 1 + if (is_fw_rev_higher(p_ctx, (uint8_t)'6', (uint8_t)'1')) + { + // Send SW version to session manager + memset(p_buffer, 0, NI_DATA_BUFFER_LEN); + memcpy(p_buffer, NI_XCODER_REVISION, sizeof(uint64_t)); + ni_log(NI_LOG_DEBUG, "%s sw_version major %c minor %c fw_rev major %c minor %c\n", __func__, + NI_XCODER_REVISION[NI_XCODER_REVISION_API_MAJOR_VER_IDX], + NI_XCODER_REVISION[NI_XCODER_REVISION_API_MINOR_VER_IDX], + p_ctx->fw_rev[NI_XCODER_REVISION_API_MAJOR_VER_IDX], + p_ctx->fw_rev[NI_XCODER_REVISION_API_MINOR_VER_IDX]); + ui32LBA = CONFIG_SESSION_SWVersion_W(p_ctx->session_id); + retval = ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, + p_buffer, NI_DATA_BUFFER_LEN, ui32LBA); + CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config, p_ctx->device_type, + p_ctx->hw_id, &(p_ctx->session_id)); + CHECK_VPU_RECOVERY(retval); + + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_ERROR, + "ERROR %s(): nvme write sw_version command " + "failed, blk_io_handle: %" PRIx64 ", hw_id, %d\n", + __func__, (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id); + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + LRETURN; + } + } + } + + // init for frame pts calculation + p_ctx->is_first_frame = 1; + p_ctx->last_pts = 0; + p_ctx->last_dts = 0; + p_ctx->active_video_width = 0; + p_ctx->active_video_height = 0; + p_ctx->actual_video_width = 0; + +#ifndef _WIN32 + if (p_ctx->isP2P) + { + int ret; + char line[256]; + char syspath[256]; + struct stat bstat; + char *block_dev; + char *dom, *bus, *dev, *fnc; + FILE *fp; + + p_ctx->netint_fd = open("/dev/netint", O_RDWR); + if (p_ctx->netint_fd < 0) + { + ni_log(NI_LOG_ERROR, "ERROR: Can't open device /dev/netint\n"); + return NI_RETCODE_FAILURE; + } + + block_dev = &p_ctx->blk_xcoder_name[0]; + if (stat(block_dev, &bstat) < 0) + { + ni_log(NI_LOG_ERROR, "failed to get stat of file %s\n", block_dev); + return NI_RETCODE_FAILURE; + } + + if ((bstat.st_mode & S_IFMT) != S_IFBLK) + { + ni_log(NI_LOG_ERROR, "%s is not a block device\n", block_dev); + return NI_RETCODE_FAILURE; + } + + ret = snprintf(syspath, sizeof(syspath) - 1, + "/sys/block/%s/device/address", block_dev + 5); + syspath[ret] = '\0'; + + fp = fopen(syspath, "r"); + + if (fp == NULL) + { + ni_log(NI_LOG_ERROR, "Failed to read address\n"); + return NI_RETCODE_FAILURE; + } + + if (fgets(line, 256, fp) == NULL) + { + ni_log(NI_LOG_ERROR, "Failed to read line from address\n"); + fclose(fp); + return NI_RETCODE_FAILURE; + } + + fclose(fp); + + errno = 0; + p_ctx->domain = strtoul(line, &dom, 16); + if (errno < 0) + { + ni_log(NI_LOG_ERROR, "Failed to read PCI domain\n"); + return NI_RETCODE_FAILURE; + } + + errno = 0; + p_ctx->bus = strtoul(dom + 1, &bus, 16); + if (errno < 0) + { + ni_log(NI_LOG_ERROR, "Failed to read PCI bus\n"); + return NI_RETCODE_FAILURE; + } + + errno = 0; + p_ctx->dev = strtoul(bus + 1, &dev, 16); + + if (errno < 0) + { + ni_log(NI_LOG_ERROR, "Failed to read PCI device\n"); + return NI_RETCODE_FAILURE; + } + + errno = 0; + p_ctx->fn = strtoul(dev + 1, &fnc, 16); + + if (errno < 0) + { + ni_log(NI_LOG_ERROR, "Falied to read PCI function\n"); + return NI_RETCODE_FAILURE; + } + + ni_log(NI_LOG_DEBUG, "PCI slot = %d:%d:%d:%d\n", p_ctx->domain, + p_ctx->bus, p_ctx->dev, p_ctx->fn); + } +#endif + +END: + + ni_aligned_free(p_buffer); + return retval; +} + +/*!****************************************************************************** + * \brief close a scaler session + * * \param[in] p_ctx pointer to session context * \param[in] eos_received (not used) * @@ -3142,7 +3451,8 @@ ni_retcode_t ni_scaler_session_close(ni_session_context_t* p_ctx, int eos_receiv if (p_ctx->session_id == NI_INVALID_SESSION_ID) { - ni_log(NI_LOG_ERROR, "ERROR %s(): invalid session\n", __func__); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -3150,7 +3460,8 @@ ni_retcode_t ni_scaler_session_close(ni_session_context_t* p_ctx, int eos_receiv //malloc data buffer if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_DATA_BUFFER_LEN)) { - ni_log(NI_LOG_ERROR, "ERROR %d: malloc scaler close data buffer failed\n", NI_ERRNO); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() malloc data buffer failed\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -3183,6 +3494,16 @@ ni_retcode_t ni_scaler_session_close(ni_session_context_t* p_ctx, int eos_receiv retry++; } +#ifndef _WIN32 + if (p_ctx->isP2P) + { + if (p_ctx->netint_fd) + { + close(p_ctx->netint_fd); + } + } +#endif + END: ni_aligned_free(p_ctx->p_all_zero_buf); @@ -3211,7 +3532,7 @@ ni_retcode_t ni_config_instance_set_scaler_params(ni_session_context_t *p_ctx, if (!p_ctx || !p_params) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): NULL pointer p_config passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; @@ -3219,7 +3540,8 @@ ni_retcode_t ni_config_instance_set_scaler_params(ni_session_context_t *p_ctx, if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -3229,10 +3551,12 @@ ni_retcode_t ni_config_instance_set_scaler_params(ni_session_context_t *p_ctx, NI_MEM_PAGE_ALIGNMENT; if (ni_posix_memalign(&p_scaler_config, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate scaler params buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() malloc p_scaler_config buffer failed\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } + memset(p_scaler_config, 0, buffer_size); //configure the session here ui32LBA = CONFIG_INSTANCE_SetScalerPara_W(p_ctx->session_id, @@ -3241,6 +3565,7 @@ ni_retcode_t ni_config_instance_set_scaler_params(ni_session_context_t *p_ctx, //Flip the bytes!! p_cfg = (ni_scaler_config_t *)p_scaler_config; p_cfg->filterblit = p_params->filterblit; + p_cfg->numInputs = p_params->nb_inputs; if (ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_scaler_config, buffer_size, ui32LBA) < 0) @@ -3249,7 +3574,7 @@ ni_retcode_t ni_config_instance_set_scaler_params(ni_session_context_t *p_ctx, "ERROR: ni_nvme_send_write_cmd failed: blk_io_handle: %" PRIx64 ", hw_id, %d, xcoder_inst_id: %d\n", (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id, p_ctx->session_id); - //Close the session since we can't configure it as per Farhan + // Close the session since we can't configure it as per fw retval = ni_scaler_session_close(p_ctx, 0); if (NI_RETCODE_SUCCESS != retval) { @@ -3320,14 +3645,15 @@ ni_retcode_t ni_scaler_alloc_frame(ni_session_context_t* p_ctx, if (p_ctx->session_id == NI_INVALID_SESSION_ID) { - ni_log(NI_LOG_ERROR, "ERROR %s(): Cannot allocate leftover buffer.\n", + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", __func__); return NI_RETCODE_ERROR_INVALID_SESSION; } if (ni_posix_memalign((void **)&p_data, sysconf(_SC_PAGESIZE), dataLen)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); return NI_RETCODE_ERROR_MEM_ALOC; } @@ -3404,14 +3730,15 @@ ni_retcode_t ni_scaler_config_frame(ni_session_context_t *p_ctx, if (p_ctx->session_id == NI_INVALID_SESSION_ID) { - ni_log(NI_LOG_ERROR, "ERROR %s(): Cannot allocate leftover buffer.\n", + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", __func__); return NI_RETCODE_ERROR_INVALID_SESSION; } if (ni_posix_memalign((void **)&p_data, sysconf(_SC_PAGESIZE), dataLen)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); return NI_RETCODE_ERROR_MEM_ALOC; } @@ -3463,6 +3790,131 @@ ni_retcode_t ni_scaler_config_frame(ni_session_context_t *p_ctx, return retval; } +/*!****************************************************************************** + * \brief config multiple frames in the scaler + * + * \param[in] p_ctx pointer to session context + * \param[in] p_cfg_in pointer to input frame config array + * \param[in] numInCfgs number of input frame configs in the p_cfg array + * \param[in] p_cfg_out pointer to output frame config + * + * \return NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_INVALID_SESSION + * NI_RETCODE_ERROR_NVME_CMD_FAILED + * NI_RETCODE_ERROR_MEM_ALOC + *******************************************************************************/ +ni_retcode_t ni_scaler_multi_config_frame(ni_session_context_t *p_ctx, + ni_frame_config_t p_cfg_in[], + int numInCfgs, + ni_frame_config_t *p_cfg_out) +{ + ni_retcode_t retval = NI_RETCODE_SUCCESS; + ni_instance_mgr_allocation_info_t *p_data, *p_data_orig; + uint32_t dataLen; + uint32_t ui32LBA = 0; + int i; + + /* Round up to nearest 4096 bytes */ + dataLen = + sizeof(ni_instance_mgr_allocation_info_t) * (numInCfgs + 1) + NI_MEM_PAGE_ALIGNMENT - 1; + dataLen = dataLen & 0xFFFFF000; + + if (!p_ctx || (!p_cfg_in && numInCfgs)) + { + return NI_RETCODE_INVALID_PARAM; + } + + if (p_ctx->session_id == NI_INVALID_SESSION_ID) + { + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); + return NI_RETCODE_ERROR_INVALID_SESSION; + } + + if (ni_posix_memalign((void **)&p_data, sysconf(_SC_PAGESIZE), dataLen)) + { + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); + return NI_RETCODE_ERROR_MEM_ALOC; + } + + memset(p_data, 0x00, dataLen); + + p_data_orig = p_data; + + for (i = 0; i < numInCfgs; i++) + { + p_data->picture_width = p_cfg_in[i].picture_width; + p_data->picture_height = p_cfg_in[i].picture_height; + p_data->picture_format = p_cfg_in[i].picture_format; + p_data->options = p_cfg_in[i].options & ~NI_SCALER_FLAG_IO; + + p_data->rectangle_width = p_cfg_in[i].rectangle_width; + p_data->rectangle_height = p_cfg_in[i].rectangle_height; + p_data->rectangle_x = p_cfg_in[i].rectangle_x; + p_data->rectangle_y = p_cfg_in[i].rectangle_y; + p_data->rgba_color = p_cfg_in[i].rgba_color; + p_data->frame_index = p_cfg_in[i].frame_index; + p_data->session_id = p_cfg_in[i].session_id; + p_data->output_index = p_cfg_in[i].output_index; + + ni_log(NI_LOG_DEBUG, + "Dev in config frame %d: W=%d; H=%d; C=%d; RW=%d; RH=%d; RX=%d; RY=%d\n", + i, p_data->picture_width, p_data->picture_height, + p_data->picture_format, p_data->rectangle_width, + p_data->rectangle_height, p_data->rectangle_x, p_data->rectangle_y); + + p_data++; + } + + if (p_cfg_out) + { + p_data->picture_width = p_cfg_out->picture_width; + p_data->picture_height = p_cfg_out->picture_height; + p_data->picture_format = p_cfg_out->picture_format; + p_data->options = p_cfg_out->options | NI_SCALER_FLAG_IO; + + p_data->rectangle_width = p_cfg_out->rectangle_width; + p_data->rectangle_height = p_cfg_out->rectangle_height; + p_data->rectangle_x = p_cfg_out->rectangle_x; + p_data->rectangle_y = p_cfg_out->rectangle_y; + p_data->rgba_color = p_cfg_out->rgba_color; + p_data->frame_index = p_cfg_out->frame_index; + + ni_log(NI_LOG_DEBUG, + "Dev out config frame: W=%d; H=%d; C=%d; RW=%d; RH=%d; RX=%d; RY=%d\n", + p_data->picture_width, p_data->picture_height, + p_data->picture_format, p_data->rectangle_width, + p_data->rectangle_height, p_data->rectangle_x, + p_data->rectangle_y); + } + + ui32LBA = CONFIG_INSTANCE_SetScalerAlloc_W(p_ctx->session_id, + NI_DEVICE_TYPE_SCALER); + + retval = ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, + p_data_orig, dataLen, ui32LBA); + CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config, + p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id)); + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_ERROR, + "ERROR: ni_nvme_send_admin_cmd failed: blk_io_handle: %" PRIx64 + ", hw_id, %u, xcoder_inst_id: %d\n", + (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id, p_ctx->session_id); + + ni_log(NI_LOG_ERROR, + "ERROR ni_scaler_config(): nvme command failed!\n"); + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + } + +// cppcheck-suppress unusedLabel +END: + + ni_aligned_free(p_data_orig); + return retval; +} + /*!****************************************************************************** * \brief Query a particular xcoder instance to get GeneralStatus data * @@ -3484,30 +3936,26 @@ int ni_query_general_status(ni_session_context_t* p_ctx, ni_device_type_t device if ((!p_ctx) || (!p_gen_status)) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (!IS_XCODER_DEVICE_TYPE(device_type)) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown device type, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown device type %d, return\n", + __func__, device_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } - if (NI_INVALID_SESSION_ID == p_ctx->session_id) - { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); - retval = NI_RETCODE_ERROR_INVALID_SESSION; - LRETURN; - } - ui32LBA = QUERY_GENERAL_GET_STATUS_R(device_type); if (ni_posix_memalign((void **)&p_buffer, sysconf(_SC_PAGESIZE), dataLen)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -3557,7 +4005,8 @@ ni_retcode_t ni_query_stream_info(ni_session_context_t* p_ctx, ni_device_type_t if ((!p_ctx) || (!p_stream_info)) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -3565,14 +4014,16 @@ ni_retcode_t ni_query_stream_info(ni_session_context_t* p_ctx, ni_device_type_t if (! (NI_DEVICE_TYPE_DECODER == device_type || NI_DEVICE_TYPE_ENCODER == device_type)) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown device type, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown device type %d, return\n", + __func__, device_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -3581,7 +4032,8 @@ ni_retcode_t ni_query_stream_info(ni_session_context_t* p_ctx, ni_device_type_t if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -3643,21 +4095,24 @@ ni_retcode_t ni_query_session_stats(ni_session_context_t *p_ctx, if ((!p_ctx) || (!p_session_stats)) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (!IS_XCODER_DEVICE_TYPE(xc_device_type)) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown device type %d, return\n", device_type); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown device type %d, return\n", + __func__, device_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -3666,8 +4121,8 @@ ni_retcode_t ni_query_session_stats(ni_session_context_t *p_ctx, if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen)) { - ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer.\n", NI_ERRNO, - __func__); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -3679,10 +4134,6 @@ ni_retcode_t ni_query_session_stats(ni_session_context_t *p_ctx, ((ni_session_stats_t *)p_buffer)->ui16SessionId = (uint16_t)NI_INVALID_SESSION_ID; - // There are some cases that FW will not dma the data but just return error status, so add a default error number. - // for example open more than 32 encoder sessions at the same time - // TODO - Farhan - Why is this here? - //((ni_session_stats_t *)p_buffer)->sess_err_no = NI_RETCODE_DEFAULT_SESSION_ERR_NO; if (ni_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, dataLen, ui32LBA) < 0) { @@ -3778,7 +4229,8 @@ int ni_query_eos(ni_session_context_t* p_ctx, ni_device_type_t device_type, ni_i if (!p_ctx || !p_stream_complete) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -3786,14 +4238,16 @@ int ni_query_eos(ni_session_context_t* p_ctx, ni_device_type_t device_type, ni_i if (! (NI_DEVICE_TYPE_DECODER == device_type || NI_DEVICE_TYPE_ENCODER == device_type)) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown device type, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown device type %d, return\n", + __func__, device_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -3859,7 +4313,8 @@ ni_retcode_t ni_query_instance_buf_info(ni_session_context_t *p_ctx, if (!p_ctx || !p_inst_buf_info) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -3869,14 +4324,16 @@ ni_retcode_t ni_query_instance_buf_info(ni_session_context_t *p_ctx, NI_DEVICE_TYPE_SCALER == device_type || NI_DEVICE_TYPE_AI == device_type)) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown device type, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown device type %d, return\n", + __func__, device_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -3905,14 +4362,16 @@ ni_retcode_t ni_query_instance_buf_info(ni_session_context_t *p_ctx, QUERY_INSTANCE_WBUFF_SIZE_BUSY_R(p_ctx->session_id, device_type); } else { - ni_log(NI_LOG_ERROR, "ERROR: Unknown query type, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown query type %d, return\n", + __func__, rw_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -3967,14 +4426,16 @@ ni_retcode_t ni_config_session_rw(ni_session_context_t *p_ctx, if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (!((SESSION_READ_CONFIG == rw_type) || (SESSION_WRITE_CONFIG == rw_type))) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown rw type, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown config type %d, return\n", + __func__, rw_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -3982,7 +4443,8 @@ ni_retcode_t ni_config_session_rw(ni_session_context_t *p_ctx, buffer_size = ((sizeof(ni_session_config_rw_t) + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT; if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate read write config buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -3993,29 +4455,31 @@ ni_retcode_t ni_config_session_rw(ni_session_context_t *p_ctx, switch(rw_type) { case SESSION_READ_CONFIG: - rw_config->uHWAccessField.ui16ReadFrameId = frame_id; - break; + rw_config->uHWAccessField.ui16ReadFrameId = frame_id; + break; case SESSION_WRITE_CONFIG: - rw_config->uHWAccessField.ui16WriteFrameId = frame_id; - break; + rw_config->uHWAccessField.ui16WriteFrameId = frame_id; + break; default: - ni_log(NI_LOG_ERROR, "ERROR: Unknown rw type, return\n"); - retval = NI_RETCODE_INVALID_PARAM; - LRETURN; + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown config type %d, return\n", + __func__, rw_type); + retval = NI_RETCODE_INVALID_PARAM; + LRETURN; } switch(rw_type) { case SESSION_READ_CONFIG: - ui32LBA = CONFIG_SESSION_Read_W(p_ctx->session_id); - break; + ui32LBA = CONFIG_SESSION_Read_W(p_ctx->session_id); + break; case SESSION_WRITE_CONFIG: - ui32LBA = CONFIG_SESSION_Write_W(p_ctx->session_id); - break; + ui32LBA = CONFIG_SESSION_Write_W(p_ctx->session_id); + break; default: - ni_log(NI_LOG_ERROR, "ERROR: Unknown rw type, return\n"); - retval = NI_RETCODE_INVALID_PARAM; - LRETURN; + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown config type %d, return\n", + __func__, rw_type); + retval = NI_RETCODE_INVALID_PARAM; + LRETURN; } if (ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, buffer_size, ui32LBA) < 0) { @@ -4049,7 +4513,8 @@ ni_retcode_t ni_config_instance_sos(ni_session_context_t* p_ctx, ni_device_type_ if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -4057,14 +4522,16 @@ ni_retcode_t ni_config_instance_sos(ni_session_context_t* p_ctx, ni_device_type_ if (! (NI_DEVICE_TYPE_DECODER == device_type || NI_DEVICE_TYPE_ENCODER == device_type)) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown device type, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown device type %d, return\n", + __func__, device_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -4100,7 +4567,8 @@ ni_retcode_t ni_config_instance_eos(ni_session_context_t* p_ctx, ni_device_type_ if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -4108,14 +4576,16 @@ ni_retcode_t ni_config_instance_eos(ni_session_context_t* p_ctx, ni_device_type_ if (! (NI_DEVICE_TYPE_DECODER == device_type || NI_DEVICE_TYPE_ENCODER == device_type)) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown device type, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown device type %d, return\n", + __func__, device_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -4152,7 +4622,8 @@ ni_retcode_t xcoder_config_instance_flush(ni_session_context_t* p_ctx, ni_device if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -4160,14 +4631,16 @@ ni_retcode_t xcoder_config_instance_flush(ni_session_context_t* p_ctx, ni_device if (! (NI_DEVICE_TYPE_DECODER == device_type || NI_DEVICE_TYPE_ENCODER == device_type)) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown device type, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown device type %d, return\n", + __func__, device_type); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -4214,30 +4687,34 @@ ni_retcode_t ni_config_instance_set_write_len(ni_session_context_t* p_ctx, ni_de if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); - retval = NI_RETCODE_INVALID_PARAM; - LRETURN; + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); + retval = NI_RETCODE_INVALID_PARAM; + LRETURN; } - if (! (NI_DEVICE_TYPE_DECODER == device_type || - NI_DEVICE_TYPE_ENCODER == device_type)) + if (!(NI_DEVICE_TYPE_DECODER == device_type || + NI_DEVICE_TYPE_ENCODER == device_type)) { - ni_log(NI_LOG_ERROR, "ERROR: Unknown device type, return\n"); - retval = NI_RETCODE_INVALID_PARAM; - LRETURN; + ni_log(NI_LOG_ERROR, "ERROR: %s() Unknown device type %d, return\n", + __func__, device_type); + retval = NI_RETCODE_INVALID_PARAM; + LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); - retval = NI_RETCODE_ERROR_INVALID_SESSION; - LRETURN; + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); + retval = NI_RETCODE_ERROR_INVALID_SESSION; + LRETURN; } buffer_size = ((sizeof(len) + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT; if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate write len config buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -4260,6 +4737,74 @@ ni_retcode_t ni_config_instance_set_write_len(ni_session_context_t* p_ctx, ni_de return retval; } +/*!****************************************************************************** + * \brief Send a p_config command to inform encoder sequence change + * + * \param ni_session_context_t p_ctx - xcoder Context + * \param ni_device_type_t device_type - xcoder type Encoder or Decoder + * \param ni_resolution_t p_resolution - sequence change resolution + * + * \return - NI_RETCODE_SUCCESS on success, NI_RETCODE_ERROR_INVALID_SESSION, NI_RETCODE_ERROR_NVME_CMD_FAILED on failure + *******************************************************************************/ +ni_retcode_t ni_config_instance_set_sequence_change(ni_session_context_t* p_ctx, ni_device_type_t device_type, ni_resolution_t *p_resolution) +{ + ni_retcode_t retval = NI_RETCODE_SUCCESS; + uint32_t ui32LBA = 0; + void * p_buffer = NULL; + uint32_t buffer_size = 0; + + ni_log(NI_LOG_TRACE, "%s(): enter\n", __func__); + + if (!p_ctx) + { + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); + retval = NI_RETCODE_INVALID_PARAM; + LRETURN; + } + + if (!(NI_DEVICE_TYPE_ENCODER == device_type)) + { + ni_log(NI_LOG_ERROR, "ERROR: Seq Change not supported for device type %d, return\n", device_type); + retval = NI_RETCODE_INVALID_PARAM; + LRETURN; + } + + if (NI_INVALID_SESSION_ID == p_ctx->session_id) + { + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); + retval = NI_RETCODE_ERROR_INVALID_SESSION; + LRETURN; + } + + buffer_size = ((sizeof(ni_resolution_t) + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT; + if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), buffer_size)) + { + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); + retval = NI_RETCODE_ERROR_MEM_ALOC; + LRETURN; + } + memset(p_buffer, 0, buffer_size); + memcpy(p_buffer, p_resolution, sizeof(ni_resolution_t)); + + ui32LBA = CONFIG_INSTANCE_SetSeqChange_W(p_ctx->session_id, device_type); + + if (ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, buffer_size, ui32LBA) < 0) + { + ni_log(NI_LOG_ERROR, "%s(): NVME command Failed\n", __func__); + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + } + +END: + + ni_aligned_free(p_buffer); + ni_log(NI_LOG_TRACE, "%s(): exit\n", __func__); + + return retval; +} + /*!****************************************************************************** * \brief Send a p_config command to configure encoding parameters. * @@ -4279,7 +4824,7 @@ ni_retcode_t ni_config_instance_set_encoder_params(ni_session_context_t* p_ctx) if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): NULL pointer p_config passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; @@ -4287,7 +4832,8 @@ ni_retcode_t ni_config_instance_set_encoder_params(ni_session_context_t* p_ctx) if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -4295,7 +4841,8 @@ ni_retcode_t ni_config_instance_set_encoder_params(ni_session_context_t* p_ctx) buffer_size = ((buffer_size + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT; if (ni_posix_memalign(&p_encoder_config, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate encConf buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -4396,21 +4943,23 @@ ni_retcode_t ni_config_instance_set_encoder_frame_params(ni_session_context_t* p if (!p_ctx || !p_params) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): NULL pointer p_config passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", __func__); return NI_RETCODE_INVALID_PARAM; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); return NI_RETCODE_ERROR_INVALID_SESSION; } buffer_size = ((buffer_size + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT; if (ni_posix_memalign((void **)&p_cfg, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate encConf buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); return NI_RETCODE_ERROR_MEM_ALOC; } @@ -4593,8 +5142,7 @@ int ni_create_frame(ni_frame_t* p_frame, uint32_t read_length, uint64_t* p_frame ni_log(NI_LOG_DEBUG, "rx_size = %d metadataSize = %d\n", rx_size, metadata_size); - p_frame->p_custom_sei = NULL; - p_frame->custom_sei_len = 0; + p_frame->p_custom_sei_set = NULL; if (rx_size == metadata_size) { @@ -4988,18 +5536,18 @@ int ni_create_frame(ni_frame_t* p_frame, uint32_t read_length, uint64_t* p_frame } } - p_frame->dts = 0; - p_frame->pts = 0; - //p_frame->end_of_stream = isEndOfStream; - p_frame->start_of_stream = 0; + p_frame->dts = NI_NOPTS_VALUE; + p_frame->pts = NI_NOPTS_VALUE; + //p_frame->end_of_stream = isEndOfStream; + p_frame->start_of_stream = 0; - if (rx_size == 0) - { - p_frame->data_len[0] = 0; - p_frame->data_len[1] = 0; - p_frame->data_len[2] = 0; - p_frame->data_len[3] = 0; - } + if (rx_size == 0) + { + p_frame->data_len[0] = 0; + p_frame->data_len[1] = 0; + p_frame->data_len[2] = 0; + p_frame->data_len[3] = 0; + } ni_log(NI_LOG_DEBUG, "received [0x%08x] data size: %d, end of stream=%u\n", read_length, rx_size, p_frame->end_of_stream); @@ -5038,6 +5586,7 @@ void ni_populate_device_capability_struct(ni_device_capability_t* p_cap, void* p } memcpy(p_cap->serial_number, p_id_data->ai8Sn, sizeof(p_cap->serial_number)); + memcpy(p_cap->model_number, p_id_data->ai8Mn, sizeof(p_cap->model_number)); memset(p_cap->fw_rev, 0, sizeof(p_cap->fw_rev)); memcpy(p_cap->fw_rev, p_id_data->ai8Fr, sizeof(p_cap->fw_rev)); @@ -5482,6 +6031,7 @@ void ni_set_custom_template(ni_session_context_t *p_ctx, p_cfg->i8intraQpDelta = p_enc->rc.intra_qp_delta; p_cfg->ui8fillerEnable = p_enc->rc.enable_filler; p_cfg->ui8picSkipEnable = p_enc->rc.enable_pic_skip; + p_cfg->ui16maxFrameSize = p_enc->maxFrameSize / 2000; p_t408->intra_period = p_enc->intra_period; p_t408->roiEnable = p_enc->roi_enable; p_t408->useLongTerm = p_enc->long_term_ref_enable; @@ -5740,6 +6290,13 @@ void ni_set_custom_template(ni_session_context_t *p_ctx, ni_fix_VUI(p_cfg->ui8VuiRbsp, p_src->pos_num_units_in_tick, p_t408->numUnitsInTick); ni_fix_VUI(p_cfg->ui8VuiRbsp, p_src->pos_time_scale, p_t408->timeScale); } + if (p_src->enable_vfr) + { + p_cfg->ui8fixedframerate = 0; + } else + { + p_cfg->ui8fixedframerate = 1; + } //new QUADRA param if (p_enc->EnableAUD != 0) @@ -5802,6 +6359,10 @@ void ni_set_custom_template(ni_session_context_t *p_ctx, p_cfg->ui8colorSpace = p_enc->colorSpace; p_cfg->ui8videoFullRange = p_enc->videoFullRange; } + if (p_enc->videoFullRange) + { + p_cfg->ui8videoFullRange = p_enc->videoFullRange; + } if (p_enc->hrdEnable != 0) { p_cfg->ui8hrdEnable = p_enc->hrdEnable; @@ -5888,6 +6449,11 @@ void ni_set_custom_template(ni_session_context_t *p_ctx, p_cfg->ui8LowDelay = p_src->low_delay_mode; } + if (p_enc->enable_ssim != 0) + { + p_cfg->ui8enableSSIM = p_enc->enable_ssim; + } + ni_log(NI_LOG_DEBUG, "lowDelay=%d\n", p_src->low_delay_mode); ni_log(NI_LOG_DEBUG, "ui8bitstreamFormat=%d\n", p_cfg->ui8bitstreamFormat); ni_log(NI_LOG_DEBUG, "i32picWidth=%d\n", p_cfg->i32picWidth); @@ -5897,6 +6463,7 @@ void ni_set_custom_template(ni_session_context_t *p_ctx, ni_log(NI_LOG_DEBUG, "i32frameRateInfo=%d\n", p_cfg->i32frameRateInfo); ni_log(NI_LOG_DEBUG, "i32vbvBufferSize=%d\n", p_cfg->i32vbvBufferSize); ni_log(NI_LOG_DEBUG, "i32userQpMax=%d\n", p_cfg->i32userQpMax); + ni_log(NI_LOG_DEBUG, "enableSSIM=%d\n", p_cfg->ui8enableSSIM); // AVC only ni_log(NI_LOG_DEBUG, "i32maxIntraSize=%d\n", p_cfg->i32maxIntraSize); ni_log(NI_LOG_DEBUG, "i32userMaxDeltaQp=%d\n", p_cfg->i32userMaxDeltaQp); @@ -6042,7 +6609,7 @@ void ni_set_custom_template(ni_session_context_t *p_ctx, ni_log(NI_LOG_DEBUG, "nrNoiseSigmaCb=%u\n", p_t408->nrNoiseSigmaCb); ni_log(NI_LOG_DEBUG, "nrNoiseSigmaCr=%u\n", p_t408->nrNoiseSigmaCr); - // newly added for T408_520 + // newly added for T408 ni_log(NI_LOG_DEBUG, "monochromeEnable=%u\n", p_t408->monochromeEnable); ni_log(NI_LOG_DEBUG, "strongIntraSmoothEnable=%u\n", p_t408->strongIntraSmoothEnable); @@ -6167,24 +6734,24 @@ void ni_set_default_template(ni_session_context_t* p_ctx, ni_encoder_config_t* p // fill in common attributes values p_config->i32picWidth = 720; p_config->i32picHeight = 480; - p_config->i32meBlkMode = 0; // (AVC ONLY) syed: 0 means use all possible block partitions - p_config->ui8sliceMode = 0; // syed: 0 means 1 slice per picture + p_config->i32meBlkMode = 0; // (AVC ONLY) 0 means use all possible block partitions + p_config->ui8sliceMode = 0; // 0 means 1 slice per picture p_config->i32frameRateInfo = 30; p_config->i32frameRateDenominator = 1; - p_config->i32vbvBufferSize = 3000; //0; // syed: parameter is ignored if rate control is off, if rate control is on, 0 means do not check vbv constraints - p_config->i32userQpMax = 51; // syed todo: this should also be h264-only parameter + p_config->i32vbvBufferSize = 3000; //0; parameter is ignored if rate control is off, if rate control is on, 0 means do not check vbv constraints + p_config->i32userQpMax = 51; // this should also be h264-only parameter // AVC only if (NI_CODEC_FORMAT_H264 == p_ctx->codec_format) { - p_config->i32maxIntraSize = 8000000; // syed: how big an intra p_frame can get? + p_config->i32maxIntraSize = 8000000; // how big an intra p_frame can get? p_config->i32userMaxDeltaQp = 51; p_config->i32userMinDeltaQp = 51; p_config->i32userQpMin = 8; } - p_config->i32bitRate = 0; //1000000; // syed todo: check if this is applicable (could be coda9 only) - p_config->i32bitRateBL = 0; // syed todo: no documentation on this parameter in documents + p_config->i32bitRate = 0; + p_config->i32bitRateBL = 0; // no documentation on this parameter in documents p_config->ui8rcEnable = 0; p_config->i32srcBitDepth = p_ctx->src_bit_depth; p_config->ui8enablePTS = 0; @@ -6228,8 +6795,8 @@ void ni_set_default_template(ni_session_context_t* p_ctx, ni_encoder_config_t* p p_config->hdrEnableVUI = 0; p_config->ui32sourceEndian = p_ctx->src_endian; - p_config->niParamT408.level = 0; // TBD - p_config->niParamT408.tier = 0; // syed 0 means main tier + p_config->niParamT408.level = 0; + p_config->niParamT408.tier = 0; // 0 means main tier p_config->niParamT408.internalBitDepth = p_ctx->src_bit_depth; p_config->niParamT408.losslessEnable = 0; @@ -6269,7 +6836,7 @@ void ni_set_default_template(ni_session_context_t* p_ctx, ni_encoder_config_t* p p_config->niParamT408.lfCrossSliceBoundaryEnable = 1; p_config->niParamT408.betaOffsetDiv2 = 0; p_config->niParamT408.tcOffsetDiv2 = 0; - p_config->niParamT408.skipIntraTrans = 1; // syed todo: do more investigation + p_config->niParamT408.skipIntraTrans = 1; p_config->niParamT408.saoEnable = 1; p_config->niParamT408.intraNxNEnable = 1; @@ -6286,7 +6853,7 @@ void ni_set_default_template(ni_session_context_t* p_ctx, ni_encoder_config_t* p p_config->niParamT408.enable_cu_level_rate_control = 1; p_config->niParamT408.enable_hvs_qp = 0; - p_config->niParamT408.hvs_qp_scale = 2; // syed todo: do more investigation + p_config->niParamT408.hvs_qp_scale = 2; p_config->niParamT408.max_delta_qp = 10; @@ -6300,7 +6867,6 @@ void ni_set_default_template(ni_session_context_t* p_ctx, ni_encoder_config_t* p p_config->niParamT408.custom_gop_params.pic_param[i].pic_type = PIC_TYPE_I; p_config->niParamT408.custom_gop_params.pic_param[i].poc_offset = 0; p_config->niParamT408.custom_gop_params.pic_param[i].pic_qp = 0; - // ToDo: value of added num_ref_pic_L0 ??? p_config->niParamT408.custom_gop_params.pic_param[i].num_ref_pic_L0 = 0; p_config->niParamT408.custom_gop_params.pic_param[i].ref_poc_L0 = 0; p_config->niParamT408.custom_gop_params.pic_param[i].ref_poc_L1 = 0; @@ -6337,7 +6903,7 @@ void ni_set_default_template(ni_session_context_t* p_ctx, ni_encoder_config_t* p p_config->niParamT408.timeScale *= 2; } - p_config->niParamT408.numTicksPocDiffOne = 0; // syed todo: verify, set to zero to try to match the model's output encoding + p_config->niParamT408.numTicksPocDiffOne = 0; p_config->niParamT408.chromaCbQpOffset = 0; p_config->niParamT408.chromaCrQpOffset = 0; @@ -6361,18 +6927,18 @@ void ni_set_default_template(ni_session_context_t* p_ctx, ni_encoder_config_t* p p_config->niParamT408.nrNoiseSigmaCb = 0; p_config->niParamT408.nrNoiseSigmaCr = 0; - p_config->niParamT408.useLongTerm = 0; // syed: keep disabled for now, need to experiment later + p_config->niParamT408.useLongTerm = 0; - // newly added for T408_520 - p_config->niParamT408.monochromeEnable = 0; // syed: do we expect monochrome input? + // newly added for T408 + p_config->niParamT408.monochromeEnable = 0; p_config->niParamT408.strongIntraSmoothEnable = 1; - p_config->niParamT408.weightPredEnable = 0; //1; // syed: enabling for better quality but need to keep an eye on performance penalty + p_config->niParamT408.weightPredEnable = 0; p_config->niParamT408.bgDetectEnable = 0; - p_config->niParamT408.bgThrDiff = 8; // syed: matching the C-model - p_config->niParamT408.bgThrMeanDiff = 1; // syed: matching the C-model - p_config->niParamT408.bgLambdaQp = 32; // syed: matching the C-model - p_config->niParamT408.bgDeltaQp = 3; // syed: matching the C-model + p_config->niParamT408.bgThrDiff = 8; // matching the C-model + p_config->niParamT408.bgThrMeanDiff = 1; // matching the C-model + p_config->niParamT408.bgLambdaQp = 32; // matching the C-model + p_config->niParamT408.bgDeltaQp = 3; // matching the C-model p_config->niParamT408.customLambdaEnable = 0; p_config->niParamT408.customMDEnable = 0; @@ -6421,7 +6987,7 @@ void ni_set_default_template(ni_session_context_t* p_ctx, ni_encoder_config_t* p p_config->niParamT408.enable_mb_level_rc = 0; else p_config->niParamT408.enable_mb_level_rc = 1; - p_config->niParamT408.entropy_coding_mode = 1; // syed: 1 means CABAC, make sure profile is main or above, can't have CABAC in baseline + p_config->niParamT408.entropy_coding_mode = 1; // 1 means CABAC, make sure profile is main or above, can't have CABAC in baseline p_config->niParamT408.forcedHeaderEnable = 0; // first IDR frame //QUADRA @@ -6463,6 +7029,8 @@ void ni_set_default_template(ni_session_context_t* p_ctx, ni_encoder_config_t* p p_config->ui8blockRCSize = 0; p_config->ui8rcQpDeltaRange = 10; p_config->ui8LowDelay = 0; + p_config->ui8fixedframerate = 1; + p_config->ui8enableSSIM = 0; } /*!****************************************************************************** @@ -6497,8 +7065,8 @@ ni_retcode_t ni_validate_custom_dec_template(ni_xcoder_params_t *p_src, p_param_warn = malloc(sizeof(p_ctx->param_err_msg)); if (!p_param_warn) { - ni_log(NI_LOG_ERROR, "ERROR: %s() p_param_warn malloc failure\n", - __func__); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() p_param_warn malloc failure\n", + NI_ERRNO, __func__); param_ret = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -6833,6 +7401,22 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, LRETURN; } } + + if(p_cfg->ui8enableSSIM != 0) + { + if (!is_fw_rev_higher(p_ctx, (uint8_t)'6', (uint8_t)'1')) + { + p_cfg->ui8enableSSIM = 0; + strncpy(p_param_warn, "enableSSIM is not supported for FW lower than Rev 62. All ssim will be 0.", max_err_len); + warning = NI_RETCODE_PARAM_WARN; + } + if ((NI_CODEC_FORMAT_H264 != p_ctx->codec_format) && (NI_CODEC_FORMAT_H265 != p_ctx->codec_format)) + { + p_cfg->ui8enableSSIM = 0; + strncpy(p_param_warn, "enableSSIM is only supported on H.264 or H.265", max_err_len); + warning = NI_RETCODE_PARAM_WARN; + } + } } if (QUADRA) @@ -6850,6 +7434,14 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, param_ret = NI_RETCODE_PARAM_ERROR_GOP_PRESET; LRETURN; } + if (p_src->source_width < 288) + { + strncpy(p_param_err, + "lookAheadDepth requires input width of at least 288", + max_err_len); + param_ret = NI_RETCODE_PARAM_ERROR_PIC_WIDTH; + LRETURN; + } } if (GOP_PRESET_IDX_DEFAULT == p_cfg->niParamT408.gop_preset_index) @@ -7054,9 +7646,6 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, warning = NI_RETCODE_PARAM_WARN; } } - } else if (NI_CODEC_FORMAT_JPEG == p_ctx->codec_format) - { - // TODO } else if (NI_CODEC_FORMAT_AV1 == p_ctx->codec_format) { if (p_cfg->niParamT408.profile != 1) @@ -7198,10 +7787,9 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, LRETURN; } - // TODO: may also need to check custom GOP pattern and block low delay GOP } - if (p_src->low_delay_mode) + if (p_src->low_delay_mode || p_cfg->ui8picSkipEnable) { if (p_cfg->niParamT408.custom_gop_params.custom_gop_size) { @@ -7209,7 +7797,10 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, { if (p_cfg->niParamT408.custom_gop_params.pic_param[i].poc_offset != (i+1)) { - strncpy(p_param_err, "Custom GOP must not have delay encode pic when lowDelay is enabled", max_err_len); + if (p_src->low_delay_mode) + strncpy(p_param_err, "Custom GOP must not include backward prediction when lowDelay is enabled", max_err_len); + else + strncpy(p_param_err, "Custom GOP must not include backward prediction when picSkip is enabled", max_err_len); param_ret = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -7217,16 +7808,53 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, } else if (1 != p_cfg->ui8gopSize && !p_cfg->ui8gopLowdelay && p_cfg->niParamT408.intra_period != 1) { - strncpy(p_param_err, "Must use low delay GOP or set GOP size 1 when lowDelay is enabled", max_err_len); + if (p_src->low_delay_mode) + strncpy(p_param_err, "Must use low delay GOP (gopPresetIdx 1,3,7,9) when lowDelay is enabled", max_err_len); + else + strncpy(p_param_err, "Must use low delay GOP (gopPresetIdx 1,3,7,9) when picSkip is enabled", max_err_len); param_ret = NI_RETCODE_PARAM_ERROR_GOP_PRESET; LRETURN; } if (p_cfg->ui8multicoreJointMode) { - strncpy(p_param_err, - "Cannot use multicoreJointMode when lowDelay is enabled", - max_err_len); + if (p_src->low_delay_mode) + strncpy(p_param_err, + "Cannot use multicoreJointMode when lowDelay is enabled", + max_err_len); + else + strncpy(p_param_err, + "Cannot use multicoreJointMode when picSkip is enabled", + max_err_len); + param_ret = NI_RETCODE_INVALID_PARAM; + LRETURN; + } + } + + if (p_src->low_delay_mode) + { + if (p_cfg->ui16maxFrameSize == 0) + { + p_cfg->ui16maxFrameSize = ((p_src->source_width * p_src->source_height * 3 / 4) * p_ctx->bit_depth_factor) / 2000; + ni_log(NI_LOG_ERROR, "%s: maxFrameSize is not set in low delay mode. Set it to half of frame size %d\n", + __func__, p_cfg->ui16maxFrameSize*2000); + } + + // minimum acceptable value of maxFrameSize is bitrate / framerate in byte + uint32_t min_maxFrameSize = ((p_cfg->i32bitRate / p_cfg->i32frameRateInfo * p_cfg->i32frameRateDenominator) / 8) / 2000; + + if (p_cfg->ui16maxFrameSize < min_maxFrameSize) + { + ni_log(NI_LOG_ERROR, "%s: maxFrameSize %d is too small. Changed to minimum value (bitrate/framerate in byte): %d\n", + __func__, p_cfg->ui16maxFrameSize*2000, min_maxFrameSize*2000); + p_cfg->ui16maxFrameSize = min_maxFrameSize; + } + } + else + { + if (p_cfg->ui16maxFrameSize != 0) + { + strncpy(p_param_err, "maxFrameSize can only be used when lowDelay is enabled", max_err_len); param_ret = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -7243,7 +7871,7 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, { if (2 == p_cfg->niParamT408.custom_gop_params.pic_param[i].pic_type) { - strncpy(p_param_err, "Custom GOP can not have B frames for gdrDuration", max_err_len); + strncpy(p_param_err, "Custom GOP can not have B frames for intra refresh", max_err_len); param_ret = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -7259,14 +7887,22 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, param_ret = NI_RETCODE_INVALID_PARAM; LRETURN; } - strncpy(p_param_warn, "GOP size forced to 1 and low delay GOP force disabled (no B frames) for gdrDuration", max_err_len); + strncpy(p_param_warn, "GOP size forced to 1 and low delay GOP force disabled (no B frames) for intra refresh", max_err_len); warning = NI_RETCODE_PARAM_WARN; p_cfg->ui8gopSize = 1; p_cfg->ui8gopLowdelay = 0; } + if (p_cfg->ui16gdrDuration == 1) + { + strncpy(p_param_err, + "intra refresh cycle (height / intraRefreshArg MB or CTU) must > 1", + max_err_len); + param_ret = NI_RETCODE_INVALID_PARAM; + LRETURN; + } if (p_cfg->ui8LookAheadDepth != 0) { - strncpy(p_param_warn, "lookaheadDepth forced to 0 (disable 2-pass) for gdrDuration", max_err_len); + strncpy(p_param_warn, "lookaheadDepth forced to 0 (disable 2-pass) for intra refresh", max_err_len); p_cfg->ui8LookAheadDepth = 0; } if (STD_HEVC == p_cfg->ui8bitstreamFormat || @@ -7274,7 +7910,7 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, { if (p_cfg->niParamT408.intra_period < p_cfg->ui16gdrDuration) { - strncpy(p_param_warn, "intraPeriod forced to match gdrDuration (intraPeriod must >= gdrDuration)", max_err_len); + strncpy(p_param_warn, "intraPeriod forced to match intra refersh cycle (intraPeriod must >= intra refersh cycle)", max_err_len); p_cfg->niParamT408.intra_period = p_cfg->ui16gdrDuration; } } @@ -7282,7 +7918,7 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, { if (p_cfg->niParamT408.avcIdrPeriod < p_cfg->ui16gdrDuration) { - strncpy(p_param_warn, "intraPeriod forced to match gdrDuration (intraPeriod must >= gdrDuration)", max_err_len); + strncpy(p_param_warn, "intraPeriod forced to match intra refersh cycle (intraPeriod must >= intra refersh cycle)", max_err_len); p_cfg->niParamT408.avcIdrPeriod = p_cfg->ui16gdrDuration; } } @@ -7440,7 +8076,6 @@ ni_retcode_t ni_validate_custom_template(ni_session_context_t *p_ctx, LRETURN; } - //if (1 == p_cfg->niParamT408.enable_mb_level_rc)//TODO QDFW-327 Remove the if and set max min QP independently { if ( p_cfg->niParamT408.minQpI < 0 || p_cfg->niParamT408.minQpI > 51 ) @@ -7628,15 +8263,6 @@ ni_retcode_t ni_check_common_params(ni_t408_config_t *p_param, LRETURN; } - // TODO: this error check will never get triggered. remove? (SZ) - if (((!low_delay) && (p_param->intra_period != 0) && ((p_param->intra_period % intra_period_gop_step_size) == 1) && p_param->decoding_refresh_type == 0) || - ((!low_delay) && (p_param->avcIdrPeriod != 0) && ((p_param->avcIdrPeriod % intra_period_gop_step_size) == 1) && p_param->decoding_refresh_type == 0)) - { - strncpy(p_param_err, "Invalid decoding_refresh_type: not support decoding refresh type I p_frame for closed gop structure", max_err_len); - ret = NI_RETCODE_PARAM_ERROR_INTRA_PERIOD; - LRETURN; - } - if (p_param->gop_preset_index == GOP_PRESET_IDX_CUSTOM) { int temp_poc[NI_MAX_GOP_NUM]; @@ -8015,6 +8641,7 @@ void *ni_session_keep_alive_thread(void *arguments) uint64_t endtime = ni_gettime_ns(); //interval(nanoseconds) is equals to ctx.keep_alive_timeout/3(330,000,000ns approximately equal to 1/3 second). uint64_t interval = args->keep_alive_timeout * 330000000LL; +#ifndef _ANDROID #ifdef __linux__ struct sched_param sched_param; @@ -8057,6 +8684,7 @@ void *ni_session_keep_alive_thread(void *arguments) ni_log(NI_LOG_DEBUG, "%s cannot set priority: %d.\n", __func__, GetLastError()); } +#endif #endif // Initializes the session context variables that keep alive command and query status command need. @@ -8197,9 +8825,16 @@ ni_retcode_t ni_uploader_session_open(ni_session_context_t* p_ctx) ui32LBA = OPEN_SESSION_CODEC(NI_DEVICE_TYPE_ENCODER, ni_htonl(p_ctx->codec_format), 1/*1 for uploadMode*/); retval = ni_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, NI_DATA_BUFFER_LEN, ui32LBA); + if (retval != NI_RETCODE_SUCCESS) + { + ni_log(NI_LOG_ERROR, "ERROR ni_nvme_send_read_cmd\n"); + LRETURN; + } //Open will return a session status structure with a valid session id if it worked. //Otherwise the invalid session id set before the open command will stay p_ctx->session_id = ni_ntohs(((ni_session_stats_t *)p_buffer)->ui16SessionId); + p_ctx->session_timestamp = + ni_htonll(((ni_session_stats_t *)p_buffer)->ui64Session_timestamp); if (NI_INVALID_SESSION_ID == p_ctx->session_id) { ni_log(NI_LOG_ERROR, @@ -8211,7 +8846,34 @@ ni_retcode_t ni_uploader_session_open(ni_session_context_t* p_ctx) retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } - ni_log(NI_LOG_DEBUG, "Uploader open session ID:0x%x\n",p_ctx->session_id); + ni_log(NI_LOG_DEBUG, + "Uploader open session ID:0x%x,timestamp:%" PRIu64 "\n", + p_ctx->session_id, p_ctx->session_timestamp); + + //Send keep alive timeout Info + uint64_t keep_alive_timeout = + p_ctx->keep_alive_timeout * 1000000; //send us to FW + memset(p_buffer, 0, NI_DATA_BUFFER_LEN); + memcpy(p_buffer, &keep_alive_timeout, sizeof(keep_alive_timeout)); + ni_log(NI_LOG_DEBUG, "%s keep_alive_timeout %" PRIx64 "\n", __func__, + keep_alive_timeout); + ui32LBA = CONFIG_SESSION_KeepAliveTimeout_W(p_ctx->session_id); + retval = ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, + p_buffer, NI_DATA_BUFFER_LEN, ui32LBA); + CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config, p_ctx->device_type, + p_ctx->hw_id, &(p_ctx->session_id)); + CHECK_VPU_RECOVERY(retval); + + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_ERROR, + "ERROR %s(): nvme write keep_alive_timeout command " + "failed, blk_io_handle: %" PRIx64 ", hw_id, %d\n", + __func__, (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id); + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + LRETURN; + } + ni_log(NI_LOG_DEBUG, "Open session completed\n"); } @@ -8434,14 +9096,16 @@ int ni_hwupload_session_write(ni_session_context_t *p_ctx, ni_frame_t *p_frame, if (!p_ctx || !p_frame) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invlid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -8450,7 +9114,8 @@ int ni_hwupload_session_write(ni_session_context_t *p_ctx, ni_frame_t *p_frame, if ((p_frame->dts != NI_NOPTS_VALUE) && (p_ctx->frame_time_q != NULL)) { abs_time_ns = ni_gettime_ns(); - ni_lat_meas_q_add_entry(p_ctx->frame_time_q, abs_time_ns, p_frame->dts); + ni_lat_meas_q_add_entry((ni_lat_meas_q_t *)p_ctx->frame_time_q, + abs_time_ns, p_frame->dts); } #endif @@ -8573,8 +9238,8 @@ int ni_hwupload_session_write(ni_session_context_t *p_ctx, ni_frame_t *p_frame, abs_time_ns = ni_gettime_ns(); ni_log(NI_LOG_INFO, "DTS:%" PRId64 ",DELTA:%lu,uLAT:%lu;\n", p_frame->dts, abs_time_ns - p_ctx->prev_read_frame_time, - ni_lat_meas_q_check_latency(p_ctx->frame_time_q, abs_time_ns, - p_frame->dts)); + ni_lat_meas_q_check_latency((ni_lat_meas_q_t *)p_ctx->frame_time_q, + abs_time_ns, p_frame->dts)); p_ctx->prev_read_frame_time = abs_time_ns; } #endif @@ -8606,55 +9271,67 @@ int ni_hwupload_session_read_hwdesc(ni_session_context_t *p_ctx, { int retval = 0; ni_instance_buf_info_t hwdesc_info = { 0 }; + int query_retry = 0; + ni_log(NI_LOG_TRACE, "%s(): enter\n", __func__); - //niFrameSurface1_t* p_data3 = (niFrameSurface1_t*)((uint8_t*)p_frame->p_data[3]); - ////p_data3->rsvd = p_meta->hwdesc->rsvd; - //ni_log(NI_LOG_DEBUG, "%s:mar16 HW=%d ui16FrameIdx=%d i8InstID=%d device_handle=%d\n", - // ishwframe, p_data3->ui16FrameIdx, p_data3->i8InstID, p_data3->device_handle); if (!p_ctx || !hwdesc) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } - if (NI_INVALID_SESSION_ID == p_ctx->session_id) - { - ni_log(NI_LOG_ERROR, "ERROR: Invlid session ID, return\n"); - retval = NI_RETCODE_ERROR_INVALID_SESSION; - LRETURN; + if (NI_INVALID_SESSION_ID == p_ctx->session_id) + { + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); + retval = NI_RETCODE_ERROR_INVALID_SESSION; + LRETURN; + } + + for (;;) + { + query_retry++; +#ifndef _WIN32 + retval = ni_query_instance_buf_info(p_ctx, INST_BUF_INFO_R_ACQUIRE, + NI_DEVICE_TYPE_ENCODER, &hwdesc_info); +#else + retval = ni_query_instance_buf_info(p_ctx, INST_BUF_INFO_RW_UPLOAD, + NI_DEVICE_TYPE_ENCODER, &hwdesc_info); +#endif + CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query, + p_ctx->device_type, p_ctx->hw_id, + &(p_ctx->session_id)); + + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_DEBUG, "Warning upload read hwdesc fail rc %d or ind " + "!\n", retval); + + if (query_retry >= 1000) + { + retval = NI_RETCODE_FAILURE; + LRETURN; + } + } + else + { + ni_log(NI_LOG_DEBUG, "Info hwupload read hwdesc success, " + "frame_ind=%d !\n", hwdesc_info.hw_inst_ind.frame_index); + + hwdesc->ui16FrameIdx = hwdesc_info.hw_inst_ind.frame_index; + hwdesc->ui16session_ID = p_ctx->session_id; + hwdesc->device_handle = + (int32_t)((int64_t)p_ctx->blk_io_handle & 0xFFFFFFFF); + hwdesc->bit_depth = p_ctx->bit_depth_factor; + hwdesc->src_cpu = (uint8_t)NI_DEVICE_TYPE_ENCODER; + hwdesc->output_idx = 0; + LRETURN; + } } -#ifndef _WIN32 - retval = ni_query_instance_buf_info(p_ctx, INST_BUF_INFO_R_ACQUIRE, - NI_DEVICE_TYPE_ENCODER, &hwdesc_info); -#else - retval = ni_query_instance_buf_info(p_ctx, INST_BUF_INFO_RW_UPLOAD, - NI_DEVICE_TYPE_ENCODER, &hwdesc_info); -#endif - CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query, - p_ctx->device_type, p_ctx->hw_id, - &(p_ctx->session_id)); - if (NI_RETCODE_SUCCESS != retval) - { - ni_log(NI_LOG_DEBUG, "Warning upload read hwdesc fail rc %d or ind " - "!\n", retval); - retval = NI_RETCODE_FAILURE; - } - else - { - ni_log(NI_LOG_DEBUG, "Info hwupload read hwdesc success, " - "frame_ind=%d !\n", hwdesc_info.hw_inst_ind.frame_index); - //hwdesc->i8InstID = hwdesc_info.hw_inst_ind.inst_id; - hwdesc->ui16FrameIdx = hwdesc_info.hw_inst_ind.frame_index; - hwdesc->ui16session_ID = p_ctx->session_id; - hwdesc->device_handle = - (int32_t)((int64_t)p_ctx->blk_io_handle & 0xFFFFFFFF); - hwdesc->bit_depth = p_ctx->bit_depth_factor; - hwdesc->src_cpu = (uint8_t)NI_DEVICE_TYPE_ENCODER; - hwdesc->output_idx = 0; - } END: return retval; } @@ -8686,7 +9363,8 @@ ni_retcode_t ni_clear_instance_buf(niFrameSurface1_t *surface, if ((uint16_t)NI_INVALID_SESSION_ID == surface->ui16session_ID) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -8694,8 +9372,8 @@ ni_retcode_t ni_clear_instance_buf(niFrameSurface1_t *surface, //malloc data buffer if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), NI_DATA_BUFFER_LEN)) { - ni_log(NI_LOG_ERROR, "ERROR %d: %s() alloc data buffer failed\n", - __func__, NI_ERRNO); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -8722,42 +9400,8 @@ ni_retcode_t ni_clear_instance_buf(niFrameSurface1_t *surface, return retval; } -/*!****************************************************************************** -* \brief Get info from received xcoder capability -* -* \param -* -* \return -*******************************************************************************/ -void ni_populate_serial_number(ni_serial_num* p_serial_num, void* p_data) -{ - ni_nvme_identity_t* p_id_data = (ni_nvme_identity_t*)p_data; - - if (!p_serial_num || !p_data) - { - ni_log(NI_LOG_ERROR, "ERROR: %s(): Null pointer parameters passed\n", - __func__); - LRETURN; - } - - if ((p_id_data->ui16Vid != NETINT_PCI_VENDOR_ID) || - (p_id_data->ui16Ssvid != NETINT_PCI_VENDOR_ID)) - { - LRETURN; - } - - memset(p_serial_num->ai8Sn, 0, sizeof(p_serial_num->ai8Sn)); - memcpy(p_serial_num->ai8Sn, p_id_data->ai8Sn, sizeof(p_serial_num->ai8Sn)); - - ni_log(NI_LOG_DEBUG, "F/W SerialNum: %.20s\n", p_serial_num->ai8Sn); - -END: - return; -} - /*!****************************************************************************** * \brief Retrieve a hw desc p_frame from decoder -* THIS IS TOO CHONKY, NEED A DDIRECT READ FOR DATA 3 + METADATA IF REQUIRED toDO * \param * * \return @@ -8786,18 +9430,23 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ int query_retry = 0; uint32_t ui32LBA = 0; unsigned int bytes_read_so_far = 0; + int query_type = INST_BUF_INFO_RW_READ; +#ifdef MEASURE_LATENCY + uint64_t abs_time_ns; +#endif ni_log(NI_LOG_TRACE, "%s(): enter\n", __func__); if (!p_ctx || !p_frame) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR %s(): xcoder instance id < 0, return\n", + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; @@ -8810,13 +9459,26 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ total_bytes_to_read = p_frame->data_len[3] + metadata_hdr_size; total_yuv_met_size = p_frame->data_len[0] + p_frame->data_len[1] + p_frame->data_len[2] + metadata_hdr_size; - ni_log(NI_LOG_DEBUG, "Total bytes to read %u total_yuv_met_size %u\n", - total_bytes_to_read, total_yuv_met_size); + ni_log(NI_LOG_DEBUG, + "Total bytes to read %u total_yuv_met_size %u, low_delay %u\n", + total_bytes_to_read, total_yuv_met_size, p_ctx->decoder_low_delay); + if (p_ctx->decoder_low_delay > 0 && !p_ctx->ready_to_close) + { + ni_log(NI_LOG_DEBUG, "frame_num = %" PRIu64 ", pkt_num = %" PRIu64 "\n", + p_ctx->frame_num, p_ctx->pkt_num); + if (p_ctx->frame_num >= p_ctx->pkt_num) + { + //nothing to query, leave + retval = NI_RETCODE_SUCCESS; + LRETURN; + } + query_type = INST_BUF_INFO_RW_READ_BUSY; + } for (;;) { query_retry++; - retval = ni_query_instance_buf_info(p_ctx, INST_BUF_INFO_RW_READ, - NI_DEVICE_TYPE_DECODER, &buf_info); + retval = ni_query_instance_buf_info(p_ctx, query_type, + NI_DEVICE_TYPE_DECODER, &buf_info); CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query, p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id)); @@ -8869,14 +9531,18 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ } } - if (NI_RETCODE_NVME_SC_WRITE_BUFFER_FULL == p_ctx->status && - query_retry < 1000) + query_retry < 1000 / 2) { ni_usleep(100); continue; } else { + if (p_ctx->decoder_low_delay>0) + { + ni_log(NI_LOG_ERROR, "Warning: low_delay mode non sequential input? Disabling LD\n"); + p_ctx->decoder_low_delay = -1; + } ni_log(NI_LOG_DEBUG, "Warning: dec read desc failed %d retries. rc=%d" "\n", query_retry, retval); } @@ -8885,6 +9551,19 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ } else { + // We have to ensure there are adequate number of DTS for picture + // reorder delay otherwise wait for more packets to be sent to decoder. + ni_timestamp_table_t *p_dts_queue = p_ctx->dts_queue; + if ((int)p_dts_queue->list.count < p_ctx->pic_reorder_delay + 1 && + !p_ctx->ready_to_close) + { + retval = NI_RETCODE_SUCCESS; + ni_log(NI_LOG_DEBUG, + "At least %d packets should be sent before reading the " + "first frame!\n", + p_ctx->pic_reorder_delay + 1); + LRETURN; + } // get actual YUV transfer size if this is the stream's very first read if (0 == p_ctx->active_video_width || 0 == p_ctx->active_video_height) { @@ -8905,6 +9584,7 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ p_ctx->pixel_format = data.pix_format; p_ctx->bit_depth_factor = ni_get_bitdepth_factor_from_pixfmt(p_ctx->pixel_format); //p_ctx->bit_depth_factor = data.transfer_frame_stride / data.picture_width; + p_ctx->is_first_frame = 1; ni_log(NI_LOG_DEBUG, "Info dec YUV, adjust frame size from %ux%u to " "%ux%u\n", p_frame->video_width, p_frame->video_height, @@ -9075,6 +9755,7 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ bytes_read_so_far = total_bytes_to_read; //bytes_read_so_far = p_frame->data_len[0] + p_frame->data_len[1] + p_frame->data_len[2] + p_frame->data_len[3] + metadata_hdr_size + sei_size; //since only HW desc rx_size = ni_create_frame(p_frame, bytes_read_so_far, &frame_offset, true); + p_ctx->frame_pkt_offset = frame_offset; if (rx_size > 0) { @@ -9085,7 +9766,44 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ XCODER_FRAME_OFFSET_DIFF_THRES, 0, p_ctx->buffer_pool) != NI_RETCODE_SUCCESS) { - p_frame->dts = NI_NOPTS_VALUE; + if (p_ctx->last_dts != NI_NOPTS_VALUE && !p_ctx->ready_to_close) + { + p_ctx->pic_reorder_delay++; + p_frame->dts = p_ctx->last_dts + p_ctx->last_dts_interval; + ni_log(NI_LOG_DEBUG, "Padding DTS: %" PRId64 "\n", p_frame->dts); + } else + { + p_frame->dts = NI_NOPTS_VALUE; + } + } + + if (p_ctx->is_first_frame) + { + for (i = 0; i < p_ctx->pic_reorder_delay; i++) + { + if (p_ctx->last_pts == NI_NOPTS_VALUE && + p_ctx->last_dts == NI_NOPTS_VALUE) + { + // If the p_frame->pts is unknown in the very beginning we assume + // p_frame->pts == 0 as well as DTS less than PTS by 1000 * 1/timebase + if (p_frame->pts >= p_frame->dts && + p_frame->pts - p_frame->dts < 1000) + { + break; + } + } + + if (ni_timestamp_get_with_threshold( + p_ctx->dts_queue, 0, (int64_t *)&p_frame->dts, + XCODER_FRAME_OFFSET_DIFF_THRES, + p_ctx->frame_num % 500 == 0, + p_ctx->buffer_pool) != NI_RETCODE_SUCCESS) + { + p_frame->dts = NI_NOPTS_VALUE; + } + } + // Reset for DTS padding counting + p_ctx->pic_reorder_delay = 0; } if (p_ctx->is_dec_pkt_512_aligned) @@ -9097,7 +9815,6 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ if (p_frame->dts == NI_NOPTS_VALUE) { p_frame->pts = NI_NOPTS_VALUE; - p_ctx->last_dts = p_ctx->last_pts = NI_NOPTS_VALUE; } // if not a bitstream retrieve the pts of the frame corresponding to the first YUV output else if((p_ctx->pts_offsets[0] != NI_NOPTS_VALUE) && (p_ctx->pkt_index != -1)) @@ -9136,10 +9853,8 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ if ((idx != NI_MAX_DEC_REJECT) && bFound) { p_frame->pts = p_ctx->pts_offsets[idx]; - if (idx) - p_ctx->last_pts = p_ctx->pts_offsets[idx - 1]; - else - p_ctx->last_pts = p_frame->pts; + p_frame->flags = p_ctx->flags_array[idx]; + p_ctx->last_pts = p_frame->pts; p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (first frame) idx %d last_dts %" PRId64 "" @@ -9154,6 +9869,7 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ "adjusting ts.\n", __func__, p_ctx->session_id); p_frame->pts = p_ctx->pts_offsets[idx]; + p_frame->flags = p_ctx->flags_array[idx]; p_ctx->last_pts = p_frame->pts; p_ctx->last_dts = p_frame->dts; p_ctx->session_run_state = SESSION_RUN_STATE_NORMAL; @@ -9161,8 +9877,6 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ else // use pts = 0 as offset { p_frame->pts = 0; - p_ctx->last_pts = 0; - p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (zero default) dts %" PRId64 " pts " "%" PRId64 "\n", @@ -9172,8 +9886,6 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ else { p_frame->pts = 0; - p_ctx->last_pts = 0; - p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (not bitstream) dts %" PRId64 " pts " "%" PRId64 "\n", @@ -9185,8 +9897,6 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ int64_t pts_delta = p_frame->dts - p_ctx->last_dts; p_frame->pts = p_ctx->last_pts + pts_delta; - p_ctx->last_pts = p_frame->pts; - p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (!is_first_frame idx) last_dts %" PRId64 "" " dts %" PRId64 " pts_delta %" PRId64 " last_pts " @@ -9199,118 +9909,53 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ { ni_log(NI_LOG_DEBUG, "%s: frame_offset %" PRIu64 "\n", __func__, frame_offset); - //ignore timestamps if bitstream - if (p_frame->dts == NI_NOPTS_VALUE) - { - p_frame->pts = NI_NOPTS_VALUE; - p_ctx->last_dts = p_ctx->last_pts = NI_NOPTS_VALUE; - ni_log(NI_LOG_DEBUG, - "%s: (dts NI_NOPTS_VALUE) dts " - "%" PRId64 " pts %" PRId64 "\n", - __func__, p_frame->dts, p_frame->pts); - } else - { if (p_ctx->is_first_frame) { - p_ctx->is_first_frame = 0; + p_ctx->is_first_frame = 0; } - if (frame_offset == 0) + // search for the pkt_offsets of received frame according to frame_offset. + // here we get the index(i) which promises (p_ctx->pkt_offsets_index_min[i] <= frame_offset && p_ctx->pkt_offsets_index[i] > frame_offset) + // i = -1 if not found + i = rotated_array_binary_search(p_ctx->pkt_offsets_index_min, + p_ctx->pkt_offsets_index, NI_FIFO_SZ, + frame_offset); + if (i >= 0) { - if (p_ctx->pts_offsets[0] == NI_NOPTS_VALUE) - { - p_frame->pts = NI_NOPTS_VALUE; - p_ctx->last_dts = p_ctx->last_pts = NI_NOPTS_VALUE; - ni_log(NI_LOG_DEBUG, - "%s: (first frame pts NI_NOPTS_VALUE not " - "bitstream) dts %" PRId64 " pts %" PRId64 "\n", - __func__, p_frame->dts, p_frame->pts); - } - else - { - p_frame->pts = p_ctx->pts_offsets[0]; + p_frame->pts = p_ctx->pts_offsets[i]; + p_frame->flags = p_ctx->flags_array[i]; p_ctx->last_pts = p_frame->pts; p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, - "%s: (first frame) dts %" PRId64 " pts " - "%" PRId64 "\n", - __func__, p_frame->dts, p_frame->pts); - } - - if (p_ctx->pkt_custom_sei[0]) - { - p_frame->p_custom_sei = p_ctx->pkt_custom_sei[0]; - p_frame->custom_sei_len = p_ctx->pkt_custom_sei_len[0]; - p_ctx->pkt_custom_sei[0] = NULL; - p_ctx->pkt_custom_sei_len[0] = 0; - } - } - else + "%s: (found pts) dts %" PRId64 " pts " + "%" PRId64 " frame_offset %" PRIu64 " i %d " + "pkt_offsets_index_min %" PRIu64 " " + "pkt_offsets_index %" PRIu64 "\n", + __func__, p_frame->dts, p_frame->pts, frame_offset, i, + p_ctx->pkt_offsets_index_min[i], + p_ctx->pkt_offsets_index[i]); + + p_frame->p_custom_sei_set = p_ctx->pkt_custom_sei_set[i]; + p_ctx->pkt_custom_sei_set[i] = NULL; + } else { - for (i = 0 ; i < NI_FIFO_SZ ; i++) - { - if ((frame_offset >= p_ctx->pkt_offsets_index_min[i]) - &&(frame_offset < p_ctx->pkt_offsets_index[i])) - { - if (p_ctx->pts_offsets[i] == NI_NOPTS_VALUE) - { - //bitstream case - p_frame->pts = NI_NOPTS_VALUE; - p_ctx->last_dts = p_ctx->last_pts = NI_NOPTS_VALUE; - ni_log(NI_LOG_DEBUG, - "%s: (pts NI_NOPTS_VALUE not " - "bitstream) dts %" PRId64 " pts %" PRId64 - " frame_offset %" PRIu64 " i %d " - "pkt_offsets_index_min %" PRIu64 - " pkt_offsets_index %" PRIu64 "\n", - __func__, p_frame->dts, p_frame->pts, frame_offset, i, - p_ctx->pkt_offsets_index_min[i], - p_ctx->pkt_offsets_index[i]); - } - else - { - p_frame->pts = p_ctx->pts_offsets[i]; - p_ctx->last_pts = p_frame->pts; - p_ctx->last_dts = p_frame->dts; - ni_log(NI_LOG_DEBUG, - "%s: (found pts) dts %" PRId64 " pts " - "%" PRId64 " frame_offset %" PRIu64 " i %d " - "pkt_offsets_index_min %" PRIu64 " " - "pkt_offsets_index %" PRIu64 "\n", - __func__, p_frame->dts, p_frame->pts, frame_offset, i, - p_ctx->pkt_offsets_index_min[i], - p_ctx->pkt_offsets_index[i]); - } - - if (p_ctx->pkt_custom_sei[i % NI_FIFO_SZ]) - { - p_frame->p_custom_sei = p_ctx->pkt_custom_sei[i % NI_FIFO_SZ]; - p_frame->custom_sei_len = p_ctx->pkt_custom_sei_len[i % NI_FIFO_SZ]; - p_ctx->pkt_custom_sei[i % NI_FIFO_SZ] = NULL; - p_ctx->pkt_custom_sei_len[i % NI_FIFO_SZ] = 0; - } - break; - } - if (i == (NI_FIFO_SZ-1)) - { - //backup solution pts - p_frame->pts = p_ctx->last_pts + (p_frame->dts - p_ctx->last_dts); - p_ctx->last_pts = p_frame->pts; - p_ctx->last_dts = p_frame->dts; - ni_log(NI_LOG_ERROR, "ERROR: NO pts found consider increasing NI_FIFO_SZ!\n"); - ni_log(NI_LOG_DEBUG, - "%s: (not found use default) dts %" PRId64 " pts %" PRId64 - "\n", - __func__, p_frame->dts, p_frame->pts); - } - } + //backup solution pts + p_frame->pts = p_ctx->last_pts + (p_frame->dts - p_ctx->last_dts); + ni_log(NI_LOG_ERROR, + "ERROR: NO pts found consider increasing NI_FIFO_SZ!\n"); + ni_log(NI_LOG_DEBUG, + "%s: (not found use default) dts %" PRId64 " pts %" PRId64 + "\n", + __func__, p_frame->dts, p_frame->pts); } - } } - int64_t best_effort_timestamp = guess_correct_pts(p_ctx, p_frame->pts, p_frame->dts); - p_frame->pts = best_effort_timestamp; + p_frame->pts = guess_correct_pts(p_ctx, p_frame->pts, p_frame->dts); + p_ctx->last_pts = p_frame->pts; + if (p_frame->dts != NI_NOPTS_VALUE && p_ctx->last_dts != NI_NOPTS_VALUE) + p_ctx->last_dts_interval = p_frame->dts - p_ctx->last_dts; + p_ctx->last_dts = p_frame->dts; ni_log(NI_LOG_DEBUG, "%s: (best_effort_timestamp) pts %" PRId64 "\n", - __func__, best_effort_timestamp); + __func__, p_frame->pts); p_ctx->frame_num++; } @@ -9338,6 +9983,18 @@ ni_retcode_t ni_decoder_session_read_desc(ni_session_context_t* p_ctx, ni_frame_ p_ctx->buffer_pool); } +#ifdef MEASURE_LATENCY + if ((p_frame->dts != NI_NOPTS_VALUE) && (p_ctx->frame_time_q != NULL)) + { + abs_time_ns = ni_gettime_ns(); + ni_log(NI_LOG_INFO, "DTS:%lld,DELTA:%lu,dLAT:%lu;\n", p_frame->dts, + abs_time_ns - p_ctx->prev_read_frame_time, + ni_lat_meas_q_check_latency((ni_lat_meas_q_t *)p_ctx->frame_time_q, + abs_time_ns, p_frame->dts)); + p_ctx->prev_read_frame_time = abs_time_ns; + } +#endif + END: if (NI_RETCODE_SUCCESS != retval) @@ -9387,13 +10044,14 @@ int ni_hwdownload_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame, if ((!p_ctx) || (!p_frame)) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR %s(): xcoder instance id < 0, return\n", + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; @@ -9489,8 +10147,12 @@ int ni_hwdownload_session_read(ni_session_context_t* p_ctx, ni_frame_t* p_frame, if (p_ctx->is_auto_dl) rx_size = (int)bytes_read_so_far; else + { rx_size = ni_create_frame(p_frame, bytes_read_so_far, &frame_offset, false); + p_ctx->frame_pkt_offset = frame_offset; + } + #ifdef XCODER_DUMP_ENABLED fwrite(p_frame->data[0], rx_size, 1, p_ctx->p_dump[1]); @@ -9579,7 +10241,7 @@ ni_retcode_t ni_config_instance_set_uploader_params(ni_session_context_t *p_ctx, if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): NULL pointer p_config passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; @@ -9587,7 +10249,8 @@ ni_retcode_t ni_config_instance_set_uploader_params(ni_session_context_t *p_ctx, if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -9596,7 +10259,8 @@ ni_retcode_t ni_config_instance_set_uploader_params(ni_session_context_t *p_ctx, if (ni_posix_memalign(&p_uploader_config, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate uplConf buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -9662,7 +10326,7 @@ ni_retcode_t ni_config_instance_set_decoder_params(ni_session_context_t* p_ctx, if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): NULL pointer p_config passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; @@ -9670,7 +10334,8 @@ ni_retcode_t ni_config_instance_set_decoder_params(ni_session_context_t* p_ctx, if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -9678,7 +10343,8 @@ ni_retcode_t ni_config_instance_set_decoder_params(ni_session_context_t* p_ctx, buffer_size = ((buffer_size + (NI_MEM_PAGE_ALIGNMENT - 1)) / NI_MEM_PAGE_ALIGNMENT) * NI_MEM_PAGE_ALIGNMENT; if (ni_posix_memalign(&p_decoder_config, sysconf(_SC_PAGESIZE), buffer_size)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate encConf buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate p_decoder_config buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -9769,6 +10435,7 @@ ni_retcode_t ni_config_instance_set_decoder_params(ni_session_context_t* p_ctx, * NI_RETCODE_ERROR_INVALID_SESSION * NI_RETCODE_ERROR_MEM_ALOC * NI_RETCODE_ERROR_NVME_CMD_FAILED + * NI_RETCODE_FAILURE *******************************************************************************/ ni_retcode_t ni_scaler_session_read_hwdesc( ni_session_context_t *p_ctx, @@ -9777,34 +10444,66 @@ ni_retcode_t ni_scaler_session_read_hwdesc( ni_retcode_t retval; ni_instance_buf_info_t sInstanceBuf = {0}; niFrameSurface1_t *pFrameSurface; + int query_retry = 0; if (!p_ctx) { + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } if (p_ctx->session_id == NI_INVALID_SESSION_ID) { - ni_log(NI_LOG_ERROR, "ERROR %s: no session\n", __func__); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); return NI_RETCODE_ERROR_INVALID_SESSION; } - retval = ni_query_instance_buf_info(p_ctx, INST_BUF_INFO_RW_UPLOAD, - NI_DEVICE_TYPE_SCALER, &sInstanceBuf); + for (;;) + { + query_retry++; - CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query, - p_ctx->device_type, p_ctx->hw_id, - &(p_ctx->session_id)); + retval = ni_query_instance_buf_info(p_ctx, INST_BUF_INFO_RW_UPLOAD, + NI_DEVICE_TYPE_SCALER, &sInstanceBuf); - pFrameSurface = (niFrameSurface1_t *) p_frame->p_data[3]; - pFrameSurface->ui16FrameIdx = sInstanceBuf.hw_inst_ind.frame_index; - pFrameSurface->ui16session_ID = p_ctx->session_id; - pFrameSurface->device_handle = - (int32_t)((int64_t)p_ctx->blk_io_handle & 0xFFFFFFFF); - pFrameSurface->src_cpu = (uint8_t) NI_DEVICE_TYPE_SCALER; - pFrameSurface->output_idx = 0; + CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_query, + p_ctx->device_type, p_ctx->hw_id, + &(p_ctx->session_id)); + + if (retval != NI_RETCODE_SUCCESS) + { + if (query_retry >= 1000) + { + ni_log(NI_LOG_DEBUG, "Warning hwdesc read fail rc %d\n", retval); + LRETURN; + } + } + else + { + pFrameSurface = (niFrameSurface1_t *) p_frame->p_data[3]; + pFrameSurface->ui16FrameIdx = sInstanceBuf.hw_inst_ind.frame_index; + pFrameSurface->ui16session_ID = p_ctx->session_id; + pFrameSurface->device_handle = + (int32_t)((int64_t)p_ctx->blk_io_handle & 0xFFFFFFFF); + pFrameSurface->src_cpu = (uint8_t) NI_DEVICE_TYPE_SCALER; + pFrameSurface->output_idx = 0; + + /* A frame index of zero is invalid, the memory acquisition failed */ + if (pFrameSurface->ui16FrameIdx == 0) + { + if (query_retry >= 1000) + { + ni_log(NI_LOG_ERROR, "Warning: 2D could not acquire frame\n"); + retval = NI_RETCODE_FAILURE; + LRETURN; + } + continue; + } + LRETURN; + } + } -// cppcheck-suppress unusedLabel END: if (NI_RETCODE_SUCCESS != retval) @@ -9879,13 +10578,14 @@ int ni_get_planar_from_pixfmt(int pix_fmt) /*!***************************************************************************** * \brief Get an address offset from a hw descriptor * + * \param[in] p_ctx ni_session_context_t to be referenced * \param[in] hwdesc Pointer to caller allocated niFrameSurface1_t * \param[out] p_offset Value of offset * * \return On success NI_RETCODE_SUCCESS * On failure NI_RETCODE_INVALID_PARAM ******************************************************************************/ -ni_retcode_t ni_get_memory_offset(const niFrameSurface1_t *hwdesc, +ni_retcode_t ni_get_memory_offset(ni_session_context_t *p_ctx, const niFrameSurface1_t *hwdesc, uint32_t *p_offset) { if (!hwdesc) @@ -9894,15 +10594,15 @@ ni_retcode_t ni_get_memory_offset(const niFrameSurface1_t *hwdesc, return NI_RETCODE_INVALID_PARAM; } - if (hwdesc->ui16FrameIdx <= NI_MIN_HWDESC_P2P_BUF_ID || - hwdesc->ui16FrameIdx >= NI_MAX_HWDESC_P2P_BUF_ID) + if (hwdesc->ui16FrameIdx <= NI_GET_MIN_HWDESC_P2P_BUF_ID(p_ctx->ddr_config) || + hwdesc->ui16FrameIdx > NI_GET_MAX_HWDESC_P2P_BUF_ID(p_ctx->ddr_config)) { ni_log(NI_LOG_ERROR, "ERROR: %s() pass invalid data\n", __func__); return NI_RETCODE_INVALID_PARAM; } - *p_offset = (hwdesc->ui16FrameIdx - NI_MIN_HWDESC_P2P_BUF_ID) * - NI_HWDESC_MEMBIN_SIZE; + *p_offset = (hwdesc->ui16FrameIdx - NI_GET_MIN_HWDESC_P2P_BUF_ID(p_ctx->ddr_config)) * + NI_HWDESC_UNIFIED_MEMBIN_SIZE; return NI_RETCODE_SUCCESS; } @@ -9928,7 +10628,7 @@ ni_retcode_t ni_config_instance_network_binary(ni_session_context_t *p_ctx, if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): NULL pointer p_config passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; @@ -9936,7 +10636,8 @@ ni_retcode_t ni_config_instance_network_binary(ni_session_context_t *p_ctx, if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -10139,14 +10840,16 @@ ni_retcode_t ni_ai_session_write(ni_session_context_t *p_ctx, if (p_frame->data_len[0] == 0) { - ni_log(NI_LOG_ERROR, "ERROR: invalid data length\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() invalid data length\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -10243,14 +10946,16 @@ ni_retcode_t ni_ai_session_read(ni_session_context_t *p_ctx, if (!p_ctx || !p_packet || !p_packet->p_data) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_DEBUG, "xcoder instance id == 0, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -10318,6 +11023,7 @@ ni_retcode_t ni_config_read_inout_layers(ni_session_context_t *p_ctx, ni_network_data_t *p_network) { void *p_buffer = NULL; + void *p_info = NULL; ni_retcode_t retval = NI_RETCODE_SUCCESS; uint32_t ui32LBA = 0; uint32_t dataLen; @@ -10332,7 +11038,8 @@ ni_retcode_t ni_config_read_inout_layers(ni_session_context_t *p_ctx, if (!p_ctx || !p_network) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; } @@ -10342,7 +11049,8 @@ ni_retcode_t ni_config_read_inout_layers(ni_session_context_t *p_ctx, ~(NI_MEM_PAGE_ALIGNMENT - 1); if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -10386,24 +11094,25 @@ ni_retcode_t ni_config_read_inout_layers(ni_session_context_t *p_ctx, /* query the real network layer data */ dataLen = (sizeof(ni_network_layer_info_t) + (NI_MEM_PAGE_ALIGNMENT - 1)) & ~(NI_MEM_PAGE_ALIGNMENT - 1); - if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), dataLen)) + if (ni_posix_memalign(&p_info, sysconf(_SC_PAGESIZE), dataLen)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate info buffer\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } - memset(p_buffer, 0, dataLen); + memset(p_info, 0, dataLen); ui32LBA = QUERY_INSTANCE_NL_R(p_ctx->session_id, NI_DEVICE_TYPE_AI); if (ni_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, - p_buffer, dataLen, ui32LBA) < 0) + p_info, dataLen, ui32LBA) < 0) { ni_log(NI_LOG_ERROR, "%s(): NVME command Failed\n", __func__); retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; LRETURN; } - p_network->linfo = *((ni_network_layer_info_t *)p_buffer); + p_network->linfo = *((ni_network_layer_info_t *)p_info); for (l = 0, p_network->input_num = 0, buffer_size = 0; l < NI_MAX_NETWORK_INPUT_NUM; l++) @@ -10456,6 +11165,7 @@ ni_retcode_t ni_config_read_inout_layers(ni_session_context_t *p_ctx, END: ni_aligned_free(p_buffer); + ni_aligned_free(p_info); ni_log(NI_LOG_TRACE, "%s(): exit\n", __func__); return retval; } @@ -10471,7 +11181,7 @@ ni_retcode_t ni_ai_session_open(ni_session_context_t *p_ctx) if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: %s(): NULL pointer p_config passed\n", + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", __func__); retval = NI_RETCODE_INVALID_PARAM; LRETURN; @@ -10505,9 +11215,8 @@ ni_retcode_t ni_ai_session_open(ni_session_context_t *p_ctx) if (ni_posix_memalign(&p_ctx->p_all_zero_buf, sysconf(_SC_PAGESIZE), NI_DATA_BUFFER_LEN)) { - ni_log(NI_LOG_ERROR, "ERROR %d: ni_ai_session_open() alloc all zero " - "buffer failed\n", - NI_ERRNO); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() alloc all zero buffer failed\n", + NI_ERRNO, __func__); retval = NI_RETCODE_ERROR_MEM_ALOC; LRETURN; } @@ -10536,6 +11245,11 @@ ni_retcode_t ni_ai_session_open(ni_session_context_t *p_ctx) retval = ni_nvme_send_read_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, p_buffer, NI_DATA_BUFFER_LEN, ui32LBA); + if (retval != NI_RETCODE_SUCCESS) + { + ni_log(NI_LOG_ERROR, "ERROR ni_nvme_send_read_cmd\n"); + LRETURN; + } //Open will return a session status structure with a valid session id if it worked. //Otherwise the invalid session id set before the open command will stay if ((uint16_t)NI_INVALID_SESSION_ID == @@ -10552,13 +11266,42 @@ ni_retcode_t ni_ai_session_open(ni_session_context_t *p_ctx) } p_ctx->session_id = ni_ntohs(((ni_session_stats_t *)p_buffer)->ui16SessionId); - ni_log(NI_LOG_DEBUG, "Ai open session ID:0x%x\n", p_ctx->session_id); + p_ctx->session_timestamp = + ni_htonll(((ni_session_stats_t *)p_buffer)->ui64Session_timestamp); + ni_log(NI_LOG_DEBUG, "Ai open session ID:0x%x,timestamp:%" PRIu64 "\n", + p_ctx->session_id, p_ctx->session_timestamp); + ni_log(NI_LOG_DEBUG, "Open session completed\n"); ni_log(NI_LOG_DEBUG, "%s(): p_ctx->device_handle=%" PRIx64 ", p_ctx->hw_id=%d, p_ctx->session_id=%d\n", __func__, (int64_t)p_ctx->device_handle, p_ctx->hw_id, p_ctx->session_id); + + //Send keep alive timeout Info + uint64_t keep_alive_timeout = + p_ctx->keep_alive_timeout * 1000000; //send us to FW + memset(p_buffer, 0, NI_DATA_BUFFER_LEN); + memcpy(p_buffer, &keep_alive_timeout, sizeof(keep_alive_timeout)); + ni_log(NI_LOG_DEBUG, "%s keep_alive_timeout %" PRIx64 "\n", __func__, + keep_alive_timeout); + ui32LBA = CONFIG_SESSION_KeepAliveTimeout_W(p_ctx->session_id); + retval = + ni_nvme_send_write_cmd(p_ctx->blk_io_handle, p_ctx->event_handle, + p_buffer, NI_DATA_BUFFER_LEN, ui32LBA); + CHECK_ERR_RC(p_ctx, retval, nvme_admin_cmd_xcoder_config, + p_ctx->device_type, p_ctx->hw_id, &(p_ctx->session_id)); + CHECK_VPU_RECOVERY(retval); + + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_ERROR, + "ERROR %s(): nvme write keep_alive_timeout command " + "failed, blk_io_handle: %" PRIx64 ", hw_id, %d\n", + __func__, (int64_t)p_ctx->blk_io_handle, p_ctx->hw_id); + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + LRETURN; + } } // init for frame pts calculation @@ -10588,14 +11331,15 @@ ni_retcode_t ni_ai_session_close(ni_session_context_t *p_ctx, int eos_recieved) if (!p_ctx) { - ni_log(NI_LOG_ERROR, "ERROR: passed parameters are null!, return\n"); - ni_log(NI_LOG_TRACE, "%s(): exit\n", __func__); + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } if (NI_INVALID_SESSION_ID == p_ctx->session_id) { - ni_log(NI_LOG_ERROR, "ERROR: Invalid session ID, return\n"); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); retval = NI_RETCODE_ERROR_INVALID_SESSION; LRETURN; } @@ -10697,13 +11441,15 @@ ni_retcode_t ni_ai_alloc_hwframe(ni_session_context_t *p_ctx, int frame_index) if (!p_ctx) { + ni_log(NI_LOG_ERROR, "ERROR: %s() passed parameters are null!, return\n", + __func__); return NI_RETCODE_INVALID_PARAM; } if (p_ctx->session_id == NI_INVALID_SESSION_ID) { - ni_log(NI_LOG_ERROR, "ERROR %s(): Cannot allocate leftover buffer.\n", - __func__); + ni_log(NI_LOG_ERROR, "ERROR %s(): Invalid session ID, return.\n", + __func__); return NI_RETCODE_ERROR_INVALID_SESSION; } @@ -10712,7 +11458,8 @@ ni_retcode_t ni_ai_alloc_hwframe(ni_session_context_t *p_ctx, int frame_index) if (ni_posix_memalign((void **)&p_data, sysconf(_SC_PAGESIZE), dataLen)) { - ni_log(NI_LOG_ERROR, "ERROR: Cannot allocate buffer.\n"); + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer\n", + NI_ERRNO, __func__); return NI_RETCODE_ERROR_MEM_ALOC; } @@ -10742,3 +11489,63 @@ ni_retcode_t ni_ai_alloc_hwframe(ni_session_context_t *p_ctx, int frame_index) ni_aligned_free(p_data); return retval; } + +/*!***************************************************************************** + * \brief Get DDR configuration of Quadra device + * + * \param[in/out] p_ctx pointer to a session context with valid file handle + * + * \return On success NI_RETCODE_SUCCESS + * On failure NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_MEM_ALOC + * NI_RETCODE_ERROR_NVME_CMD_FAILED + ******************************************************************************/ +ni_retcode_t ni_device_get_ddr_configuration(ni_session_context_t *p_ctx) +{ + void *p_buffer = NULL; + ni_nvme_identity_t *p_id_data; + ni_retcode_t retval = NI_RETCODE_SUCCESS; + ni_event_handle_t event_handle = NI_INVALID_EVENT_HANDLE; + uint32_t ui32LBA = IDENTIFY_DEVICE_R; + ni_device_handle_t device_handle = p_ctx->blk_io_handle; + + ni_log(NI_LOG_TRACE, "%s(): enter\n", __func__); + + if (NI_INVALID_DEVICE_HANDLE == device_handle) + { + ni_log(NI_LOG_ERROR, "ERROR: %s(): invalid passed parameters\n", + __func__); + retval = NI_RETCODE_INVALID_PARAM; + LRETURN; + } + + if (ni_posix_memalign(&p_buffer, sysconf(_SC_PAGESIZE), + NI_NVME_IDENTITY_CMD_DATA_SZ)) + { + ni_log(NI_LOG_ERROR, "ERROR %d: %s() Cannot allocate buffer.\n", + NI_ERRNO, __func__); + retval = NI_RETCODE_ERROR_MEM_ALOC; + LRETURN; + } + + memset(p_buffer, 0, NI_NVME_IDENTITY_CMD_DATA_SZ); + + if (ni_nvme_send_read_cmd(device_handle, event_handle, p_buffer, + NI_NVME_IDENTITY_CMD_DATA_SZ, ui32LBA) < 0) + { + retval = NI_RETCODE_ERROR_NVME_CMD_FAILED; + LRETURN; + } + + p_id_data = (ni_nvme_identity_t *) p_buffer; + p_ctx->ddr_config = (p_id_data->memory_cfg == NI_QUADRA_MEMORY_CONFIG_SR) + ? 1 : 2; + + ni_log(NI_LOG_DEBUG, "Memory configuration %d\n",p_ctx->ddr_config); +END: + + ni_aligned_free(p_buffer); + ni_log(NI_LOG_TRACE, "%s(): retval: %d\n", __func__, retval); + + return retval; +} diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api_priv.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api_priv.h index c56eaa03..a3549fa0 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api_priv.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_api_priv.h @@ -40,6 +40,7 @@ extern "C" #endif #include "ni_defs.h" +#include "ni_rsrc_api.h" typedef enum { @@ -219,7 +220,7 @@ typedef struct _ni_metadata_enc_frame //uint32_t reserved; } ni_metadata_enc_frame_t; -typedef struct _ni_metadata_enc_bstream +typedef struct _ni_metadata_enc_bstream_rev61 { uint32_t bs_frame_size; uint32_t frame_type; @@ -228,7 +229,22 @@ typedef struct _ni_metadata_enc_bstream uint32_t avg_frame_qp; uint32_t recycle_index; uint32_t av1_show_frame; - //uint32_t reserved[1]; +} ni_metadata_enc_bstream_rev61_t; // Revision 61 or lower + +typedef struct _ni_metadata_enc_bstream +{ + uint32_t metadata_size; + uint32_t frame_type; + uint64_t frame_tstamp; + uint32_t frame_cycle; + uint32_t avg_frame_qp; + uint32_t recycle_index; + uint32_t av1_show_frame; + //Added for Revision 61 + uint32_t ssimY; + uint32_t ssimU; + uint32_t ssimV; + uint32_t reserved; } ni_metadata_enc_bstream_t; /*!****** encoder paramters *********************************************/ @@ -358,7 +374,7 @@ typedef struct _ni_t408_config_t uint32_t useLongTerm; /*!*< It enables long-term reference function. */ - // newly added for T408_520 + // newly added for T408 uint32_t monochromeEnable; /*!*< It enables monochrome encoding mode. */ uint32_t strongIntraSmoothEnable; /*!*< It enables strong intra smoothing. */ @@ -502,8 +518,10 @@ typedef struct _ni_encoder_config_t // <--- not to be exposed to customers uint8_t ui8LowDelay; uint8_t ui8setLongTermCount; /* sets long-term reference frames count */ - uint8_t ui8Reserved[3]; /**< reserved for future expansion **/ + uint16_t ui16maxFrameSize; + uint8_t ui8enableSSIM; uint8_t ui8VuiRbsp[NI_MAX_VUI_SIZE]; /**< VUI raw byte sequence **/ + uint8_t ui8fixedframerate; } ni_encoder_config_t; typedef struct _ni_uploader_config_t @@ -516,6 +534,19 @@ typedef struct _ni_uploader_config_t uint8_t ui8rsvd[1]; } ni_uploader_config_t; +// struct describing resolution change. +typedef struct _ni_resolution +{ + // width + int32_t width; + + // height + int32_t height; + + // bit depth factor + int32_t bit_depth_factor; +} ni_resolution_t; + #define NI_MINIMUM_CROPPED_LENGTH 48 typedef enum { CROP_DISABLED = 0, @@ -552,8 +583,8 @@ typedef struct _ni_decoder_config_t uint8_t ui8HWFrame; uint8_t ui8UduSeiEnabled; // ui8OutputFormat; uint16_t ui16MaxSeiDataSize; - uint16_t fps_number; - uint16_t fps_denominator; + uint32_t fps_number; + uint32_t fps_denominator; uint8_t ui8MCMode; uint8_t ui8rsrv[3]; uint32_t ui32MaxPktSize; @@ -574,7 +605,8 @@ typedef struct _ni_network_buffer typedef struct _ni_scaler_config { uint8_t filterblit; - uint8_t ui8Reserved[3]; + uint8_t numInputs; + uint8_t ui8Reserved[2]; uint32_t ui32Reserved[3]; } ni_scaler_config_t; @@ -600,7 +632,10 @@ typedef enum #define NI_SESSION_CLOSE_RETRY_INTERVAL_US 500000 /* This value must agree with the membin size in Quadra firmware */ -#define NI_HWDESC_MEMBIN_SIZE 0x30E000 +#define NI_HWDESC_UNIFIED_MEMBIN_SIZE 0x187000 + +#define NI_QUADRA_MEMORY_CONFIG_DR 0 +#define NI_QUADRA_MEMORY_CONFIG_SR 1 int ni_create_frame(ni_frame_t* p_frame, uint32_t read_length, uint64_t* frame_offset, bool is_hw_frame); @@ -632,7 +667,6 @@ void ni_params_print(ni_xcoder_params_t *const p_encoder_params); int32_t ni_get_frame_index(uint32_t* value); void ni_populate_device_capability_struct(ni_device_capability_t* p_cap, void * p_data); -void ni_populate_serial_number(ni_serial_num* p_serial_num, void * p_data); int ni_xcoder_session_query(ni_session_context_t *p_ctx, ni_device_type_t device_type); @@ -650,6 +684,7 @@ ni_retcode_t ni_encoder_session_close(ni_session_context_t *p_ctx, int eos_recie ni_retcode_t ni_encoder_session_flush(ni_session_context_t *p_ctx); int ni_encoder_session_write(ni_session_context_t *p_ctx, ni_frame_t *p_frame); int ni_encoder_session_read(ni_session_context_t *p_ctx, ni_packet_t *p_packet); +ni_retcode_t ni_encoder_session_sequence_change(ni_session_context_t *p_ctx, ni_resolution_t *p_resoluion); //int ni_encoder_session_reconfig(ni_session_context_t *p_ctx, ni_session_config_t *p_config, ni_param_change_flags_t change_flags); ni_retcode_t ni_query_general_status(ni_session_context_t* p_ctx, ni_device_type_t device_type, ni_instance_mgr_general_status_t* p_gen_status); @@ -666,6 +701,7 @@ ni_retcode_t ni_config_instance_set_encoder_params(ni_session_context_t* p_ctx); ni_retcode_t ni_config_instance_update_encoder_params(ni_session_context_t* p_ctx, ni_param_change_flags_t change_flags); ni_retcode_t ni_config_instance_set_encoder_frame_params(ni_session_context_t* p_ctx, ni_encoder_frame_params_t* p_params); ni_retcode_t ni_config_instance_set_write_len(ni_session_context_t* p_ctx, ni_device_type_t device_type, uint32_t len); +ni_retcode_t ni_config_instance_set_sequence_change(ni_session_context_t* p_ctx, ni_device_type_t device_type, ni_resolution_t *p_resolution); void ni_encoder_set_vui(uint8_t* vui, ni_encoder_config_t *p_cfg); void *ni_session_keep_alive_thread(void *arguments); ni_retcode_t ni_send_session_keep_alive(uint32_t session_id, ni_device_handle_t device_handle, ni_event_handle_t event_handle, void *p_data); @@ -815,6 +851,24 @@ ni_retcode_t ni_scaler_alloc_frame(ni_session_context_t* p_ctx, int width, ni_retcode_t ni_scaler_config_frame(ni_session_context_t *p_ctx, ni_frame_config_t *p_cfg); +/*!****************************************************************************** + * \brief config multi frames in the scaler + * + * \param[in] p_ctx pointer to session context + * \param[in] p_cfg_in pointer to input frame config array + * \param[in] numInCfgs number of input frame configs in p_cfg_in array + * \param[in] p_cfg_out pointer to output frame config + * + * \return NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_INVALID_SESSION + * NI_RETCODE_ERROR_NVME_CMD_FAILED + * NI_RETCODE_ERROR_MEM_ALOC + *******************************************************************************/ +ni_retcode_t ni_scaler_multi_config_frame(ni_session_context_t *p_ctx, + ni_frame_config_t p_cfg_in[], + int numInCfgs, + ni_frame_config_t *p_cfg_out); + /*!****************************************************************************** * \brief Open a xcoder scaler instance * @@ -864,6 +918,7 @@ ni_retcode_t ni_config_instance_set_uploader_params(ni_session_context_t *p_ctx, * NI_RETCODE_ERROR_INVALID_SESSION * NI_RETCODE_ERROR_MEM_ALOC * NI_RETCODE_ERROR_NVME_CMD_FAILED + * NI_RETCODE_FAILURE *******************************************************************************/ ni_retcode_t ni_scaler_session_read_hwdesc( ni_session_context_t *p_ctx, @@ -891,16 +946,31 @@ int ni_get_planar_from_pixfmt(int pix_fmt); /*!***************************************************************************** * \brief Get an address offset from a hw descriptor * + * \param[in] p_ctx ni_session_context_t to be referenced * \param[in] hwdesc Pointer to caller allocated niFrameSurface1_t * \param[out] p_offset Value of offset * * \return On success NI_RETCODE_SUCCESS * On failure NI_RETCODE_INVALID_PARAM ******************************************************************************/ -ni_retcode_t ni_get_memory_offset(const niFrameSurface1_t *hwdesc, +ni_retcode_t ni_get_memory_offset(ni_session_context_t * p_ctx, const niFrameSurface1_t *hwdesc, uint32_t *p_offset); + #endif +/*!***************************************************************************** + * \brief Get DDR configuration of Quadra device + * + * \param[in/out] p_ctx pointer to a session context with valid file handle + * + * \return On success NI_RETCODE_SUCCESS + * On failure NI_RETCODE_INVALID_PARAM + * NI_RETCODE_ERROR_MEM_ALOC + * NI_RETCODE_ERROR_NVME_CMD_FAILED + ******************************************************************************/ +ni_retcode_t ni_device_get_ddr_configuration(ni_session_context_t *p_ctx); + + #define NI_AI_HW_ALIGN_SIZE 64 ni_retcode_t ni_ai_session_open(ni_session_context_t *p_ctx); diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_test.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_test.c index fbe928b5..2867bda9 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_test.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_test.c @@ -31,7 +31,7 @@ #ifdef _WIN32 #include #include "ni_getopt.h" -#elif __linux__ +#elif __linux__ || __APPLE__ #define _POSIX_C_SOURCE 200809L #include #include @@ -40,6 +40,7 @@ #include #include #include +#include #endif #include @@ -49,6 +50,7 @@ #include "ni_util.h" #include "ni_device_test.h" #include "ni_bitstream.h" +#include "ni_p2p_ioctl.h" typedef struct _ni_err_rc_txt_entry { @@ -56,6 +58,23 @@ typedef struct _ni_err_rc_txt_entry const char *txt; } ni_err_rc_txt_entry_t; +typedef struct _ni_filter_params_t +{ + bool p2p; + int scale_width; + int scale_height; + int format; +} ni_filter_params_t; + +typedef struct _ni_disp_buffer +{ + int fd; + int bar; + uint8_t *data; + unsigned long len; + volatile uint8_t *mmap_data; +} disp_buffer_t; + static const ni_err_rc_txt_entry_t ni_err_rc_description[] = { NI_RETCODE_SUCCESS, "SUCCESS", @@ -292,7 +311,7 @@ typedef struct dec_send_param int print_time; unsigned long *p_total_bytes_sent; device_state_t *p_xcodeState; - ni_h264_sps_t *p_SPS; + void *p_stream_info; } dec_send_param_t; typedef struct dec_recv_param @@ -315,6 +334,10 @@ typedef struct enc_send_param int input_video_width; int input_video_height; int pfs; + int input_arg_width[MAX_INPUT_FILES]; + int input_arg_height[MAX_INPUT_FILES]; + int input_bit_depth[MAX_INPUT_FILES]; + int input_arg_pfs[MAX_INPUT_FILES]; unsigned long *p_total_bytes_sent; device_state_t *p_xcodeState; int mode; @@ -322,6 +345,7 @@ typedef struct enc_send_param uint32_t dec_codec_format; // used in transcode mode int *p_input_exhausted; // used in upload mode niFrameSurface1_t *p_hwframe_pool_tracker; // used in upload mode + int input_total; } enc_send_param_t; typedef struct enc_recv_param @@ -335,6 +359,7 @@ typedef struct enc_recv_param device_state_t *p_xcodeState; int mode; niFrameSurface1_t *p_hwframe_pool_tracker; // used in upload mode + ni_session_data_io_t *p_buffered_frame; } enc_recv_param_t; typedef struct uploader_param @@ -352,6 +377,7 @@ typedef struct uploader_param volatile int send_fin_flag = 0, receive_fin_flag = 0, err_flag = 0; volatile unsigned int number_of_frames = 0; +volatile unsigned int number_of_frames_in_file = 0; volatile unsigned int number_of_packets = 0; struct timeval start_time, previous_time, current_time; time_t start_timestamp = 0, privious_timestamp = 0, current_timestamp = 0; @@ -496,6 +522,10 @@ uint32_t read_next_chunk_from_file(int pfs, uint8_t *p_dst, uint32_t to_read) { if (g_repeat > 1) { + if (number_of_frames_in_file == 0) + { //run once to know total frame count of input + number_of_frames_in_file = number_of_frames; + } data_left_size = total_file_size; g_repeat--; ni_log(NI_LOG_DEBUG, "input processed %d left\n", g_repeat); @@ -1373,211 +1403,2069 @@ int parse_h264_slice_header(uint8_t *buf, int size_bytes, ni_h264_sps_t *sps, return 0; } -/*!***************************************************************************** - * \brief Send decoder input data - * - * \param - * - * \return - ******************************************************************************/ -ni_retcode_t decoder_send_data(ni_session_context_t *p_dec_ctx, - ni_session_data_io_t *p_in_data, int sos_flag, - int input_video_width, int input_video_height, - int pkt_size, unsigned int file_size, - unsigned long *total_bytes_sent, int print_time, - device_state_t *p_device_state, - ni_h264_sps_t *sps) +typedef enum _ni_hevc_nalu_type { - static uint8_t tmp_buf[NI_MAX_TX_SZ] = {0}; - uint8_t *tmp_buf_ptr = tmp_buf; - int packet_size = pkt_size; - // int chunk_size = 0; - uint32_t frame_pkt_size = 0, nal_size; - int nal_type = -1; - int tx_size = 0; - uint32_t send_size = 0; - int new_packet = 0; - int saved_prev_size = 0; - int32_t frame_num = -1, curr_frame_num; - unsigned int first_mb_in_slice = 0; - ni_packet_t *p_in_pkt = &(p_in_data->data.packet); - ni_retcode_t retval = NI_RETCODE_SUCCESS; + HEVC_NAL_TRAIL_N = 0, + HEVC_NAL_TRAIL_R = 1, + HEVC_NAL_TSA_N = 2, + HEVC_NAL_TSA_R = 3, + HEVC_NAL_STSA_N = 4, + HEVC_NAL_STSA_R = 5, + HEVC_NAL_RADL_N = 6, + HEVC_NAL_RADL_R = 7, + HEVC_NAL_RASL_N = 8, + HEVC_NAL_RASL_R = 9, + HEVC_NAL_IDR_W_RADL = 19, + HEVC_NAL_IDR_N_LP = 20, + HEVC_NAL_CRA_NUT = 21, + HEVC_NAL_VPS = 32, + HEVC_NAL_SPS = 33, + HEVC_NAL_PPS = 34, + HEVC_NAL_AUD = 35, + HEVC_NAL_EOS_NUT = 36, + HEVC_NAL_EOB_NUT = 37, + HEVC_NAL_FD_NUT = 38, + HEVC_NAL_SEI_PREFIX = 39, + HEVC_NAL_SEI_SUFFIX = 40, +} ni_hevc_nalu_type; + +static const ni_rational_t vui_sar[] = { + {0, 1}, {1, 1}, {12, 11}, {10, 11}, {16, 11}, {40, 33}, + {24, 11}, {20, 11}, {32, 11}, {80, 33}, {18, 11}, {15, 11}, + {64, 33}, {160, 99}, {4, 3}, {3, 2}, {2, 1}, +}; - ni_log(NI_LOG_DEBUG, "===> decoder_send_data <===\n"); +static const uint8_t hevc_sub_width_c[] = {1, 2, 2, 1}; - if (p_device_state->dec_eos_sent) - { - ni_log(NI_LOG_DEBUG, "decoder_send_data: ALL data (incl. eos) sent " - "already!\n"); - LRETURN; - } +static const uint8_t hevc_sub_height_c[] = {1, 2, 1, 1}; - // TBD Demo: decoder flush at 200th packet -#if 0 - if (200 == p_dec_ctx->pkt_num) - { - if (NI_RETCODE_SUCCESS != ni_device_dec_session_flush(p_dec_ctx)) - { - ni_log(NI_LOG_ERROR, "decoder_send_data: mid-flush failed!\n"); - exit(-1); - } - } -#endif +const uint8_t hevc_diag_scan4x4_x[16] = { + 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 1, 2, 3, 2, 3, 3, +}; - if (0 == p_in_pkt->data_len) - { - memset(p_in_pkt, 0, sizeof(ni_packet_t)); +const uint8_t hevc_diag_scan4x4_y[16] = { + 0, 1, 0, 2, 1, 0, 3, 2, 1, 0, 3, 2, 1, 3, 2, 3, +}; - if (NI_CODEC_FORMAT_H264 == p_dec_ctx->codec_format) - { - // send whole encoded packet which ends with a slice NAL - while ((nal_size = find_h264_next_nalu(tmp_buf_ptr, &nal_type)) > 0) - { - frame_pkt_size += nal_size; - tmp_buf_ptr += nal_size; - ni_log(NI_LOG_DEBUG, "%s nal %d nal_size %d\n", __func__, - nal_type, nal_size); +const uint8_t hevc_diag_scan8x8_x[64] = { + 0, 0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, + 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7, 2, + 3, 4, 5, 6, 7, 3, 4, 5, 6, 7, 4, 5, 6, 7, 5, 6, 7, 6, 7, 7, +}; - // save parsed out sps/pps as stream headers in the decode session - if (H264_NAL_PPS == nal_type) - { - if (NI_RETCODE_SUCCESS != - ni_device_dec_session_save_hdrs(p_dec_ctx, tmp_buf, - frame_pkt_size)) - { - ni_log(NI_LOG_ERROR, "decoder_send_data: save_hdr failed!\n"); - } - } +const uint8_t hevc_diag_scan8x8_y[64] = { + 0, 1, 0, 2, 1, 0, 3, 2, 1, 0, 4, 3, 2, 1, 0, 5, 4, 3, 2, 1, 0, 6, + 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 7, + 6, 5, 4, 3, 2, 7, 6, 5, 4, 3, 7, 6, 5, 4, 7, 6, 5, 7, 6, 7, +}; - if (H264_NAL_SLICE == nal_type || - H264_NAL_IDR_SLICE == nal_type) - { - if (!parse_h264_slice_header(tmp_buf_ptr - nal_size, - nal_size, sps, &curr_frame_num, - &first_mb_in_slice)) - { - if (-1 == frame_num) - { - // first slice, continue to check - frame_num = curr_frame_num; - } else if (curr_frame_num != frame_num || - 0 == first_mb_in_slice) - { - // this slice has diff. frame_num or first_mb_in_slice addr is - // 0: not the same frame and return - rewind_data_buf_pos_by(nal_size); - frame_pkt_size -= nal_size; - break; - } - // this slice is in the same frame, so continue to check and see - // if there is more - } else - { - ni_log(NI_LOG_ERROR, - "decoder_send_data: parse_slice_header error " - "NAL type %d size %u, continue\n", - nal_type, nal_size); - } - } else if (-1 != frame_num) - { - // already got a slice and this is non-slice NAL: return - rewind_data_buf_pos_by(nal_size); - frame_pkt_size -= nal_size; - break; - } - // otherwise continue until a slice is found - } // while there is still NAL - } else +static const uint8_t default_scaling_list_inter[] = { + 16, 16, 16, 16, 17, 18, 20, 24, 16, 16, 16, 17, 18, 20, 24, 25, + 16, 16, 17, 18, 20, 24, 25, 28, 16, 17, 18, 20, 24, 25, 28, 33, + 17, 18, 20, 24, 25, 28, 33, 41, 18, 20, 24, 25, 28, 33, 41, 54, + 20, 24, 25, 28, 33, 41, 54, 71, 24, 25, 28, 33, 41, 54, 71, 91}; + +static const uint8_t default_scaling_list_intra[] = { + 16, 16, 16, 16, 17, 18, 21, 24, 16, 16, 16, 16, 17, 19, 22, 25, + 16, 16, 17, 18, 20, 22, 25, 29, 16, 16, 18, 21, 24, 27, 31, 36, + 17, 17, 20, 24, 30, 35, 41, 47, 18, 19, 22, 27, 35, 44, 54, 65, + 21, 22, 25, 31, 41, 54, 70, 88, 24, 25, 29, 36, 47, 65, 88, 115}; + +/** + * find/copy next H.265 NAL unit (including start code) and its type; + * return NAL data size if found, 0 otherwise +*/ +uint32_t find_h265_next_nalu(uint8_t *p_dst, int *nal_type) +{ + uint32_t data_size; + uint32_t i = curr_found_pos; + + if (i + 3 >= total_file_size) + { + ni_log(NI_LOG_DEBUG, + "%s reaching end, curr_pos %d " + "total input size %u\n", + __func__, curr_found_pos, total_file_size); + + if (g_repeat > 1) { - frame_pkt_size = read_next_chunk(tmp_buf, packet_size); - // chunk_size = frame_pkt_size; + g_repeat--; + ni_log(NI_LOG_DEBUG, "input processed, %d left\n", g_repeat); + reset_data_buf_pos(); } - ni_log(NI_LOG_DEBUG, "decoder_send_data * frame_pkt_size %d\n", - frame_pkt_size); - - p_in_pkt->p_data = NULL; - p_in_pkt->data_len = frame_pkt_size; + return 0; + } - if (frame_pkt_size + p_dec_ctx->prev_size > 0) + // search for start code 0x000001 or 0x00000001 + while ((g_curr_cache_pos[i] != 0x00 || g_curr_cache_pos[i + 1] != 0x00 || + g_curr_cache_pos[i + 2] != 0x01) && + (g_curr_cache_pos[i] != 0x00 || g_curr_cache_pos[i + 1] != 0x00 || + g_curr_cache_pos[i + 2] != 0x00 || g_curr_cache_pos[i + 3] != 0x01)) + { + i++; + if (i + 3 > total_file_size) { - ni_packet_buffer_alloc(p_in_pkt, - (int)frame_pkt_size + p_dec_ctx->prev_size); + return 0; } + } - new_packet = 1; - send_size = frame_pkt_size + p_dec_ctx->prev_size; - saved_prev_size = p_dec_ctx->prev_size; - } else + // found start code, advance to NAL unit start depends on actual start code + if (g_curr_cache_pos[i] != 0x00 || g_curr_cache_pos[i + 1] != 0x00 || + g_curr_cache_pos[i + 2] != 0x01) { - send_size = p_in_pkt->data_len; + i++; } - p_in_pkt->start_of_stream = sos_flag; - p_in_pkt->end_of_stream = 0; - p_in_pkt->video_width = input_video_width; - p_in_pkt->video_height = input_video_height; + i += 3; + curr_nal_start = i; - if (send_size == 0) + // get the NAL type + *nal_type = (g_curr_cache_pos[i] & 0x7E) >> 1; + + // advance to the end of NAL, or stream + while ((g_curr_cache_pos[i] != 0x00 || g_curr_cache_pos[i + 1] != 0x00 || + g_curr_cache_pos[i + 2] != 0x00) && + (g_curr_cache_pos[i] != 0x00 || g_curr_cache_pos[i + 1] != 0x00 || + g_curr_cache_pos[i + 2] != 0x01)) { - if (new_packet) + i++; + // if reaching the stream end + if (i + 3 > total_file_size) { - send_size = - ni_packet_copy(p_in_pkt->p_data, tmp_buf, 0, - p_dec_ctx->p_leftover, &p_dec_ctx->prev_size); - // todo save offset + data_size = total_file_size - curr_found_pos; + memcpy(p_dst, &g_curr_cache_pos[curr_found_pos], data_size); + curr_found_pos = (int)total_file_size; + return data_size; } - p_in_pkt->data_len = send_size; + } - p_in_pkt->end_of_stream = 1; - printf("Sending p_last packet (size %u) + eos\n", p_in_pkt->data_len); - } else + data_size = i - curr_found_pos; + memcpy(p_dst, &g_curr_cache_pos[curr_found_pos], data_size); + curr_found_pos = i; + return data_size; +} + +static void h265_decode_sublayer_hrd(ni_bitstream_reader_t *br, + unsigned int nb_cpb, + int subpic_params_present) +{ + uint32_t i; + + for (i = 0; i < nb_cpb; i++) { - if (new_packet) + ni_bs_reader_get_ue(br); // bit_rate_value_minus1 + ni_bs_reader_get_ue(br); // cpb_size_value_minus1 + + if (subpic_params_present) { - send_size = - ni_packet_copy(p_in_pkt->p_data, tmp_buf, frame_pkt_size, - p_dec_ctx->p_leftover, &p_dec_ctx->prev_size); - // todo: update offset with send_size - // p_in_pkt->data_len is the actual packet size to be sent to decoder - p_in_pkt->data_len += saved_prev_size; + ni_bs_reader_get_ue(br); // cpb_size_du_value_minus1 + ni_bs_reader_get_ue(br); // bit_rate_du_value_minus1 } + ni_bs_reader_skip_bits(br, 1); // cbr_flag } +} - tx_size = - ni_device_session_write(p_dec_ctx, p_in_data, NI_DEVICE_TYPE_DECODER); +static int h265_decode_profile_tier_level(ni_bitstream_reader_t *br, + PTLCommon *ptl) +{ + int i; - if (tx_size < 0) - { - // Error - fprintf(stderr, "Error: sending data error. rc:%d\n", tx_size); - retval = NI_RETCODE_FAILURE; - LRETURN; - } else if (tx_size == 0) - { - ni_log(NI_LOG_DEBUG, "0 byte sent this time, sleep and will re-try.\n"); - ni_usleep(10000); - } else if ((uint32_t)tx_size < send_size) + if (ni_bs_reader_get_bits_left(br) < 2 + 1 + 5 + 32 + 4 + 43 + 1) + return -1; + + ptl->profile_space = ni_bs_reader_get_bits(br, 2); + ptl->tier_flag = ni_bs_reader_get_bits(br, 1); + ptl->profile_idc = ni_bs_reader_get_bits(br, 5); + + for (i = 0; i < 32; i++) { - if (print_time) + ptl->profile_compatibility_flag[i] = ni_bs_reader_get_bits(br, 1); + + if (ptl->profile_idc == 0 && i > 0 && + ptl->profile_compatibility_flag[i]) + ptl->profile_idc = i; + } + ptl->progressive_source_flag = ni_bs_reader_get_bits(br, 1); + ptl->interlaced_source_flag = ni_bs_reader_get_bits(br, 1); + ptl->non_packed_constraint_flag = ni_bs_reader_get_bits(br, 1); + ptl->frame_only_constraint_flag = ni_bs_reader_get_bits(br, 1); + +#define check_profile_idc(idc) \ + ptl->profile_idc == (idc) || ptl->profile_compatibility_flag[idc] + + if (check_profile_idc(4) || check_profile_idc(5) || check_profile_idc(6) || + check_profile_idc(7) || check_profile_idc(8) || check_profile_idc(9) || + check_profile_idc(10)) + { + ptl->max_12bit_constraint_flag = ni_bs_reader_get_bits(br, 1); + ptl->max_10bit_constraint_flag = ni_bs_reader_get_bits(br, 1); + ptl->max_8bit_constraint_flag = ni_bs_reader_get_bits(br, 1); + ptl->max_422chroma_constraint_flag = ni_bs_reader_get_bits(br, 1); + ptl->max_420chroma_constraint_flag = ni_bs_reader_get_bits(br, 1); + ptl->max_monochrome_constraint_flag = ni_bs_reader_get_bits(br, 1); + ptl->intra_constraint_flag = ni_bs_reader_get_bits(br, 1); + ptl->one_picture_only_constraint_flag = ni_bs_reader_get_bits(br, 1); + ptl->lower_bit_rate_constraint_flag = ni_bs_reader_get_bits(br, 1); + + if (check_profile_idc(5) || check_profile_idc(9) || + check_profile_idc(10)) { - //printf("Sent %d < %d , re-try next time ?\n", tx_size, send_size); + ptl->max_14bit_constraint_flag = ni_bs_reader_get_bits(br, 1); + ni_bs_reader_skip_bits(br, 33); // XXX_reserved_zero_33bits[0..32] + } else + { + ni_bs_reader_skip_bits(br, 34); // XXX_reserved_zero_34bits[0..33] } + } else if (check_profile_idc(2)) + { + ni_bs_reader_skip_bits(br, 7); + ptl->one_picture_only_constraint_flag = ni_bs_reader_get_bits(br, 1); + ni_bs_reader_skip_bits(br, 35); // XXX_reserved_zero_35bits[0..34] + } else + { + ni_bs_reader_skip_bits(br, 43); // XXX_reserved_zero_43bits[0..42] } - *total_bytes_sent += tx_size; + if (check_profile_idc(1) || check_profile_idc(2) || check_profile_idc(3) || + check_profile_idc(4) || check_profile_idc(5) || check_profile_idc(9)) + ptl->inbld_flag = ni_bs_reader_get_bits(br, 1); + else + ni_bs_reader_skip_bits(br, 1); +#undef check_profile_idc - if (p_dec_ctx->ready_to_close) + return 0; +} + +static int h265_parse_ptl(ni_bitstream_reader_t *br, PTL *ptl, + int max_num_sub_layers) +{ + int i; + if (h265_decode_profile_tier_level(br, &ptl->general_ptl) < 0 || + ni_bs_reader_get_bits_left(br) < + 8 + (8 * 2 * (max_num_sub_layers - 1 > 0))) { - p_device_state->dec_eos_sent = 1; + ni_log(NI_LOG_ERROR, "PTL information too short\n"); + return -1; } - if (print_time) + ptl->general_ptl.level_idc = ni_bs_reader_get_bits(br, 8); + + for (i = 0; i < max_num_sub_layers - 1; i++) { - printf("decoder_send_data: success, total sent: %lu\n", - *total_bytes_sent); + ptl->sub_layer_profile_present_flag[i] = ni_bs_reader_get_bits(br, 1); + ptl->sub_layer_level_present_flag[i] = ni_bs_reader_get_bits(br, 1); } - if (tx_size > 0) + if (max_num_sub_layers - 1 > 0) + for (i = max_num_sub_layers - 1; i < 8; i++) + ni_bs_reader_skip_bits(br, 2); // reserved_zero_2bits[i] + for (i = 0; i < max_num_sub_layers - 1; i++) + { + if (ptl->sub_layer_profile_present_flag[i] && + h265_decode_profile_tier_level(br, &ptl->sub_layer_ptl[i]) < 0) + { + ni_log(NI_LOG_ERROR, "PTL information for sublayer %i too short\n", + i); + return -1; + } + if (ptl->sub_layer_level_present_flag[i]) + { + if (ni_bs_reader_get_bits_left(br) < 8) + { + ni_log(NI_LOG_ERROR, + "Not enough data for sublayer %i level_idc\n", i); + return -1; + } else + ptl->sub_layer_ptl[i].level_idc = ni_bs_reader_get_bits(br, 8); + } + } + + return 0; +} + +static int h265_decode_hrd(ni_bitstream_reader_t *br, int common_inf_present, + int max_sublayers) +{ + int nal_params_present = 0, vcl_params_present = 0; + int subpic_params_present = 0; + int i; + + if (common_inf_present) + { + nal_params_present = ni_bs_reader_get_bits(br, 1); + vcl_params_present = ni_bs_reader_get_bits(br, 1); + + if (nal_params_present || vcl_params_present) + { + subpic_params_present = ni_bs_reader_get_bits(br, 1); + + if (subpic_params_present) + { + ni_bs_reader_skip_bits(br, 8); // tick_divisor_minus2 + ni_bs_reader_skip_bits( + br, 5); // du_cpb_removal_delay_increment_length_minus1 + ni_bs_reader_skip_bits( + br, 1); // sub_pic_cpb_params_in_pic_timing_sei_flag + ni_bs_reader_skip_bits( + br, 5); // dpb_output_delay_du_length_minus1 + } + + ni_bs_reader_skip_bits(br, 4); // bit_rate_scale + ni_bs_reader_skip_bits(br, 4); // cpb_size_scale + + if (subpic_params_present) + ni_bs_reader_skip_bits(br, 4); // cpb_size_du_scale + + ni_bs_reader_skip_bits( + br, 5); // initial_cpb_removal_delay_length_minus1 + ni_bs_reader_skip_bits(br, + 5); // au_cpb_removal_delay_length_minus1 + ni_bs_reader_skip_bits(br, 5); // dpb_output_delay_length_minus1 + } + } + + for (i = 0; i < max_sublayers; i++) + { + int low_delay = 0; + unsigned int nb_cpb = 1; + int fixed_rate = ni_bs_reader_get_bits(br, 1); + + if (!fixed_rate) + fixed_rate = ni_bs_reader_get_bits(br, 1); + + if (fixed_rate) + ni_bs_reader_get_ue(br); // elemental_duration_in_tc_minus1 + else + low_delay = ni_bs_reader_get_bits(br, 1); + + if (!low_delay) + { + nb_cpb = ni_bs_reader_get_ue(br) + 1; + if (nb_cpb < 1 || nb_cpb > 32) + { + ni_log(NI_LOG_ERROR, "nb_cpb %d invalid\n", nb_cpb); + return -1; + } + } + + if (nal_params_present) + h265_decode_sublayer_hrd(br, nb_cpb, subpic_params_present); + if (vcl_params_present) + h265_decode_sublayer_hrd(br, nb_cpb, subpic_params_present); + } + return 0; +} + +static void h265_set_default_scaling_list_data(ScalingList *sl) +{ + int matrixId; + + for (matrixId = 0; matrixId < 6; matrixId++) + { + // 4x4 default is 16 + memset(sl->sl[0][matrixId], 16, 16); + sl->sl_dc[0][matrixId] = 16; // default for 16x16 + sl->sl_dc[1][matrixId] = 16; // default for 32x32 + } + memcpy(sl->sl[1][0], default_scaling_list_intra, 64); + memcpy(sl->sl[1][1], default_scaling_list_intra, 64); + memcpy(sl->sl[1][2], default_scaling_list_intra, 64); + memcpy(sl->sl[1][3], default_scaling_list_inter, 64); + memcpy(sl->sl[1][4], default_scaling_list_inter, 64); + memcpy(sl->sl[1][5], default_scaling_list_inter, 64); + memcpy(sl->sl[2][0], default_scaling_list_intra, 64); + memcpy(sl->sl[2][1], default_scaling_list_intra, 64); + memcpy(sl->sl[2][2], default_scaling_list_intra, 64); + memcpy(sl->sl[2][3], default_scaling_list_inter, 64); + memcpy(sl->sl[2][4], default_scaling_list_inter, 64); + memcpy(sl->sl[2][5], default_scaling_list_inter, 64); + memcpy(sl->sl[3][0], default_scaling_list_intra, 64); + memcpy(sl->sl[3][1], default_scaling_list_intra, 64); + memcpy(sl->sl[3][2], default_scaling_list_intra, 64); + memcpy(sl->sl[3][3], default_scaling_list_inter, 64); + memcpy(sl->sl[3][4], default_scaling_list_inter, 64); + memcpy(sl->sl[3][5], default_scaling_list_inter, 64); +} + +static int h265_scaling_list_data(ni_bitstream_reader_t *br, ScalingList *sl, + ni_h265_sps_t *sps) +{ + uint8_t scaling_list_pred_mode_flag; + int32_t scaling_list_dc_coef[2][6]; + int size_id, matrix_id, pos; + int i; + + for (size_id = 0; size_id < 4; size_id++) + for (matrix_id = 0; matrix_id < 6; + matrix_id += ((size_id == 3) ? 3 : 1)) + { + scaling_list_pred_mode_flag = ni_bs_reader_get_bits(br, 1); + if (!scaling_list_pred_mode_flag) + { + int delta = ni_bs_reader_get_ue(br); + /* Only need to handle non-zero delta. Zero means default, + * which should already be in the arrays. */ + if (delta) + { + // Copy from previous array. + delta *= (size_id == 3) ? 3 : 1; + if (matrix_id < delta) + { + ni_log(NI_LOG_ERROR, + "Invalid delta in scaling list data: %d.\n", + delta); + return -1; + } + + memcpy(sl->sl[size_id][matrix_id], + sl->sl[size_id][matrix_id - delta], + size_id > 0 ? 64 : 16); + if (size_id > 1) + sl->sl_dc[size_id - 2][matrix_id] = + sl->sl_dc[size_id - 2][matrix_id - delta]; + } + } else + { + int32_t next_coef, coef_num; + int32_t scaling_list_delta_coef; + + next_coef = 8; + coef_num = 1 << (4 + (size_id << 1)); + if (coef_num >= 64) + coef_num = 64; + if (size_id > 1) + { + scaling_list_dc_coef[size_id - 2][matrix_id] = + ni_bs_reader_get_se(br) + 8; + next_coef = scaling_list_dc_coef[size_id - 2][matrix_id]; + sl->sl_dc[size_id - 2][matrix_id] = next_coef; + } + for (i = 0; i < coef_num; i++) + { + if (size_id == 0) + pos = + 4 * hevc_diag_scan4x4_y[i] + hevc_diag_scan4x4_x[i]; + else + pos = + 8 * hevc_diag_scan8x8_y[i] + hevc_diag_scan8x8_x[i]; + + scaling_list_delta_coef = ni_bs_reader_get_se(br); + next_coef = + (next_coef + 256U + scaling_list_delta_coef) % 256; + sl->sl[size_id][matrix_id][pos] = next_coef; + } + } + } + + if (sps->chroma_format_idc == 3) + { + for (i = 0; i < 64; i++) + { + sl->sl[3][1][i] = sl->sl[2][1][i]; + sl->sl[3][2][i] = sl->sl[2][2][i]; + sl->sl[3][4][i] = sl->sl[2][4][i]; + sl->sl[3][5][i] = sl->sl[2][5][i]; + } + sl->sl_dc[1][1] = sl->sl_dc[0][1]; + sl->sl_dc[1][2] = sl->sl_dc[0][2]; + sl->sl_dc[1][4] = sl->sl_dc[0][4]; + sl->sl_dc[1][5] = sl->sl_dc[0][5]; + } + + return 0; +} + +static int h265_decode_short_term_rps(ni_bitstream_reader_t *br, + ShortTermRPS *rps, + const ni_h265_sps_t *sps, + int is_slice_header) +{ + uint8_t rps_predict = 0; + int32_t delta_poc; + int k0 = 0; + int k1 = 0; + int32_t k = 0; + int i; + + if (rps != sps->st_rps && sps->nb_st_rps) + rps_predict = ni_bs_reader_get_bits(br, 1); + + if (rps_predict) + { + const ShortTermRPS *rps_ridx; + int32_t delta_rps; + int32_t abs_delta_rps; + uint8_t use_delta_flag = 0; + uint8_t delta_rps_sign; + + if (is_slice_header) + { + unsigned int delta_idx = ni_bs_reader_get_ue(br) + 1; + if (delta_idx > sps->nb_st_rps) + { + ni_log(NI_LOG_ERROR, + "Invalid value of delta_idx in slice header RPS: %d > " + "%d.\n", + delta_idx, sps->nb_st_rps); + return -1; + } + rps_ridx = &sps->st_rps[sps->nb_st_rps - delta_idx]; + rps->rps_idx_num_delta_pocs = rps_ridx->num_delta_pocs; + } else + rps_ridx = &sps->st_rps[rps - sps->st_rps - 1]; + + delta_rps_sign = ni_bs_reader_get_bits(br, 1); + abs_delta_rps = (int)(ni_bs_reader_get_ue(br) + 1); + if (abs_delta_rps < 1 || abs_delta_rps > 32768) + { + ni_log(NI_LOG_ERROR, "Invalid value of abs_delta_rps: %d\n", + abs_delta_rps); + return -1; + } + delta_rps = (1 - (delta_rps_sign << 1)) * abs_delta_rps; + for (i = 0; i <= rps_ridx->num_delta_pocs; i++) + { + int used = rps->used[k] = ni_bs_reader_get_bits(br, 1); + + if (!used) + use_delta_flag = ni_bs_reader_get_bits(br, 1); + + if (used || use_delta_flag) + { + if (i < rps_ridx->num_delta_pocs) + delta_poc = delta_rps + rps_ridx->delta_poc[i]; + else + delta_poc = delta_rps; + rps->delta_poc[k] = delta_poc; + if (delta_poc < 0) + k0++; + else + k1++; + k++; + } + } + + if (k >= (sizeof(rps->used) / sizeof(rps->used[0]))) + { + ni_log(NI_LOG_ERROR, "Invalid num_delta_pocs: %d\n", k); + return -1; + } + + rps->num_delta_pocs = k; + rps->num_negative_pics = k0; + // sort in increasing order (smallest first) + if (rps->num_delta_pocs != 0) + { + int used, tmp; + for (i = 1; i < rps->num_delta_pocs; i++) + { + delta_poc = rps->delta_poc[i]; + used = rps->used[i]; + for (k = i - 1; k >= 0; k--) + { + tmp = rps->delta_poc[k]; + if (delta_poc < tmp) + { + rps->delta_poc[k + 1] = tmp; + rps->used[k + 1] = rps->used[k]; + rps->delta_poc[k] = delta_poc; + rps->used[k] = used; + } + } + } + } + if ((rps->num_negative_pics >> 1) != 0) + { + int used; + k = rps->num_negative_pics - 1; + // flip the negative values to largest first + for (i = 0; i < (int)(rps->num_negative_pics >> 1); i++) + { + delta_poc = rps->delta_poc[i]; + used = rps->used[i]; + rps->delta_poc[i] = rps->delta_poc[k]; + rps->used[i] = rps->used[k]; + rps->delta_poc[k] = delta_poc; + rps->used[k] = used; + k--; + } + } + } else + { + int prev, nb_positive_pics; + rps->num_negative_pics = ni_bs_reader_get_ue(br); + nb_positive_pics = ni_bs_reader_get_ue(br); + + if (rps->num_negative_pics >= HEVC_MAX_REFS || + nb_positive_pics >= HEVC_MAX_REFS) + { + ni_log(NI_LOG_ERROR, "Too many refs in a short term RPS.\n"); + return -1; + } + + rps->num_delta_pocs = (int)(rps->num_negative_pics + nb_positive_pics); + if (rps->num_delta_pocs) + { + prev = 0; + for (i = 0; i < (int)rps->num_negative_pics; i++) + { + delta_poc = ni_bs_reader_get_ue(br) + 1; + if (delta_poc < 1 || delta_poc > 32768) + { + ni_log(NI_LOG_ERROR, "Invalid value of delta_poc: %d\n", + delta_poc); + return -1; + } + prev -= delta_poc; + rps->delta_poc[i] = prev; + rps->used[i] = ni_bs_reader_get_bits(br, 1); + } + prev = 0; + for (i = 0; i < nb_positive_pics; i++) + { + delta_poc = ni_bs_reader_get_ue(br) + 1; + if (delta_poc < 1 || delta_poc > 32768) + { + ni_log(NI_LOG_ERROR, "Invalid value of delta_poc: %d\n", + delta_poc); + return -1; + } + prev += delta_poc; + rps->delta_poc[rps->num_negative_pics + i] = prev; + rps->used[rps->num_negative_pics + i] = + ni_bs_reader_get_bits(br, 1); + } + } + } + return 0; +} + +static int h265_decode_vui(ni_bitstream_reader_t *br, int apply_defdispwin, + ni_h265_sps_t *sps) +{ + VUI backup_vui, *vui = &sps->vui; + ni_bitstream_reader_t br_backup; + int sar_present, alt = 0; + + sar_present = ni_bs_reader_get_bits(br, 1); + if (sar_present) + { + uint8_t sar_idx = ni_bs_reader_get_bits(br, 8); + if (sar_idx < (sizeof(vui_sar) / sizeof(vui_sar[0]))) + vui->sar = vui_sar[sar_idx]; + else if (sar_idx == 255) + { + vui->sar.num = ni_bs_reader_get_bits(br, 16); + vui->sar.den = ni_bs_reader_get_bits(br, 16); + } else + { + ni_log(NI_LOG_ERROR, "Unknown SAR Index: %u.\n", sar_idx); + } + } + + vui->overscan_info_present_flag = ni_bs_reader_get_bits(br, 1); + if (vui->overscan_info_present_flag) + vui->overscan_appropriate_flag = ni_bs_reader_get_bits(br, 1); + + vui->video_signal_type_present_flag = ni_bs_reader_get_bits(br, 1); + if (vui->video_signal_type_present_flag) + { + vui->video_format = ni_bs_reader_get_bits(br, 3); + vui->video_full_range_flag = ni_bs_reader_get_bits(br, 1); + vui->colour_description_present_flag = ni_bs_reader_get_bits(br, 1); + if (vui->video_full_range_flag && sps->pix_fmt == NI_PIX_FMT_YUV420P) + sps->pix_fmt = NI_PIX_FMT_YUV420P; + if (vui->colour_description_present_flag) + { + vui->colour_primaries = ni_bs_reader_get_bits(br, 8); + vui->transfer_characteristic = ni_bs_reader_get_bits(br, 8); + vui->matrix_coeffs = ni_bs_reader_get_bits(br, 8); + + if (vui->colour_primaries >= NI_COL_PRI_NB) + { + vui->colour_primaries = NI_COL_PRI_UNSPECIFIED; + } + if (vui->transfer_characteristic >= NI_COL_TRC_NB) + { + vui->transfer_characteristic = NI_COL_TRC_UNSPECIFIED; + } + if (vui->matrix_coeffs >= NI_COL_SPC_NB) + { + vui->matrix_coeffs = NI_COL_SPC_UNSPECIFIED; + } + if (vui->matrix_coeffs == NI_COL_SPC_RGB) + { + if (sps->pix_fmt) + { + ni_log(NI_LOG_ERROR, + "Invalid format, only support yuv420p\n"); + return -1; + } + } + } + } + + vui->chroma_loc_info_present_flag = ni_bs_reader_get_bits(br, 1); + if (vui->chroma_loc_info_present_flag) + { + vui->chroma_sample_loc_type_top_field = ni_bs_reader_get_ue(br); + vui->chroma_sample_loc_type_bottom_field = ni_bs_reader_get_ue(br); + } + + vui->neutra_chroma_indication_flag = ni_bs_reader_get_bits(br, 1); + vui->field_seq_flag = ni_bs_reader_get_bits(br, 1); + vui->frame_field_info_present_flag = ni_bs_reader_get_bits(br, 1); + + // Backup context in case an alternate header is detected + memcpy(&br_backup, br, sizeof(br_backup)); + memcpy(&backup_vui, vui, sizeof(backup_vui)); + vui->default_display_window_flag = ni_bs_reader_get_bits(br, 1); + + if (vui->default_display_window_flag) + { + int vert_mult = hevc_sub_height_c[sps->chroma_format_idc]; + int horiz_mult = hevc_sub_width_c[sps->chroma_format_idc]; + vui->def_disp_win.left_offset = ni_bs_reader_get_ue(br) * horiz_mult; + vui->def_disp_win.right_offset = ni_bs_reader_get_ue(br) * horiz_mult; + vui->def_disp_win.top_offset = ni_bs_reader_get_ue(br) * vert_mult; + vui->def_disp_win.bottom_offset = ni_bs_reader_get_ue(br) * vert_mult; + + if (apply_defdispwin) + { + ni_log(NI_LOG_DEBUG, + "discarding vui default display window, " + "original values are l:%u r:%u t:%u b:%u\n", + vui->def_disp_win.left_offset, + vui->def_disp_win.right_offset, vui->def_disp_win.top_offset, + vui->def_disp_win.bottom_offset); + + vui->def_disp_win.left_offset = vui->def_disp_win.right_offset = + vui->def_disp_win.top_offset = vui->def_disp_win.bottom_offset = + 0; + } + } + +timing_info: + vui->vui_timing_info_present_flag = ni_bs_reader_get_bits(br, 1); + + if (vui->vui_timing_info_present_flag) + { + if (ni_bs_reader_get_bits_left(br) < 66 && !alt) + { + // The alternate syntax seem to have timing info located + // at where def_disp_win is normally located + ni_log(NI_LOG_INFO, + "Strange VUI timing information, retrying...\n"); + memcpy(vui, &backup_vui, sizeof(backup_vui)); + memcpy(br, &br_backup, sizeof(br_backup)); + alt = 1; + goto timing_info; + } + vui->vui_num_units_in_tick = ni_bs_reader_get_bits(br, 32); + vui->vui_time_scale = ni_bs_reader_get_bits(br, 32); + if (alt) + { + ni_log(NI_LOG_INFO, "Retry got %u/%ufps\n", vui->vui_time_scale, + vui->vui_num_units_in_tick); + } + vui->vui_poc_proportional_to_timing_flag = ni_bs_reader_get_bits(br, 1); + if (vui->vui_poc_proportional_to_timing_flag) + vui->vui_num_ticks_poc_diff_one_minus1 = ni_bs_reader_get_ue(br); + vui->vui_hrd_parameters_present_flag = ni_bs_reader_get_bits(br, 1); + if (vui->vui_hrd_parameters_present_flag) + h265_decode_hrd(br, 1, sps->max_sub_layers); + } + + vui->bitstream_restriction_flag = ni_bs_reader_get_bits(br, 1); + if (vui->bitstream_restriction_flag) + { + if (ni_bs_reader_get_bits_left(br) < 8 && !alt) + { + ni_log(NI_LOG_INFO, + "Strange VUI bitstream restriction information, retrying" + " from timing information...\n"); + memcpy(vui, &backup_vui, sizeof(backup_vui)); + memcpy(br, &br_backup, sizeof(br_backup)); + alt = 1; + goto timing_info; + } + vui->tiles_fixed_structure_flag = ni_bs_reader_get_bits(br, 1); + vui->motion_vectors_over_pic_boundaries_flag = + ni_bs_reader_get_bits(br, 1); + vui->restricted_ref_pic_lists_flag = ni_bs_reader_get_bits(br, 1); + vui->min_spatial_segmentation_idc = ni_bs_reader_get_ue(br); + vui->max_bytes_per_pic_denom = ni_bs_reader_get_ue(br); + vui->max_bits_per_min_cu_denom = ni_bs_reader_get_ue(br); + vui->log2_max_mv_length_horizontal = ni_bs_reader_get_ue(br); + vui->log2_max_mv_length_vertical = ni_bs_reader_get_ue(br); + } + + if (ni_bs_reader_get_bits_left(br) < 1 && !alt) + { + // XXX: Alternate syntax when sps_range_extension_flag != 0? + ni_log(NI_LOG_INFO, + "Overread in VUI, retrying from timing information...\n"); + memcpy(vui, &backup_vui, sizeof(backup_vui)); + memcpy(br, &br_backup, sizeof(br_backup)); + alt = 1; + goto timing_info; + } + return 0; +} + +int h265_parse_sps(ni_h265_sps_t *sps, uint8_t *buf, int size_bytes) +{ + ni_h265_window_t *ow; + int ret = 0; + int log2_diff_max_min_transform_block_size; + int bit_depth_chroma, start, vui_present, sublayer_ordering_info; + int i; + + ni_bitstream_reader_t br; + uint32_t sps_id; + ni_bitstream_reader_init(&br, buf, 8 * size_bytes); + + ni_bs_reader_skip_bits(&br, 16); // skip NAL header + + sps->vps_id = ni_bs_reader_get_bits(&br, 4); + + sps->max_sub_layers = (int)ni_bs_reader_get_bits(&br, 3) + 1; + if (sps->max_sub_layers > HEVC_MAX_SUB_LAYERS) + { + ni_log(NI_LOG_ERROR, "sps_max_sub_layers out of range: %d\n", + sps->max_sub_layers); + return -1; + } + + sps->temporal_id_nesting_flag = ni_bs_reader_get_bits(&br, 1); + + if ((ret = h265_parse_ptl(&br, &sps->ptl, sps->max_sub_layers)) < 0) + return ret; + + sps_id = ni_bs_reader_get_ue(&br); + if (sps_id >= HEVC_MAX_SPS_COUNT) + { + ni_log(NI_LOG_ERROR, "SPS id out of range: %d\n", sps_id); + return -1; + } + + sps->chroma_format_idc = ni_bs_reader_get_ue(&br); + if (sps->chroma_format_idc > 3U) + { + ni_log(NI_LOG_ERROR, "chroma_format_idc %d is invalid\n", + sps->chroma_format_idc); + return -1; + } + + if (sps->chroma_format_idc == 3) + sps->separate_colour_plane_flag = ni_bs_reader_get_bits(&br, 1); + + if (sps->separate_colour_plane_flag) + sps->chroma_format_idc = 0; + + sps->width = (int)ni_bs_reader_get_ue(&br); + sps->height = (int)ni_bs_reader_get_ue(&br); + + if (ni_bs_reader_get_bits(&br, 1)) + { // pic_conformance_flag + int vert_mult = hevc_sub_height_c[sps->chroma_format_idc]; + int horiz_mult = hevc_sub_width_c[sps->chroma_format_idc]; + sps->pic_conf_win.left_offset = ni_bs_reader_get_ue(&br) * horiz_mult; + sps->pic_conf_win.right_offset = ni_bs_reader_get_ue(&br) * horiz_mult; + sps->pic_conf_win.top_offset = ni_bs_reader_get_ue(&br) * vert_mult; + sps->pic_conf_win.bottom_offset = ni_bs_reader_get_ue(&br) * vert_mult; + + sps->output_window = sps->pic_conf_win; + } + + sps->bit_depth = (int)(ni_bs_reader_get_ue(&br) + 8); + bit_depth_chroma = (int)(ni_bs_reader_get_ue(&br) + 8); + if (sps->chroma_format_idc && bit_depth_chroma != sps->bit_depth) + { + ni_log(NI_LOG_ERROR, + "Luma bit depth (%d) is different from chroma bit depth (%d), " + "this is unsupported.\n", + sps->bit_depth, bit_depth_chroma); + return -1; + } + sps->bit_depth_chroma = bit_depth_chroma; + if (((sps->bit_depth != 8) && (sps->bit_depth != 10)) || + (sps->chroma_format_idc != 1)) + { + ni_log(NI_LOG_ERROR, + "only support 8bit/10bit yuv420p, bit_depth %d, " + "chroma_format_idc %d\n", + sps->bit_depth, sps->chroma_format_idc); + return -1; + } + sps->pix_fmt = 0; + sps->hshift[0] = sps->vshift[0] = 0; + sps->hshift[2] = sps->hshift[1] = 1; + sps->vshift[2] = sps->vshift[1] = 1; + sps->pixel_shift = sps->bit_depth > 8; + + sps->log2_max_poc_lsb = ni_bs_reader_get_ue(&br) + 4; + if (sps->log2_max_poc_lsb > 16) + { + ni_log(NI_LOG_ERROR, + "log2_max_pic_order_cnt_lsb_minus4 out range: %d\n", + sps->log2_max_poc_lsb - 4); + return -1; + } + + sublayer_ordering_info = ni_bs_reader_get_bits(&br, 1); + start = sublayer_ordering_info ? 0 : sps->max_sub_layers - 1; + for (i = start; i < sps->max_sub_layers; i++) + { + sps->temporal_layer[i].max_dec_pic_buffering = + (int)(ni_bs_reader_get_ue(&br) + 1); + sps->temporal_layer[i].num_reorder_pics = (int)ni_bs_reader_get_ue(&br); + sps->temporal_layer[i].max_latency_increase = + (int)(ni_bs_reader_get_ue(&br) - 1); + if (sps->temporal_layer[i].num_reorder_pics > + sps->temporal_layer[i].max_dec_pic_buffering - 1) + { + ni_log(NI_LOG_ERROR, "sps_max_num_reorder_pics out of range: %d\n", + sps->temporal_layer[i].num_reorder_pics); + sps->temporal_layer[i].max_dec_pic_buffering = + sps->temporal_layer[i].num_reorder_pics + 1; + } + } + + if (!sublayer_ordering_info) + { + for (i = 0; i < start; i++) + { + sps->temporal_layer[i].max_dec_pic_buffering = + sps->temporal_layer[start].max_dec_pic_buffering; + sps->temporal_layer[i].num_reorder_pics = + sps->temporal_layer[start].num_reorder_pics; + sps->temporal_layer[i].max_latency_increase = + sps->temporal_layer[start].max_latency_increase; + } + } + + sps->log2_min_cb_size = ni_bs_reader_get_ue(&br) + 3; + sps->log2_diff_max_min_coding_block_size = ni_bs_reader_get_ue(&br); + sps->log2_min_tb_size = ni_bs_reader_get_ue(&br) + 2; + log2_diff_max_min_transform_block_size = ni_bs_reader_get_ue(&br); + sps->log2_max_trafo_size = + log2_diff_max_min_transform_block_size + sps->log2_min_tb_size; + + if (sps->log2_min_cb_size < 3 || sps->log2_min_cb_size > 30) + { + ni_log(NI_LOG_ERROR, "Invalid value %d for log2_min_cb_size", + sps->log2_min_cb_size); + return -1; + } + + if (sps->log2_diff_max_min_coding_block_size > 30) + { + ni_log(NI_LOG_ERROR, + "Invalid value %d for log2_diff_max_min_coding_block_size", + sps->log2_diff_max_min_coding_block_size); + return -1; + } + + if (sps->log2_min_tb_size >= sps->log2_min_cb_size || + sps->log2_min_tb_size < 2) + { + ni_log(NI_LOG_ERROR, "Invalid value for log2_min_tb_size"); + return -1; + } + + if (log2_diff_max_min_transform_block_size < 0 || + log2_diff_max_min_transform_block_size > 30) + { + ni_log(NI_LOG_ERROR, + "Invalid value %d for log2_diff_max_min_transform_block_size", + log2_diff_max_min_transform_block_size); + return -1; + } + + sps->max_transform_hierarchy_depth_inter = ni_bs_reader_get_ue(&br); + sps->max_transform_hierarchy_depth_intra = ni_bs_reader_get_ue(&br); + + sps->scaling_list_enable_flag = ni_bs_reader_get_bits(&br, 1); + if (sps->scaling_list_enable_flag) + { + h265_set_default_scaling_list_data(&sps->scaling_list); + + if (ni_bs_reader_get_bits(&br, 1)) + { + ret = h265_scaling_list_data(&br, &sps->scaling_list, sps); + if (ret < 0) + return ret; + } + } + + sps->amp_enabled_flag = ni_bs_reader_get_bits(&br, 1); + sps->sao_enabled = ni_bs_reader_get_bits(&br, 1); + + sps->pcm_enabled_flag = ni_bs_reader_get_bits(&br, 1); + if (sps->pcm_enabled_flag) + { + sps->pcm.bit_depth = ni_bs_reader_get_bits(&br, 4) + 1; + sps->pcm.bit_depth_chroma = ni_bs_reader_get_bits(&br, 4) + 1; + sps->pcm.log2_min_pcm_cb_size = ni_bs_reader_get_ue(&br) + 3; + sps->pcm.log2_max_pcm_cb_size = + sps->pcm.log2_min_pcm_cb_size + ni_bs_reader_get_ue(&br); + if ((sps->pcm.bit_depth > sps->bit_depth) || + (sps->pcm.bit_depth_chroma > sps->bit_depth)) + { + ni_log(NI_LOG_ERROR, + "PCM bit depth (%d, %d) is greater than normal bit depth " + "(%d)\n", + sps->pcm.bit_depth, sps->pcm.bit_depth_chroma, + sps->bit_depth); + return -1; + } + + sps->pcm.loop_filter_disable_flag = ni_bs_reader_get_bits(&br, 1); + } + + sps->nb_st_rps = ni_bs_reader_get_ue(&br); + if (sps->nb_st_rps > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) + { + ni_log(NI_LOG_ERROR, "Too many short term RPS: %d.\n", sps->nb_st_rps); + return -1; + } + for (i = 0; i < (int)sps->nb_st_rps; i++) + { + if ((ret = h265_decode_short_term_rps(&br, &sps->st_rps[i], sps, 0)) < + 0) + return ret; + } + + sps->long_term_ref_pics_present_flag = ni_bs_reader_get_bits(&br, 1); + if (sps->long_term_ref_pics_present_flag) + { + sps->num_long_term_ref_pics_sps = ni_bs_reader_get_ue(&br); + if (sps->num_long_term_ref_pics_sps > HEVC_MAX_LONG_TERM_REF_PICS) + { + ni_log(NI_LOG_ERROR, "Too many long term ref pics: %d.\n", + sps->num_long_term_ref_pics_sps); + return -1; + } + for (i = 0; i < sps->num_long_term_ref_pics_sps; i++) + { + sps->lt_ref_pic_poc_lsb_sps[i] = + ni_bs_reader_get_bits(&br, (int)sps->log2_max_poc_lsb); + sps->used_by_curr_pic_lt_sps_flag[i] = + ni_bs_reader_get_bits(&br, 1); + } + } + + sps->sps_temporal_mvp_enabled_flag = ni_bs_reader_get_bits(&br, 1); + sps->sps_strong_intra_smoothing_enable_flag = ni_bs_reader_get_bits(&br, 1); + sps->vui.sar = (ni_rational_t){0, 1}; + vui_present = ni_bs_reader_get_bits(&br, 1); + if (vui_present) + h265_decode_vui(&br, 0, sps); + + if (ni_bs_reader_get_bits(&br, 1)) + { // sps_extension_flag + sps->sps_range_extension_flag = ni_bs_reader_get_bits(&br, 1); + ni_bs_reader_skip_bits( + &br, 7); //sps_extension_7bits = ni_bs_reader_get_bits(br, 7); + if (sps->sps_range_extension_flag) + { + sps->transform_skip_rotation_enabled_flag = + ni_bs_reader_get_bits(&br, 1); + sps->transform_skip_context_enabled_flag = + ni_bs_reader_get_bits(&br, 1); + sps->implicit_rdpcm_enabled_flag = ni_bs_reader_get_bits(&br, 1); + + sps->explicit_rdpcm_enabled_flag = ni_bs_reader_get_bits(&br, 1); + + sps->extended_precision_processing_flag = + ni_bs_reader_get_bits(&br, 1); + if (sps->extended_precision_processing_flag) + ni_log( + NI_LOG_INFO, + "extended_precision_processing_flag not yet implemented\n"); + + sps->intra_smoothing_disabled_flag = ni_bs_reader_get_bits(&br, 1); + sps->high_precision_offsets_enabled_flag = + ni_bs_reader_get_bits(&br, 1); + if (sps->high_precision_offsets_enabled_flag) + ni_log(NI_LOG_INFO, + "high_precision_offsets_enabled_flag not yet " + "implemented\n"); + + sps->persistent_rice_adaptation_enabled_flag = + ni_bs_reader_get_bits(&br, 1); + + sps->cabac_bypass_alignment_enabled_flag = + ni_bs_reader_get_bits(&br, 1); + if (sps->cabac_bypass_alignment_enabled_flag) + ni_log(NI_LOG_INFO, + "cabac_bypass_alignment_enabled_flag not yet " + "implemented\n"); + } + } + if (0) + { + sps->output_window.left_offset += sps->vui.def_disp_win.left_offset; + sps->output_window.right_offset += sps->vui.def_disp_win.right_offset; + sps->output_window.top_offset += sps->vui.def_disp_win.top_offset; + sps->output_window.bottom_offset += sps->vui.def_disp_win.bottom_offset; + } + + ow = &sps->output_window; + if (ow->left_offset >= INT32_MAX - ow->right_offset || + ow->top_offset >= INT32_MAX - ow->bottom_offset || + ow->left_offset + ow->right_offset >= (uint32_t)sps->width || + ow->top_offset + ow->bottom_offset >= (uint32_t)sps->height) + { + ni_log(NI_LOG_INFO, "Invalid cropping offsets: %u/%u/%u/%u\n", + ow->left_offset, ow->right_offset, ow->top_offset, + ow->bottom_offset); + ni_log(NI_LOG_INFO, "Displaying the whole video surface.\n"); + memset(ow, 0, sizeof(*ow)); + memset(&sps->pic_conf_win, 0, sizeof(sps->pic_conf_win)); + } + + // Inferred parameters + sps->log2_ctb_size = + sps->log2_min_cb_size + sps->log2_diff_max_min_coding_block_size; + sps->log2_min_pu_size = sps->log2_min_cb_size - 1; + + if (sps->log2_ctb_size > HEVC_MAX_LOG2_CTB_SIZE) + { + ni_log(NI_LOG_ERROR, "CTB size out of range: 2^%d\n", + sps->log2_ctb_size); + return -1; + } + if (sps->log2_ctb_size < 4) + { + ni_log( + NI_LOG_ERROR, + "log2_ctb_size %d differs from the bounds of any known profile\n", + sps->log2_ctb_size); + return -1; + } + + sps->ctb_width = + (sps->width + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size; + sps->ctb_height = + (sps->height + (1 << sps->log2_ctb_size) - 1) >> sps->log2_ctb_size; + sps->ctb_size = sps->ctb_width * sps->ctb_height; + + sps->min_cb_width = sps->width >> sps->log2_min_cb_size; + sps->min_cb_height = sps->height >> sps->log2_min_cb_size; + sps->min_tb_width = sps->width >> sps->log2_min_tb_size; + sps->min_tb_height = sps->height >> sps->log2_min_tb_size; + sps->min_pu_width = sps->width >> sps->log2_min_pu_size; + sps->min_pu_height = sps->height >> sps->log2_min_pu_size; + sps->tb_mask = (1 << (sps->log2_ctb_size - sps->log2_min_tb_size)) - 1; + + sps->qp_bd_offset = 6 * (sps->bit_depth - 8); + + if ((sps->width & ((1U << sps->log2_min_cb_size) - 1)) || + (sps->height & ((1U << sps->log2_min_cb_size) - 1))) + { + ni_log(NI_LOG_ERROR, "Invalid coded frame dimensions.\n"); + return -1; + } + + if (sps->max_transform_hierarchy_depth_inter > + (int)(sps->log2_ctb_size - sps->log2_min_tb_size)) + { + ni_log(NI_LOG_ERROR, + "max_transform_hierarchy_depth_inter out of range: %d\n", + sps->max_transform_hierarchy_depth_inter); + return -1; + } + if (sps->max_transform_hierarchy_depth_intra > + (int)(sps->log2_ctb_size - sps->log2_min_tb_size)) + { + ni_log(NI_LOG_ERROR, + "max_transform_hierarchy_depth_intra out of range: %d\n", + sps->max_transform_hierarchy_depth_intra); + return -1; + } + if ((sps->log2_max_trafo_size > sps->log2_ctb_size) && + (sps->log2_max_trafo_size > 5)) + { + ni_log(NI_LOG_ERROR, "max transform block size out of range: %d\n", + sps->log2_max_trafo_size); + return -1; + } + if (ni_bs_reader_get_bits_left(&br) < 0) + { + ni_log(NI_LOG_ERROR, "Overread SPS by %d bits\n", + -ni_bs_reader_get_bits_left(&br)); + return -1; + } + + return 0; +} + +// probe h.265 stream info; return 0 if stream can be decoded, -1 otherwise +int probe_h265_stream_info(ni_h265_sps_t *sps) +{ + int ret = -1; + uint8_t *buf = NULL; + uint8_t *p_buf; + uint32_t nal_size, ep3_removed = 0, vcl_nal_count = 0; + int nal_type = -1, sei_type = -1; + int sps_parsed = 0; + + if (NULL == (buf = calloc(1, NI_MAX_TX_SZ))) + { + ni_log(NI_LOG_ERROR, + "Error probe_h265_stream_info: allocate stream buf failed\n"); + goto end; + } + + reset_data_buf_pos(); + // probe at most 100 VCL before stops + while ((!sps_parsed) && vcl_nal_count < 100 && + (nal_size = find_h265_next_nalu(buf, &nal_type)) > 0) + { + p_buf = buf; + + // skip the start code + while (!(p_buf[0] == 0x00 && p_buf[1] == 0x00 && p_buf[2] == 0x01) && + (nal_size > 3)) + { + p_buf++; + nal_size--; + } + if (nal_size <= 3) + { + ni_log(NI_LOG_ERROR, + "Error probe_h265_stream_info NAL has no header\n"); + continue; + } + + p_buf += 3; // skip start code + nal_size -= 3; + ep3_removed = ni_remove_emulation_prevent_bytes(p_buf, nal_size); + nal_size -= ep3_removed; + ni_log(NI_LOG_DEBUG, "nal %d nal_size %d\n", nal_type, nal_size); + + if (HEVC_NAL_SPS == nal_type && !sps_parsed) + { + if (vcl_nal_count > 0) + { + ni_log(NI_LOG_INFO, + "Warning: %s has %d slice NAL units ahead of SPS!\n", + __func__, vcl_nal_count); + } + + if (h265_parse_sps(sps, p_buf, nal_size)) + { + ni_log(NI_LOG_ERROR, + "probe_h265_stream_info: parse_sps error\n"); + break; + } + sps_parsed = 1; + } else if (nal_type < 32) + { + vcl_nal_count++; + } + } + + reset_data_buf_pos(); + if (sps_parsed) + { + ret = 0; + } else + { + ni_log(NI_LOG_ERROR, "probing failed.\n"); + } + +end: + free(buf); + buf = NULL; + return ret; +} + +uint32_t find_vp9_next_packet(uint8_t *p_dst) +{ + uint32_t data_size; + uint32_t i = curr_found_pos; + if (i + 12 >= total_file_size) + { + ni_log(NI_LOG_DEBUG, + "%s reaching end, curr_pos %d " + "total input size %u\n", + __func__, curr_found_pos, total_file_size); + return 0; + } + /** packet structure: + * bytes 0-3: size of frame in bytes (not including the 12-byte header) + * bytes 4-11: 64-bit presentation timestamp + * bytes 12.. frame data + */ + data_size = + ((g_curr_cache_pos[i]) + (g_curr_cache_pos[i + 1] << 8) + + (g_curr_cache_pos[i + 2] << 16) + (g_curr_cache_pos[i + 3] << 24)); + ni_log(NI_LOG_DEBUG, "vp9 packet data_size %u\n", data_size); + i += 12; + curr_found_pos = i; + if (i + data_size > total_file_size) + { + data_size = total_file_size - i; + memcpy(p_dst, &g_curr_cache_pos[i], data_size); + curr_found_pos = (int)total_file_size; + return data_size; + } + + memcpy(p_dst, &g_curr_cache_pos[i], data_size); + curr_found_pos = i + data_size; // point to the start of data packet + return data_size; +} + +int vp9_parse_header(ni_vp9_header_info_t *vp9_info, uint8_t *buf, + int size_bytes) +{ + ni_bitstream_reader_t br; + ni_bitstream_reader_init(&br, buf, 8 * size_bytes); + + ni_bs_reader_skip_bits(&br, 32); // skip signature + ni_bs_reader_skip_bits(&br, 16); // skip version + vp9_info->header_length = + ni_bs_reader_get_bits(&br, 8) + (ni_bs_reader_get_bits(&br, 8) << 8); + ni_bs_reader_skip_bits(&br, 32); // skip codec fucc + vp9_info->width = + ni_bs_reader_get_bits(&br, 8) + (ni_bs_reader_get_bits(&br, 8) << 8); + vp9_info->height = + ni_bs_reader_get_bits(&br, 8) + (ni_bs_reader_get_bits(&br, 8) << 8); + vp9_info->timebase.den = ni_bs_reader_get_bits(&br, 8) + + (ni_bs_reader_get_bits(&br, 8) << 8) + + (ni_bs_reader_get_bits(&br, 8) << 16) + + (ni_bs_reader_get_bits(&br, 8) << 24); + vp9_info->timebase.num = ni_bs_reader_get_bits(&br, 8) + + (ni_bs_reader_get_bits(&br, 8) << 8) + + (ni_bs_reader_get_bits(&br, 8) << 16) + + (ni_bs_reader_get_bits(&br, 8) << 24); + + vp9_info->total_frames = ni_bs_reader_get_bits(&br, 8) + + (ni_bs_reader_get_bits(&br, 8) << 8) + + (ni_bs_reader_get_bits(&br, 8) << 16) + + (ni_bs_reader_get_bits(&br, 8) << 24); + + if (vp9_info->header_length != 32) + { + ni_log(NI_LOG_ERROR, "Parse faled: header_length %d != 32\n", + vp9_info->header_length); + return -1; + } + ni_bs_reader_skip_bits(&br, 32); // unused bytes + // here we skip frame header(12 bytes) to get profile + ni_bs_reader_skip_bits(&br, 8 * 12); + if (ni_bs_reader_get_bits(&br, 2) != 0x2) // frame marker + { + ni_log(NI_LOG_ERROR, "Invalid frame marker\n"); + return -1; + } + int profile = 0; + profile = ni_bs_reader_get_bits(&br, 1); + profile |= ni_bs_reader_get_bits(&br, 1) << 1; + if ((profile != 0) && (profile != 2)) + { + ni_log( + NI_LOG_ERROR, + "Only support profile0(yuv420,8bit) and profile2(yuv420, 10bit)\n"); + return -1; + } + vp9_info->profile = profile; + return 0; +} + +// probe vp9 stream info; return 0 if stream can be decoded, -1 otherwise +int probe_vp9_stream_info(ni_vp9_header_info_t *vp9_info) +{ + int ret = -1; + uint8_t *buf = NULL; + + if (NULL == (buf = calloc(1, 64))) + { + ni_log(NI_LOG_ERROR, + "Error probe_vp9_stream_info: allocate stream buf failed\n"); + goto end; + } + + reset_data_buf_pos(); + uint32_t size_bytes = 64; + if (32 + 12 + 1 >= total_file_size) + { + ni_log(NI_LOG_ERROR, "No frame data probed!\n"); + goto end; + } else + { + if (size_bytes > total_file_size) + size_bytes = total_file_size; + memcpy(buf, &g_curr_cache_pos[curr_found_pos], size_bytes); + } + + ret = vp9_parse_header(vp9_info, buf, size_bytes); + if (ret) + { + ni_log(NI_LOG_ERROR, "Failed to parse vp9 header info\n"); + goto end; + } + reset_data_buf_pos(); + curr_found_pos += + vp9_info->header_length; // packets data starts after ivf file header + +end: + free(buf); + buf = NULL; + return ret; +} + +int write_dmabuf_data(uint8_t *pdata, FILE *fp, int width, int height, + int format) +{ + if (!pdata || !fp) + return -1; + + switch (format) + { + case GC620_I420: + { + int write_width = width; + int write_height = height; + int plane_width; + int plane_height; + int j; + uint8_t *src = pdata; + + // write Y stride + if (fwrite(pdata, write_width * write_height, 1, fp) != 1) + { + fprintf(stderr, "Error: writing Y stride error!\n"); + fprintf(stderr, "Error: ferror rc = %d\n", ferror(fp)); + return -1; + } + + int width_aligned = (((width + 127) / 128) * 128); + int height_aligned = ((height + 1) / 2) * 2; + int luma_size = width_aligned * height_aligned; + pdata = src + luma_size; + + // write U stride + plane_height = height / 2; + plane_width = (((int)(write_width) / 2 + 127) / 128) * 128; + write_height /= 2; + write_width /= 2; + for (j = 0; j < plane_height; j++) + { + if (j < write_height && fwrite(pdata, write_width, 1, fp) != 1) + { + fprintf(stderr, + "Error: writing U stride: height %d error!\n", + height); + fprintf(stderr, "Error: ferror rc = %d\n", ferror(fp)); + return -1; + } + pdata += plane_width; + } + + int chroma_b_size; + int chroma_width_aligned = ((((width / 2) + 127) / 128) * 128); + int chroma_height_aligned = height_aligned / 2; + chroma_b_size = chroma_width_aligned * chroma_height_aligned; + + // write V stride + pdata = src + luma_size + chroma_b_size; + + for (j = 0; j < plane_height; j++) + { + if (j < write_height && fwrite(pdata, write_width, 1, fp) != 1) + { + fprintf(stderr, + "Error: writing V stride: height %d error!\n", + height); + fprintf(stderr, "Error: ferror rc = %d\n", ferror(fp)); + return -1; + } + pdata += plane_width; + } + break; + } + case GC620_RGBA8888: + { + if (fwrite(pdata, width * height * 4, 1, fp) != 1) + { + fprintf(stderr, "Error: writing rgba data error!\n"); + fprintf(stderr, "Error: ferror rc = %d\n", ferror(fp)); + return -1; + } + break; + } + case GC620_RGB888_PLANAR: + { + int stride_size = NI_VPU_ALIGN32(width * height); + for (int i = 0; i < 3; i++) + { + if (fwrite(pdata, width * height, 1, fp) != 1) + { + fprintf(stderr, "Error: writing bgrp data error!\n"); + fprintf(stderr, "Error: ferror rc = %d\n", ferror(fp)); + return -1; + } + pdata += stride_size; + } + break; + } + + default: + break; + } + + if (fflush(fp)) + { + fprintf(stderr, "Error: writing data frame flush failed! errno %d\n", + errno); + } + + return 0; +} + +int calc_frame_buffer_size(int width, int height, int format) +{ + int width_aligned = width; + int height_aligned = height; + int data_len = 0; + switch (format) + { + case GC620_I420: + { + width_aligned = ((width + 127) / 128) * 128; + height_aligned = ((height + 1) / 2) * 2; + int luma_size = width_aligned * height_aligned; + int chroma_b_size; + int chroma_r_size; + int chroma_width_aligned = (((width / 2) + 127) / 128) * 128; + int chroma_height_aligned = height_aligned / 2; + chroma_b_size = chroma_r_size = + chroma_width_aligned * chroma_height_aligned; + data_len = luma_size + chroma_b_size + chroma_r_size; + break; + } + case GC620_RGBA8888: + { + data_len = width * height * 4; + break; + } + case GC620_RGB888_PLANAR: + { + data_len = NI_VPU_ALIGN32(width * height) * 3; + break; + } + + default: + break; + } + return data_len; +} + +/*!***************************************************************************** + * \brief Write hwdl data to files. + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int write_rawvideo_data(FILE *p_file, int width, int height, int format, + ni_frame_t *p_out_frame) +{ + if (p_file && p_out_frame) + { + if (format == GC620_I420) + { + int i, j; + for (i = 0; i < 3; i++) + { + uint8_t *src = p_out_frame->p_data[i]; + int write_width = width; + int write_height = height; + int plane_width = width; + int plane_height = height; + + write_width *= 1; // bit depth 1 + + if (i == 1 || i == 2) + { + plane_height /= 2; + // U/V stride size is multiple of 128, following the calculation + // in ni_decoder_frame_buffer_alloc + plane_width = + (((int)(write_width) / 2 * 1 + 127) / 128) * 128; + write_height /= 2; + write_width /= 2; + } + + for (j = 0; j < plane_height; j++) + { + if (j < write_height && + fwrite(src, write_width, 1, p_file) != 1) + { + fprintf( + stderr, + "Error: writing data plane %d: height %d error!\n", + i, plane_height); + fprintf(stderr, "Error: ferror rc = %d\n", + ferror(p_file)); + } + src += plane_width; + } + } + } else if (format == GC620_RGBA8888) + { + uint8_t *src = p_out_frame->p_data[0]; + if (fwrite(src, width * height * 4, 1, p_file) != 1) + { + fprintf(stderr, "Error: ferror rc = %d\n", ferror(p_file)); + } + } else if (format == GC620_RGB888_PLANAR) + { + uint8_t *src; + for (int i = 0; i < 3; i++) + { + src = p_out_frame->p_data[i]; + if (fwrite(src, width * height, 1, p_file) != 1) + { + fprintf(stderr, "Error: ferror rc = %d\n", ferror(p_file)); + } + } + } + + if (fflush(p_file)) + { + fprintf(stderr, + "Error: writing data frame flush failed! errno %d\n", + errno); + } + } + return 0; +} + +#ifndef _WIN32 +/*!***************************************************************************** + * \brief Read dmabuf data(4k aligned) to cpu for test. + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int read_from_dmabuf(ni_session_context_t *p_ctx, niFrameSurface1_t *p_surface, + disp_buffer_t *disp, int format, FILE *fp) +{ + if (!disp) + { + printf("Error: Invalid input params\n"); + return -1; + } + int ret = 0; + int data_len = calc_frame_buffer_size(p_surface->ui16width, + p_surface->ui16height, format); + data_len = (data_len + 4095) & ~4095; // must be 4096 bytes aligned + if (!data_len) + { + printf("Error: read size is 0!\n"); + return -1; + } + + disp->fd = -1; + disp->mmap_data = MAP_FAILED; + disp->len = data_len; + disp->bar = 4; + + ret = ni_scaler_p2p_frame_acquire(p_ctx, p_surface, data_len); + if (ret != 0) + { + printf("failed to export dma buf\n"); + return -1; + } + disp->fd = p_surface->dma_buf_fd; + + //mmap + disp->mmap_data = + mmap(0, data_len, PROT_READ | PROT_WRITE, MAP_SHARED, disp->fd, 0); + if (disp->mmap_data == MAP_FAILED) + { + printf("failed to mmap dmabuf: %s\n", strerror(errno)); + return -1; + } + + uint8_t *data = NULL; + ret = posix_memalign((void **)&data, sysconf(_SC_PAGESIZE), disp->len); + if (ret) + { + printf("failed to allocate memory\n"); + return -1; + } + disp->data = data; + + // write data to output file + uint8_t *pdata = NULL; + pdata = malloc(data_len); + if (!pdata) + { + printf("failed to allocate data\n"); + if (fp) + fclose(fp); + free(pdata); + return -1; + } + + struct netint_iocmd_issue_request uis; + memset(&uis, 0, sizeof(uis)); + uis.fd = disp->fd; + uis.data = disp->data; + uis.len = disp->len; + uis.dir = NI_DMABUF_READ_FROM_DEVICE; + memset(disp->data, 0, disp->len); + ret = ioctl(p_ctx->netint_fd, NETINT_IOCTL_ISSUE_REQ, &uis); + if (ret < 0) + { + printf("failed to send req: %s\n", strerror(errno)); + if (fp) + fclose(fp); + free(pdata); + return -1; + } + + // poll to check if read complete + struct pollfd pfds[1]; + pfds[0].fd = disp->fd; + pfds[0].events = POLLOUT; + pfds[0].revents = 0; + ret = poll(pfds, 1, -1); + if (ret < 0) + { + printf("failed to poll\n"); + if (fp) + fclose(fp); + free(pdata); + return -1; + } + + ni_log(NI_LOG_DEBUG, "data ox%lx, data_len %u\n", (unsigned long)disp->data, + data_len); + memcpy(pdata, disp->data, data_len); + + if (fp) + { + if (0 != + write_dmabuf_data(pdata, fp, p_surface->ui16width, + p_surface->ui16height, format)) + { + printf("failed to write file\n"); + if (fp) + fclose(fp); + free(pdata); + return -1; + } + free(pdata); + } + + return 0; +} +#endif + +/*!***************************************************************************** + * \brief Download hw frames by HwDesc. + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int hwdl_frame(ni_session_context_t *p_ctx, + ni_session_data_io_t *p_session_data, ni_frame_t *p_src_frame, + int output_format) +{ + niFrameSurface1_t *src_surf = (niFrameSurface1_t *)(p_src_frame->p_data[3]); + int ret = 0; + int pixel_format; + + switch (output_format) + { + case GC620_I420: + pixel_format = NI_PIX_FMT_YUV420P; + break; + case GC620_RGBA8888: + pixel_format = NI_PIX_FMT_RGBA; + break; + case GC620_RGB888_PLANAR: + pixel_format = NI_PIX_FMT_BGRP; + break; + default: + ni_log(NI_LOG_ERROR, "Pixel format not supported.\n"); + return NI_RETCODE_INVALID_PARAM; + } + + ret = ni_frame_buffer_alloc_dl(&(p_session_data->data.frame), + src_surf->ui16width, src_surf->ui16height, + pixel_format); + + if (ret != NI_RETCODE_SUCCESS) + { + return NI_RETCODE_ERROR_MEM_ALOC; + } + + p_ctx->is_auto_dl = false; + ret = ni_device_session_hwdl(p_ctx, p_session_data, src_surf); + if (ret <= 0) + { + ni_frame_buffer_free(&p_session_data->data.frame); + return ret; + } + return ret; +} + +/*!***************************************************************************** + * \brief Send decoder input data + * + * \param + * + * \return + ******************************************************************************/ +ni_retcode_t decoder_send_data(ni_session_context_t *p_dec_ctx, + ni_session_data_io_t *p_in_data, int sos_flag, + int input_video_width, int input_video_height, + int pkt_size, unsigned int file_size, + unsigned long *total_bytes_sent, int print_time, + device_state_t *p_device_state, + void *stream_info) +{ + static uint8_t tmp_buf[NI_MAX_TX_SZ] = {0}; + uint8_t *tmp_buf_ptr = tmp_buf; + int packet_size = pkt_size; + // int chunk_size = 0; + uint32_t frame_pkt_size = 0, nal_size; + int nal_type = -1; + int tx_size = 0; + uint32_t send_size = 0; + int new_packet = 0; + int saved_prev_size = 0; + int32_t frame_num = -1, curr_frame_num; + unsigned int first_mb_in_slice = 0; + ni_packet_t *p_in_pkt = &(p_in_data->data.packet); + ni_retcode_t retval = NI_RETCODE_SUCCESS; + + ni_log(NI_LOG_DEBUG, "===> decoder_send_data <===\n"); + + if (p_device_state->dec_eos_sent) + { + ni_log(NI_LOG_DEBUG, "decoder_send_data: ALL data (incl. eos) sent " + "already!\n"); + LRETURN; + } + + // TBD Demo: decoder flush at 200th packet +#if 0 + if (200 == p_dec_ctx->pkt_num) + { + if (NI_RETCODE_SUCCESS != ni_device_dec_session_flush(p_dec_ctx)) + { + ni_log(NI_LOG_ERROR, "decoder_send_data: mid-flush failed!\n"); + exit(-1); + } + } +#endif + + if (0 == p_in_pkt->data_len) + { + memset(p_in_pkt, 0, sizeof(ni_packet_t)); + + if (NI_CODEC_FORMAT_H264 == p_dec_ctx->codec_format) + { + ni_h264_sps_t *sps; + sps = (ni_h264_sps_t *)stream_info; + // send whole encoded packet which ends with a slice NAL + while ((nal_size = find_h264_next_nalu(tmp_buf_ptr, &nal_type)) > 0) + { + frame_pkt_size += nal_size; + tmp_buf_ptr += nal_size; + ni_log(NI_LOG_DEBUG, "%s nal %d nal_size %d\n", __func__, + nal_type, nal_size); + + // save parsed out sps/pps as stream headers in the decode session + if (H264_NAL_PPS == nal_type) + { + if (NI_RETCODE_SUCCESS != + ni_device_dec_session_save_hdrs(p_dec_ctx, tmp_buf, + frame_pkt_size)) + { + ni_log(NI_LOG_ERROR, "decoder_send_data: save_hdr failed!\n"); + } + } + + if (H264_NAL_SLICE == nal_type || + H264_NAL_IDR_SLICE == nal_type) + { + if (!parse_h264_slice_header(tmp_buf_ptr - nal_size, + nal_size, sps, &curr_frame_num, + &first_mb_in_slice)) + { + if (-1 == frame_num) + { + // first slice, continue to check + frame_num = curr_frame_num; + } else if (curr_frame_num != frame_num || + 0 == first_mb_in_slice) + { + // this slice has diff. frame_num or first_mb_in_slice addr is + // 0: not the same frame and return + rewind_data_buf_pos_by(nal_size); + frame_pkt_size -= nal_size; + break; + } + // this slice is in the same frame, so continue to check and see + // if there is more + } else + { + ni_log(NI_LOG_ERROR, + "decoder_send_data: parse_slice_header error " + "NAL type %d size %u, continue\n", + nal_type, nal_size); + } + } else if (-1 != frame_num) + { + // already got a slice and this is non-slice NAL: return + rewind_data_buf_pos_by(nal_size); + frame_pkt_size -= nal_size; + break; + } + // otherwise continue until a slice is found + } // while there is still NAL + } else if (NI_CODEC_FORMAT_H265 == p_dec_ctx->codec_format) + { + while ((nal_size = find_h265_next_nalu(tmp_buf_ptr, &nal_type)) > 0) + { + frame_pkt_size += nal_size; + tmp_buf_ptr += nal_size; + ni_log(NI_LOG_DEBUG, "%s nal_type %d nal_size %d\n", __func__, + nal_type, nal_size); + + if (nal_type == HEVC_NAL_VPS || nal_type == HEVC_NAL_SPS || + nal_type == HEVC_NAL_PPS) // save vps, sps, pps + { + if (nal_type == 32 && p_dec_ctx->prev_size > 0) + { + // sequence change situation, replace previous p_leftover with new headers + p_dec_ctx->prev_size = 0; + } + // copy the nal to the end of p_leftover + memcpy(p_dec_ctx->p_leftover + p_dec_ctx->prev_size, + tmp_buf_ptr - nal_size, nal_size); + p_dec_ctx->prev_size += nal_size; + } + + if (nal_type >= 0 && nal_type <= 23) // vcl units + { + ni_log(NI_LOG_DEBUG, "%s send vcl_nal %d nal_size %d\n", + __func__, nal_type, nal_size); + break; + } + } + } else if (NI_CODEC_FORMAT_VP9 == p_dec_ctx->codec_format) + { + while ((packet_size = find_vp9_next_packet(tmp_buf_ptr)) > 0) + { + frame_pkt_size += packet_size; + ni_log(NI_LOG_DEBUG, "%s vp9 packet_size %d\n", __func__, + packet_size); + break; + } + } else + { + frame_pkt_size = read_next_chunk(tmp_buf, packet_size); + // chunk_size = frame_pkt_size; + } + ni_log(NI_LOG_DEBUG, "decoder_send_data * frame_pkt_size %d\n", + frame_pkt_size); + + p_in_pkt->p_data = NULL; + p_in_pkt->data_len = frame_pkt_size; + + if (frame_pkt_size + p_dec_ctx->prev_size > 0) + { + ni_packet_buffer_alloc(p_in_pkt, + (int)frame_pkt_size + p_dec_ctx->prev_size); + } + + new_packet = 1; + send_size = frame_pkt_size + p_dec_ctx->prev_size; + saved_prev_size = p_dec_ctx->prev_size; + } else + { + send_size = p_in_pkt->data_len; + } + + p_in_pkt->start_of_stream = sos_flag; + p_in_pkt->end_of_stream = 0; + p_in_pkt->video_width = input_video_width; + p_in_pkt->video_height = input_video_height; + + if (send_size == 0) + { + if (new_packet) + { + send_size = + ni_packet_copy(p_in_pkt->p_data, tmp_buf, 0, + p_dec_ctx->p_leftover, &p_dec_ctx->prev_size); + // todo save offset + } + p_in_pkt->data_len = send_size; + + p_in_pkt->end_of_stream = 1; + printf("Sending p_last packet (size %u) + eos\n", p_in_pkt->data_len); + } else + { + if (new_packet) + { + send_size = + ni_packet_copy(p_in_pkt->p_data, tmp_buf, frame_pkt_size, + p_dec_ctx->p_leftover, &p_dec_ctx->prev_size); + // todo: update offset with send_size + // p_in_pkt->data_len is the actual packet size to be sent to decoder + p_in_pkt->data_len += saved_prev_size; + } + } + + tx_size = + ni_device_session_write(p_dec_ctx, p_in_data, NI_DEVICE_TYPE_DECODER); + + if (tx_size < 0) + { + // Error + fprintf(stderr, "Error: sending data error. rc:%d\n", tx_size); + retval = NI_RETCODE_FAILURE; + LRETURN; + } else if (tx_size == 0) + { + ni_log(NI_LOG_DEBUG, "0 byte sent this time, sleep and will re-try.\n"); + ni_usleep(10000); + } else if ((uint32_t)tx_size < send_size) + { + if (print_time) + { + //printf("Sent %d < %d , re-try next time ?\n", tx_size, send_size); + } + } + + *total_bytes_sent += tx_size; + + if (p_dec_ctx->ready_to_close) + { + p_device_state->dec_eos_sent = 1; + } + + if (print_time) + { + printf("decoder_send_data: success, total sent: %lu\n", + *total_bytes_sent); + } + + if (tx_size > 0) { ni_log(NI_LOG_DEBUG, "decoder_send_data: reset packet_buffer.\n"); ni_packet_buffer_free(p_in_pkt); @@ -1842,6 +3730,7 @@ void prep_reconf_demo_data(ni_session_context_t *p_enc_ctx, ni_frame_t *frame) g_reconfigCount++; } break; + */ case XCODER_TEST_RECONF_VUI_HRD: if (p_enc_ctx->frame_num == api_param->reconf_hash[g_reconfigCount][0]) @@ -1860,13 +3749,14 @@ void prep_reconf_demo_data(ni_session_context_t *p_enc_ctx, ni_frame_t *frame) api_param->reconf_hash[g_reconfigCount][5]; p_enc_ctx->enc_change_params->aspectRatioHeight = api_param->reconf_hash[g_reconfigCount][6]; + p_enc_ctx->enc_change_params->videoFullRange = + api_param->reconf_hash[g_reconfigCount][7]; // frame reconf_len needs to be set here frame->reconf_len = sizeof(ni_encoder_change_params_t); g_reconfigCount++; } break; - */ case XCODER_TEST_RECONF_LONG_TERM_REF: // the reconf file data line format for this is: // :useCurSrcAsLongtermPic,useLongtermRef where @@ -2016,6 +3906,42 @@ void prep_reconf_demo_data(ni_session_context_t *p_enc_ctx, ni_frame_t *frame) g_reconfigCount++; } break; + case XCODER_TEST_RECONF_VUI_HRD_API: + if (p_enc_ctx->frame_num == + api_param->reconf_hash[g_reconfigCount][0]) + { + ni_vui_hrd_t vui; + vui.colorDescPresent = + (uint8_t)api_param->reconf_hash[g_reconfigCount][1]; + vui.colorPrimaries = + (uint8_t)api_param->reconf_hash[g_reconfigCount][2]; + vui.colorTrc = + (uint8_t)api_param->reconf_hash[g_reconfigCount][3]; + vui.colorSpace = + (uint8_t)api_param->reconf_hash[g_reconfigCount][4]; + vui.aspectRatioWidth = + (uint8_t)api_param->reconf_hash[g_reconfigCount][5]; + vui.aspectRatioHeight = + (uint8_t)api_param->reconf_hash[g_reconfigCount][6]; + vui.videoFullRange = + (uint8_t)api_param->reconf_hash[g_reconfigCount][7]; + + ni_reconfig_vui(p_enc_ctx, &vui); + ni_log(NI_LOG_DEBUG, "%s(): frame #%lu API reconfig VUI HRD " + "colorDescPresent %d colorPrimaries %d " + "colorTrc %d colorSpace %d aspectRatioWidth %d " + "aspectRatioHeight %d videoFullRange %d\n", + __func__, p_enc_ctx->frame_num, + api_param->reconf_hash[g_reconfigCount][1], + api_param->reconf_hash[g_reconfigCount][2], + api_param->reconf_hash[g_reconfigCount][3], + api_param->reconf_hash[g_reconfigCount][4], + api_param->reconf_hash[g_reconfigCount][5], + api_param->reconf_hash[g_reconfigCount][6], + api_param->reconf_hash[g_reconfigCount][7]); + g_reconfigCount++; + } + break; case XCODER_TEST_RECONF_LTR_API: if (p_enc_ctx->frame_num == api_param->reconf_hash[g_reconfigCount][0]) @@ -2195,7 +4121,11 @@ int upload_send_data_get_desc( retval = ni_device_session_hwup(p_upl_ctx, p_swin_data, dst_surf); if (retval < 0) { - fprintf(stderr, "Error: failed ni_device_session_hwup():%d\n", retval); + fprintf(stderr, "Error: failed ni_device_session_hwup():%d, frameNum %u\n", + retval, number_of_frames); + //file was read so reset read pointer and try again + data_left_size += chunk_size; + lseek(pfs, chunk_size * number_of_frames, SEEK_SET); return -1; } else { @@ -2232,7 +4162,7 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, ni_session_data_io_t *p_in_data, int sos_flag, int input_video_width, int input_video_height, int pfs, unsigned int file_size, unsigned long *bytes_sent, - device_state_t *p_device_state) + device_state_t *p_device_state, int bit_depth, int is_last_input) { static uint8_t tmp_buf[MAX_YUV_FRAME_SIZE]; volatile static int started = 0; @@ -2251,11 +4181,17 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, ni_log(NI_LOG_DEBUG, "===> encoder_send_data <===\n"); + if (p_device_state->enc_seq_change == 1) + { + ni_log(NI_LOG_DEBUG, "encoder_send_data: Sequence Change - waiting for previous session to end\n"); + return NI_TEST_RETCODE_SUCCESS; + } + if (p_device_state->enc_eos_sent == 1) { ni_log(NI_LOG_DEBUG, "encoder_send_data: ALL data (incl. eos) sent " "already!\n"); - return 0; + return NI_TEST_RETCODE_SUCCESS; } if (need_to_resend) @@ -2264,7 +4200,7 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, } p_in_frame->start_of_stream = 0; - if (!started) + if (!started || p_enc_ctx->session_run_state == SESSION_RUN_STATE_SEQ_CHANGE_OPENING) { started = 1; p_in_frame->start_of_stream = 1; @@ -2274,7 +4210,7 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, p_in_frame->video_width = input_video_width; p_in_frame->video_height = input_video_height; - + // reset encoder change data buffer memset(p_enc_ctx->enc_change_params, 0, sizeof(ni_encoder_change_params_t)); @@ -2283,6 +4219,50 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, p_in_frame->roi_len = 0; p_in_frame->reconf_len = 0; p_in_frame->sei_total_len = 0; + + /* // currently xcoder demo app does not support semi-planar - following is for future reference + int is_planar = 1; // hard coded to planar in demo + p_in_frame->pixel_format = + (is_planar ? NI_PIX_FMT_YUV420P : NI_PIX_FMT_NV12); + if (10 == bit_depth) + { + p_in_frame->pixel_format = + (is_planar ? NI_PIX_FMT_YUV420P10LE : NI_PIX_FMT_P010LE); + } + */ + p_in_frame->pixel_format = NI_PIX_FMT_YUV420P; + if (10 == bit_depth) + { + p_in_frame->pixel_format = NI_PIX_FMT_YUV420P10LE; + } + + if (!p_in_frame->start_of_stream && + (p_in_frame->video_width != p_enc_ctx->actual_video_width || + p_in_frame->video_height != p_enc_ctx->active_video_height || + p_in_frame->pixel_format != p_enc_ctx->pixel_format)) + { + ni_log(NI_LOG_INFO, + "encoder_send_data: resolution change %dx%d " + "-> %dx%d or pixel format change %d -> %d\n", + p_enc_ctx->actual_video_width, p_enc_ctx->active_video_height, + p_in_frame->video_width, p_in_frame->video_height, + p_enc_ctx->pixel_format, p_in_frame->pixel_format); + + // change run state + p_enc_ctx->session_run_state = + SESSION_RUN_STATE_SEQ_CHANGE_DRAINING; + + ni_log(NI_LOG_DEBUG, + "encoder_send_data: session_run_state change to %d \n", + p_enc_ctx->session_run_state); + + // queue frame not needed because frame info stored in p_in_frame + // (customer application may queue frame here) + + // send EOS + p_in_frame->end_of_stream = 1; + goto send_frame; + } // collect encode reconfig and demo info and save them in the data holder // struct, to be used in the aux data prep and copy later @@ -2352,7 +4332,7 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, if (!p_in_frame->p_data[0]) { fprintf(stderr, "Error: could not allocate YUV frame buffer!"); - return -1; + return NI_TEST_RETCODE_FAILURE; } ni_log(NI_LOG_DEBUG, @@ -2429,7 +4409,7 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, if (chunk_size == -1) { fprintf(stderr, "Error: could not read file!"); - return -1; + return NI_TEST_RETCODE_FAILURE; } } else { @@ -2440,7 +4420,7 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, if (chunk_size == -1) { fprintf(stderr, "Error: could not read file!"); - return -1; + return NI_TEST_RETCODE_FAILURE; } // YUV part of the encoder input data layout @@ -2452,12 +4432,6 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, dst_stride, dst_height_aligned, src_stride, src_height); } - if (chunk_size == 0) - { - p_in_frame->end_of_stream = 1; - ni_log(NI_LOG_DEBUG, "encoder_send_data: read chunk size 0, eos!\n"); - } - // auxiliary data part of the encoder input data layout ni_enc_copy_aux_data(p_enc_ctx, p_in_frame, &dec_frame, p_enc_ctx->codec_format, mdcv_data, cll_data, cc_data, @@ -2466,6 +4440,20 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, // clean up data storage ni_frame_buffer_free(&dec_frame); + if (chunk_size == 0) + { + if (is_last_input) + { + p_in_frame->end_of_stream = 1; + ni_log(NI_LOG_DEBUG, "encoder_send_data: read chunk size 0, eos!\n"); + } + else + { + ni_log(NI_LOG_DEBUG, "encoder_send_data: exit to get next input\n"); + return NI_TEST_RETCODE_NEXT_INPUT; + } + } + send_frame: oneSent = ni_device_session_write(p_enc_ctx, p_in_data, NI_DEVICE_TYPE_ENCODER); @@ -2474,13 +4462,14 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, fprintf(stderr, "Error: failed ni_device_session_write() for encoder\n"); need_to_resend = 1; - return -1; + return NI_TEST_RETCODE_FAILURE; } else if (oneSent == 0 && !p_enc_ctx->ready_to_close) { need_to_resend = 1; } else { need_to_resend = 0; + number_of_frames++; *bytes_sent += p_in_frame->data_len[0] + p_in_frame->data_len[1] + p_in_frame->data_len[2] + p_in_frame->data_len[3]; @@ -2488,14 +4477,30 @@ int encoder_send_data(ni_session_context_t *p_enc_ctx, *bytes_sent); ni_log(NI_LOG_DEBUG, "encoder_send_data: success\n"); - + if (p_enc_ctx->ready_to_close) { - p_device_state->enc_eos_sent = 1; + if (p_enc_ctx->session_run_state == SESSION_RUN_STATE_SEQ_CHANGE_DRAINING) + { + p_device_state->enc_seq_change = 1; + } + else + { + p_device_state->enc_eos_sent = 1; + } + } + + if (p_enc_ctx->session_run_state == SESSION_RUN_STATE_SEQ_CHANGE_OPENING) + { + p_enc_ctx->session_run_state = SESSION_RUN_STATE_NORMAL; + + ni_log(NI_LOG_DEBUG, + "encoder_send_data: session_run_state change to %d \n", + p_enc_ctx->session_run_state); } } - return 0; + return NI_TEST_RETCODE_SUCCESS; } /******************************************************************************* @@ -2905,7 +4910,7 @@ int scan_and_clean_hwdescriptors(niFrameSurface1_t *p_pool_tracker) { int i; int recycled = 0; - for (i = 0; i < NI_MAX_HWDESC_FRAME_INDEX; i++) + for (i = 0; i < NI_MAX_DR_HWDESC_FRAME_INDEX; i++) { if (p_pool_tracker[i].ui16FrameIdx) { @@ -2919,6 +4924,119 @@ int scan_and_clean_hwdescriptors(niFrameSurface1_t *p_pool_tracker) return recycled; } +/*!***************************************************************************** + * \brief Reopen or reconfig encoder upon sequence change + * + * \param + * + * \return 0 - success got packet + * 1 - received eos + * 2 - got nothing, need retry + * -1 - failure + ******************************************************************************/ +int encoder_reinit_session(ni_session_context_t *p_enc_ctx, + ni_session_data_io_t *p_in_data, + ni_session_data_io_t *p_out_data) +{ + int ret = NI_TEST_RETCODE_SUCCESS; + int new_stride, ori_stride; + bool bIsSmallPicture = false; + ni_frame_t *p_buffered_frame = &(p_in_data->data.frame); + ni_xcoder_params_t *p_api_param = (ni_xcoder_params_t *)p_enc_ctx->p_session_config; + int new_width, new_height; + int new_bit_depth, new_bit_depth_factor; + + new_width = p_buffered_frame->video_width; + new_height = p_buffered_frame->video_height; + + switch (p_buffered_frame->pixel_format) + { + case NI_PIX_FMT_YUV420P: + case NI_PIX_FMT_NV12: + new_bit_depth = 8; + new_bit_depth_factor = 1; + break; + case NI_PIX_FMT_YUV420P10LE: + case NI_PIX_FMT_P010LE: + new_bit_depth = 10; + new_bit_depth_factor = 2; + break; + default: + new_bit_depth = 8; + new_bit_depth_factor = 1; + break; + } + + new_stride = NI_ALIGN(new_width, 128); + ori_stride = NI_ALIGN(p_enc_ctx->ori_width, 128); + if (p_api_param->cfg_enc_params.lookAheadDepth) { + ni_log(NI_LOG_DEBUG, "xcoder_encode_reinit 2-pass " + "lookaheadDepth %d\n", + p_api_param->cfg_enc_params.lookAheadDepth); + if ((new_width < NI_2PASS_ENCODE_MIN_WIDTH) || + (new_height < NI_2PASS_ENCODE_MIN_HEIGHT)) { + bIsSmallPicture = true; + } + } + else { + if ((new_width < NI_MIN_WIDTH) || + (new_height < NI_MIN_HEIGHT)) { + bIsSmallPicture = true; + } + } + + if (p_api_param->cfg_enc_params.multicoreJointMode) { + ni_log(NI_LOG_DEBUG, "xcoder_encode_reinit multicore " + "joint mode\n"); + if ((new_width < NI_MULTICORE_ENCODE_MIN_WIDTH) || + (new_height < NI_MULTICORE_ENCODE_MIN_HEIGHT)) { + bIsSmallPicture = true; + } + } + + ni_log(NI_LOG_DEBUG, "xcoder_encode_reinit resolution: %dx%d->%dx%d " + "pix fmt: %d->%d bIsSmallPicture %d codec %d\n", + ori_stride, p_enc_ctx->ori_height, new_stride, new_height, + p_enc_ctx->ori_pix_fmt, p_buffered_frame->pixel_format, + bIsSmallPicture, + p_enc_ctx->codec_format); + + // fast sequence change without close / open only if new resolution < original resolution + if ((ori_stride*p_enc_ctx->ori_height < new_stride*new_height) || + (p_enc_ctx->ori_pix_fmt != p_buffered_frame->pixel_format) || + bIsSmallPicture || + (p_enc_ctx->codec_format == NI_CODEC_FORMAT_JPEG)) { + ni_log(NI_LOG_INFO, "XCoder encode sequence change by close / re-open session\n"); + encoder_close_session(p_enc_ctx, p_in_data, p_out_data); + ret = encoder_init_session(p_enc_ctx, p_in_data, p_out_data, new_width, new_height, new_bit_depth); + } + else { + if (p_enc_ctx->codec_format == NI_CODEC_FORMAT_AV1) { + // AV1 8x8 alignment HW limitation is now worked around by FW cropping input resolution + if (new_width % NI_PARAM_AV1_ALIGN_WIDTH_HEIGHT) + ni_log(NI_LOG_ERROR, + "resolution change: AV1 Picture Width not aligned to %d - picture will be cropped\n", + NI_PARAM_AV1_ALIGN_WIDTH_HEIGHT); + + if (new_height % NI_PARAM_AV1_ALIGN_WIDTH_HEIGHT) + ni_log(NI_LOG_ERROR, + "resolution change: AV1 Picture Height not aligned to %d - picture will be cropped\n", + NI_PARAM_AV1_ALIGN_WIDTH_HEIGHT); + } + ni_log(NI_LOG_INFO, "XCoder encode sequence change by re-config session (fast path)\n"); + ret = encoder_sequence_change(p_enc_ctx, p_in_data, p_out_data, new_width, new_height, new_bit_depth_factor); + } + + // set run state + p_enc_ctx->session_run_state = SESSION_RUN_STATE_SEQ_CHANGE_OPENING; // this state is referenced when sending first frame after sequence change + + ni_log(NI_LOG_DEBUG, + "encoder_reinit_session: session_run_state change to %d \n", + p_enc_ctx->session_run_state); + + return ret; +} + /*!***************************************************************************** * \brief Receive output data from encoder * @@ -2933,14 +5051,15 @@ int encoder_receive_data(ni_session_context_t *p_enc_ctx, ni_session_data_io_t *p_out_data, int output_video_width, int output_video_height, FILE *p_file, unsigned long long *total_bytes_received, - int print_time) + int print_time, + ni_session_data_io_t *p_in_data) //p_in_data is passed in to specify new frame resolution upon sequence change { int packet_size = NI_MAX_TX_SZ; int rc = 0; int end_flag = 0; int rx_size = 0; ni_packet_t *p_out_pkt = &(p_out_data->data.packet); - int meta_size = NI_FW_ENC_BITSTREAM_META_DATA_SIZE; + int meta_size = p_enc_ctx->meta_size; ni_log(NI_LOG_DEBUG, "===> encoder_receive_data <===\n"); @@ -2948,14 +5067,14 @@ int encoder_receive_data(ni_session_context_t *p_enc_ctx, NI_INVALID_DEVICE_HANDLE == p_enc_ctx->blk_io_handle) { ni_log(NI_LOG_DEBUG, "encode session not opened yet, return\n"); - return 0; + return NI_TEST_RETCODE_SUCCESS; } rc = ni_packet_buffer_alloc(p_out_pkt, packet_size); if (rc != NI_RETCODE_SUCCESS) { fprintf(stderr, "Error: malloc packet failed, ret = %d!\n", rc); - return -1; + return NI_TEST_RETCODE_FAILURE; } receive_data: @@ -2992,13 +5111,37 @@ int encoder_receive_data(ni_session_context_t *p_enc_ctx, { fprintf(stderr, "Error: received %d bytes, <= metadata size %d!\n", rx_size, meta_size); - return -1; + return NI_TEST_RETCODE_FAILURE; } else if (!end_flag && ((ni_xcoder_params_t *)(p_enc_ctx->p_session_config)) ->low_delay_mode) { ni_log(NI_LOG_DEBUG, "low delay mode and NO pkt, keep reading ..\n"); goto receive_data; + } else + { + if (end_flag) + { + if (SESSION_RUN_STATE_SEQ_CHANGE_DRAINING == + p_enc_ctx->session_run_state) + { + // after sequence change completes, reset codec state + ni_log(NI_LOG_INFO, "encoder_receive_data: sequence " + "change completed, return SEQ_CHANGE_DONE and will reopen " + "or reconfig codec!\n"); + + rc = encoder_reinit_session(p_enc_ctx, p_in_data, p_out_data); + ni_log(NI_LOG_TRACE, "encoder_receive_data: encoder_reinit_session ret %d\n", rc); + if (rc == NI_RETCODE_SUCCESS) + { + return NI_TEST_RETCODE_SEQ_CHANGE_DONE; + } + else + { + return NI_TEST_RETCODE_FAILURE; + } + } + } } if (print_time) @@ -3017,15 +5160,15 @@ int encoder_receive_data(ni_session_context_t *p_enc_ctx, if (end_flag) { printf("Encoder Receiving done.\n"); - return 1; + return NI_TEST_RETCODE_END_OF_STREAM; } else if (0 == rx_size) { - return 2; + return NI_TEST_RETCODE_EAGAIN; } ni_log(NI_LOG_DEBUG, "encoder_receive_data: success\n"); - return 0; + return NI_TEST_RETCODE_SUCCESS; } /*!***************************************************************************** @@ -3135,11 +5278,21 @@ int encoder_open_session( p_enc_ctx->src_bit_depth = src_bit_depth; p_enc_ctx->src_endian = NI_FRAME_LITTLE_ENDIAN; p_enc_ctx->bit_depth_factor = 1; + p_enc_ctx->pixel_format = + (is_planar ? NI_PIX_FMT_YUV420P : NI_PIX_FMT_NV12); if (10 == p_enc_ctx->src_bit_depth) { p_enc_ctx->bit_depth_factor = 2; + p_enc_ctx->pixel_format = + (is_planar ? NI_PIX_FMT_YUV420P10LE : NI_PIX_FMT_P010LE); } + // original resolution this stream started with, this is used by encoder sequence change + p_enc_ctx->ori_width = width; + p_enc_ctx->ori_height = height; + p_enc_ctx->ori_bit_depth_factor = p_enc_ctx->bit_depth_factor; + p_enc_ctx->ori_pix_fmt = p_enc_ctx->pixel_format; + int linesize_aligned = width; if (linesize_aligned < NI_MIN_WIDTH) { @@ -3172,7 +5325,9 @@ int encoder_open_session( // encoder config p_enc_params->cfg_enc_params.colorDescPresent = 0; // ToDo: when to enable - if (color_primaries != 0) + if ((color_primaries != NI_COL_PRI_UNSPECIFIED) || + (color_space != NI_COL_SPC_UNSPECIFIED) || + (color_trc != NI_COL_TRC_UNSPECIFIED)) { p_enc_params->cfg_enc_params.colorDescPresent = 1; } @@ -3186,6 +5341,8 @@ int encoder_open_session( // default planar encoder input data; ToDo: HW frames p_enc_params->cfg_enc_params.planar = is_planar; + p_enc_params->video_full_range_flag = video_full_range_flag; + ret = ni_device_session_open(p_enc_ctx, NI_DEVICE_TYPE_ENCODER); if (ret < 0) { @@ -3205,6 +5362,108 @@ int encoder_open_session( return ret; } +/*!***************************************************************************** + * \brief encoder session close + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int encoder_close_session(ni_session_context_t *p_enc_ctx, + ni_session_data_io_t *p_in_data, + ni_session_data_io_t *p_out_data) +{ + int ret = 0; + ni_device_session_close(p_enc_ctx, 1, NI_DEVICE_TYPE_ENCODER); + + ni_log(NI_LOG_DEBUG, "encoder_close_session - close encoder blk_io_handle %d device_handle %d\n", p_enc_ctx->blk_io_handle, p_enc_ctx->device_handle); +#ifdef _WIN32 + ni_device_close(p_enc_ctx->device_handle); +#elif __linux__ + ni_device_close(p_enc_ctx->device_handle); + ni_device_close(p_enc_ctx->blk_io_handle); +#endif + + if (p_enc_ctx->codec_format == NI_CODEC_FORMAT_AV1 && + p_out_data->data.packet.av1_buffer_index) + { + ni_packet_buffer_free_av1(&(p_out_data->data.packet)); + } + ni_frame_buffer_free(&(p_in_data->data.frame)); + ni_packet_buffer_free(&(p_out_data->data.packet)); + return ret; +} + +/*!***************************************************************************** + * \brief encoder session init + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int encoder_init_session(ni_session_context_t *p_enc_ctx, + ni_session_data_io_t *p_in_data, + ni_session_data_io_t *p_out_data, + int arg_width, + int arg_height, + int bit_depth) +{ + int ret = 0; + ni_xcoder_params_t *p_api_param = (ni_xcoder_params_t *)p_enc_ctx->p_session_config; + + ni_log(NI_LOG_DEBUG, "XCoder encode sequence change (re-open): session_run_state %d\n", p_enc_ctx->session_run_state); + + // for encode from YUV, use all the parameters specified by user + ret = encoder_open_session( + p_enc_ctx, p_enc_ctx->codec_format, p_enc_ctx->hw_id, p_api_param, bit_depth, + arg_width, arg_height, NULL, p_api_param->color_primaries, + p_api_param->color_transfer_characteristic, p_api_param->color_space, + p_api_param->video_full_range_flag, p_api_param->sar_num, p_api_param->sar_denom, + 1); + if (NI_RETCODE_SUCCESS != ret) + { + ni_log(NI_LOG_ERROR, "Failed to Re-open Encoder Session upon Sequence Change (status = %d)\n", ret); + return ret; + } + + p_out_data->data.packet.end_of_stream = 0; + p_in_data->data.frame.start_of_stream = 1; + return ret; +} + +int encoder_sequence_change(ni_session_context_t *p_enc_ctx, + ni_session_data_io_t *p_in_data, + ni_session_data_io_t *p_out_data, + int width, + int height, + int bit_depth_factor) +{ + ni_retcode_t ret = 0; + + ni_log(NI_LOG_DEBUG, "XCoder encode sequence change (reconfig): session_run_state %d\n", p_enc_ctx->session_run_state); + + ret = ni_device_session_sequence_change(p_enc_ctx, width, height, bit_depth_factor, NI_DEVICE_TYPE_ENCODER); + + if (NI_RETCODE_SUCCESS != ret) + { + ni_log(NI_LOG_ERROR, "Failed to send Sequence Change to Encoder Session (status = %d)\n", ret); + return ret; + } + + // update session context + p_enc_ctx->bit_depth_factor = bit_depth_factor; + p_enc_ctx->src_bit_depth = (bit_depth_factor == 1) ? 8 : 10; + // xcoder demo only support little endian (for 10-bit pixel format) + p_enc_ctx->src_endian = NI_FRAME_LITTLE_ENDIAN; + p_enc_ctx->ready_to_close = 0; + p_enc_ctx->frame_num = 0; // need to reset frame_num because pkt_num is set to 1 when header received after sequnce change, and low delay mode compares frame_num and pkt_num + p_enc_ctx->pkt_num = 0; // also need to reset pkt_num because before header received, pkt_num > frame_num will also cause low delay mode stuck + p_enc_ctx->pixel_format = p_in_data->data.frame.pixel_format; + p_out_data->data.packet.end_of_stream = 0; + p_in_data->data.frame.start_of_stream = 1; + return ret; +} + /*!***************************************************************************** * \brief decoder session open * @@ -3311,7 +5570,7 @@ int uploader_open_session(ni_session_context_t *p_upl_ctx, int iXcoderGUID, void print_usage(void) { printf("Video decoder/encoder/transcoder application directly using Netint " - "Libxcoder API v%s\n" + "Libxcoder release v%s\n" "Usage: xcoder [options]\n" "\n" "options:\n" @@ -3335,8 +5594,9 @@ void print_usage(void) "format:\n" " InType2OutType. [a2y, h2y, y2a, u2a, y2h, " "u2h, a2a, " - "a2h, h2a, h2h]\n" + "a2h, h2a, h2h, y2x, u2x, v2y]\n" " Type notation: y=YUV420P a=AVC, h=HEVC, " + "v=VP9, x=AV1, " "u=hwupload yuv\n" "-b | --bitdepth Input and output bit depth. [8, 10]\n" " (Default: 8)\n" @@ -3350,7 +5610,9 @@ void print_usage(void) " " "QuadraIntegration&ProgrammingGuide*.pdf for help.\n" " (Default: \"\")\n" - "-o | --output Output file path.\n", + "-o | --output Output file path.\n" + "-f | --vf Scaling params. Example: " + "ni_width=1280:ni_height=720:format=0:p2p=1.\n", NI_XCODER_REVISION); } @@ -3502,7 +5764,8 @@ static int retrieve_decoder_params(char xcoderParams[], } } ctx->keep_alive_timeout = params->dec_input_params.keep_alive_timeout; - + ctx->decoder_low_delay = params->dec_input_params.decoder_low_delay; + return ret; } @@ -3522,7 +5785,7 @@ void *decoder_send_thread(void *args) p_dec_send_param->input_video_height, p_dec_send_param->pkt_size, total_file_size, p_dec_send_param->p_total_bytes_sent, p_dec_send_param->print_time, p_dec_send_param->p_xcodeState, - p_dec_send_param->p_SPS); + p_dec_send_param->p_stream_info); sos_flag = 0; if (retval < 0) // Error { @@ -3665,24 +5928,45 @@ void *encoder_send_thread(void *args) int input_exhausted = 0; int sos_flag = 1; int retval; + int input_index = 0; + int input_total = p_enc_send_param->input_total; + int is_last_input; printf("encoder_send_thread start\n"); for (;;) { if (p_enc_send_param->mode == XCODER_APP_ENCODE) { + is_last_input = (input_index == (input_total-1)) ? 1 : 0; + retval = encoder_send_data( - p_enc_ctx, p_enc_send_param->p_in_frame, sos_flag, - p_enc_send_param->input_video_width, - p_enc_send_param->input_video_height, p_enc_send_param->pfs, - total_file_size, p_enc_send_param->p_total_bytes_sent, - p_enc_send_param->p_xcodeState); + p_enc_ctx, + p_enc_send_param->p_in_frame, + sos_flag, + p_enc_send_param->input_arg_width[input_index], + p_enc_send_param->input_arg_height[input_index], + p_enc_send_param->input_arg_pfs[input_index], + total_file_size, + p_enc_send_param->p_total_bytes_sent, + p_enc_send_param->p_xcodeState, + p_enc_send_param->input_bit_depth[input_index], + is_last_input); sos_flag = 0; if (retval < 0) // Error { fprintf(stderr, "Error: encoder_send_thread break in encode mode!\n"); break; + } else if (retval == NI_TEST_RETCODE_NEXT_INPUT) // next input (will trigger sequence change) + { + input_index++; + lseek(p_enc_send_param->input_arg_pfs[input_index], 0, SEEK_END); + total_file_size = lseek(p_enc_send_param->input_arg_pfs[input_index], 0, SEEK_CUR); + lseek(p_enc_send_param->input_arg_pfs[input_index], 0, SEEK_SET); + data_left_size = total_file_size; + } else if (p_enc_send_param->p_xcodeState->enc_seq_change) // sequene change + { + ni_usleep(100); } else if (p_enc_send_param->p_xcodeState->enc_eos_sent) //eos { ni_log(NI_LOG_DEBUG, @@ -3836,7 +6120,8 @@ void *encoder_receive_thread(void *args) p_enc_recv_param->p_enc_ctx, p_enc_recv_param->p_out_packet, p_enc_recv_param->output_video_width, p_enc_recv_param->output_video_height, p_enc_recv_param->p_file, - p_enc_recv_param->p_total_bytes_received, print_time); + p_enc_recv_param->p_total_bytes_received, print_time, + p_enc_recv_param->p_buffered_frame); if (retval < 0) // Error { fprintf(stderr, "Error: encoder_receive_thread break!\n"); @@ -3845,16 +6130,20 @@ void *encoder_receive_thread(void *args) { printf("encoder_receive_thread reach eos\n"); break; - } else if (retval == 2) + } else if (retval == NI_TEST_RETCODE_EAGAIN) { ni_usleep(100); + } else if (retval == NI_TEST_RETCODE_SEQ_CHANGE_DONE) + { + p_enc_recv_param->p_xcodeState->enc_seq_change = 0; } else if (p_enc_recv_param->p_enc_ctx->hw_action) { //encoder only returns valid recycle index //when there's something to recycle. //This range is suitable for all memory bins if (p_ni_packet->recycle_index > 0 && - p_ni_packet->recycle_index < NI_MAX_HWDESC_FRAME_INDEX) + p_ni_packet->recycle_index < NI_GET_MAX_HWDESC_FRAME_INDEX( + p_enc_recv_param->p_enc_ctx->ddr_config)) { p_hwframe = p_enc_recv_param->p_hwframe_pool_tracker + p_ni_packet->recycle_index; @@ -3930,6 +6219,520 @@ void *uploader_thread(void *args) return NULL; } +static int ni_scaler_params_set_value(ni_filter_params_t *params, + const char *name, const char *value) +{ + if (!params) + { + printf("Error: Null pointer parameters passed\n"); + return -1; + } + + if (!name) + { + printf("Error: Null name pointer parameters passed\n"); + return -1; + } + + if (!strcmp("scale_width", name)) + { + params->scale_width = atoi(value); + } else if (!strcmp("scale_height", name)) + { + params->scale_height = atoi(value); + } else if (!strcmp("p2p", name)) + { + int is_p2p = atoi(value); + params->p2p = is_p2p; + } else if (!strcmp("format", name)) + { + int format = atoi(value); + if (format == 0) + { + params->format = GC620_I420; + } else if (format == 1) + { + params->format = GC620_RGBA8888; + } else if (format == 2) + { + params->format = GC620_RGB888_PLANAR; + } else + { + printf("Error: invallid scaler parameters\n"); + return -1; + } + } else + { + printf("Error: invallid scaler parameters\n"); + return -1; + } + return 0; +} + +static int retrieve_filter_params(char xcoderParams[], + ni_filter_params_t *params) +{ + char key[64], value[64]; + char *curr = xcoderParams, *colon_pos; + int ret = 0; + + while (*curr) + { + colon_pos = strchr(curr, ':'); + + if (colon_pos) + { + *colon_pos = '\0'; + } + + if (strlen(curr) > sizeof(key) + sizeof(value) - 1 || + get_key_value(curr, key, value)) + { + fprintf(stderr, + "Error: scaler-params key/value not " + "retrieved: %s\n", + curr); + ret = -1; + break; + } + ret = ni_scaler_params_set_value(params, key, value); + if (ret != 0) + { + printf("Error: failed to parse the input scaler parameters\n"); + ret = -1; + break; + } + + if (colon_pos) + { + curr = colon_pos + 1; + } else + { + curr += strlen(curr); + } + } + return ret; +} + +/*!***************************************************************************** + * \brief Init scaler params here - both user setting params and fixed params. + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +void init_scaler_params(ni_scaler_input_params_t *p_scaler_params, + ni_scaler_opcode_t op, int in_rec_width, + int in_rec_height, int in_rec_x, int in_rec_y, + int out_rec_x, int out_rec_y) +{ + p_scaler_params->op = op; + // input_format/width/height, output_format/width/height should be assigned by users for all ops + if (op == NI_SCALER_OPCODE_CROP) + { + // fixed numbers + p_scaler_params->out_rec_width = 0; + p_scaler_params->out_rec_height = 0; + p_scaler_params->out_rec_x = 0; + p_scaler_params->out_rec_y = 0; + p_scaler_params->rgba_color = 0; + + // params set by user + p_scaler_params->in_rec_width = in_rec_width; + p_scaler_params->in_rec_height = in_rec_height; + p_scaler_params->in_rec_x = in_rec_x; + p_scaler_params->in_rec_y = in_rec_y; + } else if (op == NI_SCALER_OPCODE_SCALE) + { + // fixed params + p_scaler_params->in_rec_width = 0; + p_scaler_params->in_rec_height = 0; + p_scaler_params->in_rec_x = 0; + p_scaler_params->in_rec_y = 0; + + p_scaler_params->out_rec_width = 0; + p_scaler_params->out_rec_height = 0; + p_scaler_params->out_rec_x = 0; + p_scaler_params->out_rec_y = 0; + + p_scaler_params->rgba_color = 0; + } else if (op == NI_SCALER_OPCODE_PAD) + { + // fixed params + p_scaler_params->in_rec_width = p_scaler_params->input_width; + p_scaler_params->in_rec_height = p_scaler_params->input_height; + p_scaler_params->in_rec_x = 0; + p_scaler_params->in_rec_y = 0; + + p_scaler_params->out_rec_width = p_scaler_params->input_width; + p_scaler_params->out_rec_height = p_scaler_params->input_height; + + /* + Scaler uses BGRA color, or ARGB in little-endian + ui32RgbaColor = (s->rgba_color[3] << 24) | (s->rgba_color[0] << 16) | + (s->rgba_color[1] << 8) | s->rgba_color[2]; + here p_scaler_params->rgba_color = ui32RgbaColor; + */ + p_scaler_params->rgba_color = + 4278190080; // now padding color is black + + // params set by user + p_scaler_params->out_rec_x = out_rec_x; + p_scaler_params->out_rec_y = out_rec_y; + } else if (op == NI_SCALER_OPCODE_OVERLAY) + { + // fixed params + // set the in_rec params to the w/h of overlay(the upper) frames + p_scaler_params->in_rec_width = p_scaler_params->input_width; + p_scaler_params->in_rec_height = p_scaler_params->input_height; + + // the output w/h is the main frame's w/h (main frame is the lower/background frame) + p_scaler_params->out_rec_width = p_scaler_params->output_width; + p_scaler_params->out_rec_height = p_scaler_params->output_height; + p_scaler_params->out_rec_x = 0; + p_scaler_params->out_rec_y = 0; + p_scaler_params->rgba_color = 0; + + // params set by user + p_scaler_params->in_rec_x = in_rec_x; + p_scaler_params->in_rec_y = in_rec_x; + } +} + +/*!***************************************************************************** + * \brief open scaler session + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int scaler_session_open(ni_session_context_t *p_scaler_ctx, int iXcoderGUID, + ni_scaler_opcode_t op) +{ + int ret = 0; + + p_scaler_ctx->session_id = NI_INVALID_SESSION_ID; + + p_scaler_ctx->device_handle = NI_INVALID_DEVICE_HANDLE; + p_scaler_ctx->blk_io_handle = NI_INVALID_DEVICE_HANDLE; + p_scaler_ctx->hw_id = iXcoderGUID; + p_scaler_ctx->device_type = NI_DEVICE_TYPE_SCALER; + p_scaler_ctx->scaler_operation = op; + p_scaler_ctx->keep_alive_timeout = NI_DEFAULT_KEEP_ALIVE_TIMEOUT; + + ret = ni_device_session_open(p_scaler_ctx, NI_DEVICE_TYPE_SCALER); + + if (ret < 0) + { + fprintf(stderr, "Error: ni_scaler_session_open() failure!\n"); + return -1; + } else + { +#ifdef _WIN32 + printf("Scaler session open: device_handle %p, session_id %u.\n", + p_scaler_ctx->device_handle, p_scaler_ctx->session_id); +#else + printf("Scaler session open: device_handle %d, session_id %u.\n", + p_scaler_ctx->device_handle, p_scaler_ctx->session_id); +#endif + return 0; + } +} + +/*!***************************************************************************** + * \brief Launch scaler operation and get the result hw frame + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int launch_scaler_operation(ni_session_context_t *p_ctx, + ni_frame_t *p_frame_in_up, + ni_frame_t *p_frame_in_bg, + ni_session_data_io_t *p_data_out, + ni_scaler_input_params_t scaler_params) +{ + int ret = 0; + if (p_ctx->session_id == NI_INVALID_SESSION_ID) + { + // Open scaler session + if (0 != scaler_session_open(p_ctx, 0, scaler_params.op)) + { + fprintf(stderr, "Error: scaler open session error\n"); + return -1; + } + + // init scaler hwframe pool + if (0 != ni_scaler_frame_pool_alloc(p_ctx, scaler_params)) + { + fprintf(stderr, "Error: init filter hwframe pool\n"); + return -1; + } + } + + // allocate a ni_frame_t structure on the host PC + if (0 != + ni_frame_buffer_alloc_hwenc(&(p_data_out->data.frame), + scaler_params.output_width, + scaler_params.output_height, 0)) + { + return -1; + } + niFrameSurface1_t *frame_surface_up; + frame_surface_up = (niFrameSurface1_t *)(( + p_frame_in_up->p_data[3])); // out_frame retrieved from decoder + + // allocate scaler input frame + if (0 != + ni_scaler_input_frame_alloc(p_ctx, scaler_params, frame_surface_up)) + { + return -1; + } + + niFrameSurface1_t *frame_surface_bg; + frame_surface_bg = (niFrameSurface1_t *)((p_frame_in_bg->p_data[3])); + // Allocate scaler destination frame. + if (0 != ni_scaler_dest_frame_alloc(p_ctx, scaler_params, frame_surface_bg)) + { + return -1; + } + + // Retrieve hardware frame info from 2D engine and put it in the ni_frame_t structure. + ret = + ni_device_session_read_hwdesc(p_ctx, p_data_out, NI_DEVICE_TYPE_SCALER); + if (ret < 0) + { + ni_frame_buffer_free(p_frame_in_up); + ni_frame_buffer_free(p_frame_in_bg); + ni_frame_buffer_free(&(p_data_out->data.frame)); + } + return ret; +} + +/*!***************************************************************************** + * \brief Use crop->pad->overlay to simulate a drawbox filter. + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int drawbox_filter(ni_session_context_t *p_crop_ctx, + ni_session_context_t *p_pad_ctx, + ni_session_context_t *p_overlay_ctx, + ni_session_context_t *p_fmt_ctx, ni_frame_t *p_frame_in, + ni_session_data_io_t *p_data_out, box_params_t *p_box_params, + int output_format) +{ + // assume drawing box at the same position (can be set by box_params) + // set default box params + int box_width = 80; + int box_height = 60; + int box_x = 160; + int box_y = 100; + int line_width = 4; + if (p_box_params) + { + box_width = ((int)((p_box_params->box_w + 1) / 2) * 2); + box_height = ((int)((p_box_params->box_h + 1) / 2) * 2); + box_x = p_box_params->box_x; + box_y = p_box_params->box_y; + } + + /* + To simulate a drawbox filter, we need to + 1. Crop at the box set position + 2. Padding the crop output frame for fixed fixels (depends on the line_width of the box) + Recycle the crop hwFrame + 3. Overlay the padding result on the original frame + Recycle the padding hwFrame + 4. if format-change is needed, launch a scale operation and do format change + Recycle the overlay hwFrame + */ + + int ret = 0; + niFrameSurface1_t *p_surface_in; + p_surface_in = (niFrameSurface1_t *)(p_frame_in->p_data[3]); + + ni_scaler_input_params_t crop_params = {0}; + crop_params.input_format = GC620_I420; + crop_params.input_width = p_surface_in->ui16width; + crop_params.input_height = p_surface_in->ui16height; + crop_params.output_format = GC620_I420; + crop_params.output_width = box_width; + crop_params.output_height = box_height; + init_scaler_params(&crop_params, NI_SCALER_OPCODE_CROP, box_width, + box_height, box_x, box_y, 0, 0); + ni_session_data_io_t crop_data = {0}; + ret = launch_scaler_operation(p_crop_ctx, p_frame_in, p_frame_in, + &crop_data, crop_params); + if (ret != 0) + { + printf("Failed to lauch scaler operation %d\n", crop_params.op); + return -1; + } + niFrameSurface1_t *crop_frame_surface = + (niFrameSurface1_t *)(crop_data.data.frame.p_data[3]); + + ni_scaler_input_params_t pad_params = {0}; + pad_params.input_format = GC620_I420; + pad_params.input_width = crop_params.output_width; + pad_params.input_height = crop_params.output_height; + pad_params.output_format = GC620_I420; + pad_params.output_width = crop_params.output_width + line_width * 2; + pad_params.output_height = crop_params.output_height + line_width * 2; + init_scaler_params(&pad_params, NI_SCALER_OPCODE_PAD, 0, 0, 0, 0, + line_width, line_width); + ni_session_data_io_t pad_data = {0}; + ret = + launch_scaler_operation(p_pad_ctx, &(crop_data.data.frame), + &(crop_data.data.frame), &pad_data, pad_params); + // recycle HwFrameIdx first, then free the frame + ni_hwframe_buffer_recycle(crop_frame_surface, + crop_frame_surface->device_handle); + ni_frame_buffer_free(&(crop_data.data.frame)); + if (ret != 0) + { + printf("Failed to lauch scaler operation %d\n", pad_params.op); + return -1; + } + niFrameSurface1_t *pad_frame_surface = + (niFrameSurface1_t *)(pad_data.data.frame.p_data[3]); + + ni_scaler_input_params_t overlay_params = {0}; + overlay_params.input_format = GC620_I420; + overlay_params.input_width = pad_params.output_width; + overlay_params.input_height = pad_params.output_height; + overlay_params.output_format = GC620_I420; + overlay_params.output_width = p_surface_in->ui16width; + overlay_params.output_height = p_surface_in->ui16height; + int overlay_x = (box_width > line_width) ? (box_width - line_width) : 0; + int overlay_y = (box_height > line_width) ? (box_height - line_width) : 0; + init_scaler_params(&overlay_params, NI_SCALER_OPCODE_OVERLAY, 0, 0, + overlay_x, overlay_y, 0, 0); + ni_session_data_io_t ovly_data = {0}; + if (output_format == GC620_I420) + ret = launch_scaler_operation(p_overlay_ctx, &(pad_data.data.frame), + p_frame_in, p_data_out, overlay_params); + else + ret = launch_scaler_operation(p_overlay_ctx, &(pad_data.data.frame), + p_frame_in, &ovly_data, overlay_params); + // recycle HwFrameIdx first, then free the frame + ni_hwframe_buffer_recycle(pad_frame_surface, + pad_frame_surface->device_handle); + ni_frame_buffer_free(&(pad_data.data.frame)); + if (ret != 0) + { + printf("Failed to lauch scaler operation %d\n", overlay_params.op); + return -1; + } + + if (output_format != GC620_I420) // use scale filter to do format change + { + niFrameSurface1_t *ovly_frame_surface = + (niFrameSurface1_t *)(ovly_data.data.frame.p_data[3]); + ovly_frame_surface->ui16width = overlay_params.output_width; + ovly_frame_surface->ui16height = overlay_params.output_height; + ret = scale_filter(p_fmt_ctx, &(ovly_data.data.frame), p_data_out, + overlay_params.output_width, + overlay_params.output_height, output_format); + ni_hwframe_buffer_recycle(ovly_frame_surface, + ovly_frame_surface->device_handle); + ni_frame_buffer_free(&(ovly_data.data.frame)); + if (ret != 0) + { + printf("Failed to lauch scaler operation 0\n"); + return -1; + } + } + + return 0; +} + +/*!***************************************************************************** + * \brief Do a scale and/or format-change operation. + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int scale_filter(ni_session_context_t *p_ctx, ni_frame_t *p_frame_in, + ni_session_data_io_t *p_data_out, int scale_width, + int scale_height, int out_format) +{ + niFrameSurface1_t *p_surface_in; + p_surface_in = (niFrameSurface1_t *)(p_frame_in->p_data[3]); + + ni_scaler_input_params_t scale_params; + scale_params.output_format = out_format; // rgba or bgrp or yuv420p; + scale_params.output_width = scale_width; + scale_params.output_height = scale_height; + scale_params.input_format = + GC620_I420; // now assume the decoded frame format is GC620_I420; + scale_params.input_width = p_surface_in->ui16width; + scale_params.input_height = p_surface_in->ui16height; + init_scaler_params(&scale_params, NI_SCALER_OPCODE_SCALE, 0, 0, 0, 0, 0, 0); + int ret = launch_scaler_operation(p_ctx, p_frame_in, p_frame_in, p_data_out, + scale_params); + if (ret != 0) + { + printf("Failed to lauch scaler operation %d\n", scale_params.op); + return -1; + } + return 0; +} + +/*!***************************************************************************** + * \brief Write scaler p2p or hwdl output. + * + * \param + * + * \return 0 if successful, < 0 otherwise + ******************************************************************************/ +int scaler_output_write(ni_session_context_t *p_ctx, + ni_session_data_io_t *p_data_out, int out_width, + int out_height, int out_format, FILE *fp, + disp_buffer_t *disp) +{ + if (!fp) + return 0; + niFrameSurface1_t *p_frame_surface = + (niFrameSurface1_t *)(p_data_out->data.frame.p_data[3]); + p_frame_surface->ui16width = out_width; + p_frame_surface->ui16height = out_height; + p_frame_surface->bit_depth = 1; + p_frame_surface->encoding_type = NI_PIXEL_PLANAR_FORMAT_PLANAR; + int ret; + + if (p_ctx->isP2P) + { +#ifndef _WIN32 + ret = read_from_dmabuf(p_ctx, p_frame_surface, disp, out_format, fp); + if (ret != 0) + { + ni_frame_buffer_free(&(p_data_out->data.frame)); + return -1; + } +#endif + } else + { + // use hwdownload to download hw frame, recycle hwframe buffer + ni_session_data_io_t hwdl_session_data = {0}; + ret = hwdl_frame(p_ctx, &hwdl_session_data, &(p_data_out->data.frame), + out_format); + if (ret <= 0) + { + ni_frame_buffer_free(&(p_data_out->data.frame)); + return -1; + } + + // write hwdl frame to output_file + write_rawvideo_data(fp, out_width, out_height, out_format, + &(hwdl_session_data.data.frame)); + ni_frame_buffer_free(&(hwdl_session_data.data.frame)); + } + return 0; +} + /*!***************************************************************************** * \brief main * @@ -3954,8 +6757,8 @@ int main(int argc, char *argv[]) char mode_description[128]; int input_video_width; int input_video_height; - int arg_width = 0; - int arg_height = 0; + int arg_width; + int arg_height; int mode = -1; int multi_thread = 0; size_t i; @@ -3967,25 +6770,37 @@ int main(int argc, char *argv[]) niFrameSurface1_t *p_hwframe; char encConfXcoderParams[2048] = {0}; char decConfXcoderParams[2048] = {0}; + char scaConfXcoderParams[2048] = {0}; int ret = 0; int recycle_index = 0; - ni_log_level_t log_level; + ni_log_level_t log_level = NI_LOG_INFO; //inelegant solution but quick when memory is cheap - niFrameSurface1_t hwframe_pool_tracker[NI_MAX_HWDESC_FRAME_INDEX]; + niFrameSurface1_t hwframe_pool_tracker[NI_MAX_DR_HWDESC_FRAME_INDEX]; memset(hwframe_pool_tracker, 0, - NI_MAX_HWDESC_FRAME_INDEX * sizeof(niFrameSurface1_t)); + NI_MAX_DR_HWDESC_FRAME_INDEX * sizeof(niFrameSurface1_t)); ni_device_handle_t dev_handle = NI_INVALID_DEVICE_HANDLE, dev_handle_1 = NI_INVALID_DEVICE_HANDLE; int src_codec_format = 0, dst_codec_format = 0; - ni_log_level_t loglevel = NI_LOG_ERROR; int bit_depth = 8; + + int input_arg_width[MAX_INPUT_FILES] = {0}; + int input_arg_height[MAX_INPUT_FILES] = {0}; + int input_bit_depth[MAX_INPUT_FILES]; + int input_arg_pfs[MAX_INPUT_FILES] = {0}; + ni_h264_sps_t SPS = {0}; // input header SPS + ni_h265_sps_t HEVC_SPS = {0}; + ni_vp9_header_info_t VP9_INFO = {0}; + int input_index = 0; + int input_total; + int size_index = 0; + int bit_depth_index = 0; // Input arg handling int opt; int opt_index; - const char *opt_string = "hvtl:c:i:s:m:b:x:d:o:r:"; + const char *opt_string = "hvtl:c:i:s:m:b:x:d:f:o:r:"; static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, @@ -3998,6 +6813,7 @@ int main(int argc, char *argv[]) {"bitdepth", required_argument, NULL, 'b'}, {"xcoder-params", required_argument, NULL, 'x'}, {"decoder-params", required_argument, NULL, 'd'}, + {"scaler-params", required_argument, NULL, 'f'}, {"output", required_argument, NULL, 'o'}, {"repeat", required_argument, NULL, 'r'}, {NULL, 0, NULL, 0}, @@ -4012,11 +6828,12 @@ int main(int argc, char *argv[]) print_usage(); exit(0); case 'v': - printf("Ver: %s\n" - "Date: %s\n" - "ID: %s\n", - NI_XCODER_REVISION, NI_SW_RELEASE_TIME, - NI_SW_RELEASE_ID); + printf("Release ver: %s\n" + "API ver: %s\n" + "Date: %s\n" + "ID: %s\n", + NI_XCODER_REVISION, LIBXCODER_API_VERSION, + NI_SW_RELEASE_TIME, NI_SW_RELEASE_ID); exit(0); case 't': multi_thread = 1; @@ -4038,13 +6855,25 @@ int main(int argc, char *argv[]) arg_error_exit("-c | --card", optarg); break; case 'i': - strcpy(sdPara.fileName, optarg); + if (input_index == MAX_INPUT_FILES) + { + printf("Error: number of input files cannot exceed %d\n", MAX_INPUT_FILES); + exit(-1); + } + strcpy(sdPara.fileName[input_index], optarg); + input_index++; break; case 's': - arg_width = (int)strtol(optarg, &n, 10); - arg_height = atoi(n + 1); - if ((*n != 'x') || (!arg_width || !arg_height)) + if (size_index == MAX_INPUT_FILES) + { + printf("Error: number of input resolutions cannot exceed %d\n", MAX_INPUT_FILES); + exit(-1); + } + input_arg_width[size_index] = (int)strtol(optarg, &n, 10); + input_arg_height[size_index] = atoi(n + 1); + if ((*n != 'x') || (!input_arg_width[size_index] || !input_arg_height[size_index])) arg_error_exit("-s | --size", optarg); + size_index++; break; case 'm': if (!(strlen(optarg) == 3)) @@ -4057,7 +6886,10 @@ int main(int argc, char *argv[]) strcmp(optarg, "a2y") != 0 && strcmp(optarg, "a2a") != 0 && strcmp(optarg, "a2h") != 0 && strcmp(optarg, "h2y") != 0 && strcmp(optarg, "h2a") != 0 && strcmp(optarg, "h2h") != 0 && - strcmp(optarg, "u2a") != 0 && strcmp(optarg, "u2h") != 0) + strcmp(optarg, "u2a") != 0 && strcmp(optarg, "u2h") != 0 && + strcmp(optarg, "a2r") != 0 && strcmp(optarg, "h2r") != 0 && + strcmp(optarg, "u2x") != 0 && strcmp(optarg, "y2x") != 0 && + strcmp(optarg, "v2y") != 0) arg_error_exit("-, | --mode", optarg); // determine dec/enc/xcod mode to use @@ -4076,6 +6908,10 @@ int main(int argc, char *argv[]) { sprintf(mode_description, "HWUpload + Encoding"); mode = XCODER_APP_HWUP_ENCODE; + } else if (optarg[2] == 'r') + { + sprintf(mode_description, "Decoding + filtering"); + mode = XCODER_APP_FILTER; } else { sprintf(mode_description, "Transcoding"); @@ -4093,6 +6929,11 @@ int main(int argc, char *argv[]) src_codec_format = NI_CODEC_FORMAT_H265; strcat(mode_description, " from HEVC"); } + if (optarg[0] == 'v') + { + src_codec_format = NI_CODEC_FORMAT_VP9; + strcat(mode_description, " from VP9"); + } if (optarg[2] == 'a') { dst_codec_format = NI_CODEC_FORMAT_H264; @@ -4103,12 +6944,22 @@ int main(int argc, char *argv[]) dst_codec_format = NI_CODEC_FORMAT_H265; strcat(mode_description, " to HEVC"); } - + if (optarg[2] == 'x') + { + dst_codec_format = NI_CODEC_FORMAT_AV1; + strcat(mode_description, " to AV1"); + } break; case 'b': + if (bit_depth_index == MAX_INPUT_FILES) + { + printf("Error: cannot input more than %d bitdepth\n", MAX_INPUT_FILES); + exit(-1); + } if (!(atoi(optarg) == 8 || atoi(optarg) == 10)) arg_error_exit("-b | --bitdepth", optarg); - bit_depth = atoi(optarg); + input_bit_depth[bit_depth_index] = atoi(optarg); + bit_depth_index++; break; case 'x': strcpy(encConfXcoderParams, optarg); @@ -4116,6 +6967,9 @@ int main(int argc, char *argv[]) case 'd': strcpy(decConfXcoderParams, optarg); break; + case 'f': + strcpy(scaConfXcoderParams, optarg); + break; case 'o': strcpy(rcPara.fileName, optarg); break; @@ -4130,14 +6984,80 @@ int main(int argc, char *argv[]) } } + // sequence change input parameter check + if (input_index != size_index) + { + if (mode == XCODER_APP_ENCODE) + { + printf("Error: number of input files %d does not match with number of input resolutions %d\n", input_index, size_index); + exit(-1); + } + } + + input_total = input_index; + + if (input_total > 1) + { + if (mode != XCODER_APP_ENCODE) + { + printf("Error: multiple input files not supported for mode %d\n", mode); + exit(-1); + } + + if (g_repeat > 1) + { + printf("Error: multiple input files not supported when repeat %d greater than one\n", g_repeat); + exit(-1); + } + } + + for ( ; bit_depth_index < MAX_INPUT_FILES; bit_depth_index++) + { + input_bit_depth[bit_depth_index] = 8; + } + + arg_width = input_arg_width[0]; + arg_height = input_arg_height[0]; + bit_depth = input_bit_depth[0]; + // Check required args are present - if (!sdPara.fileName[0]) + if (!sdPara.fileName[0][0]) { printf("Error: missing argument for -i | --input\n"); exit(-1); } + + for (input_index = 0; input_index < input_total; input_index++) + { + if (!sdPara.fileName[input_index][0]) + { + printf("Error: incorrect input file %d\n", input_index); + exit(-1); + } + +#ifdef _WIN32 + input_arg_pfs[input_index] = open(sdPara.fileName[input_index], O_RDONLY | O_BINARY); +#else + input_arg_pfs[input_index] = open(sdPara.fileName[input_index], O_RDONLY); +#endif + + if (input_arg_pfs[input_index] < 0) + { + fprintf(stderr, "Error: cannot open %s\n", sdPara.fileName[input_index]); + fprintf(stderr, "Error: input file read failure\n"); + err_flag = 1; + goto end; + } + printf("SUCCESS: Opened input file: %s with file id = %d\n", + sdPara.fileName[input_index], input_arg_pfs[input_index]); + } + + input_index = 0; + pfs = input_arg_pfs[0]; + if ((mode != XCODER_APP_TRANSCODE) && (mode != XCODER_APP_DECODE) && - (mode != XCODER_APP_ENCODE) && (mode != XCODER_APP_HWUP_ENCODE)) + (mode != XCODER_APP_ENCODE) && (mode != XCODER_APP_HWUP_ENCODE) && + (mode != XCODER_APP_FILTER)) { printf("Error: missing argument for -m | --mode\n"); exit(-1); @@ -4156,26 +7076,37 @@ int main(int argc, char *argv[]) pkt_size = 131040; // hardcoded input data chunk size (for H.265) + lseek(pfs, 0, SEEK_END); + total_file_size = lseek(pfs, 0, SEEK_CUR); + lseek(pfs, 0, SEEK_SET); + unsigned long tmpFileSize = total_file_size; + + /* + if (fileName2[0]) + { + + + + #ifdef _WIN32 - pfs = open(sdPara.fileName, O_RDONLY | O_BINARY); + pfs2 = open(fileName2, O_RDONLY | O_BINARY); #else - pfs = open(sdPara.fileName, O_RDONLY); + pfs2 = open(fileName2, O_RDONLY); #endif - if (pfs < 0) - { - fprintf(stderr, "Error: cannot open %s\n", sdPara.fileName); - fprintf(stderr, "Error: input file read failure\n"); - err_flag = 1; - goto end; + if (pfs2 < 0) + { + fprintf(stderr, "Error: cannot open %s\n", fileName2); + fprintf(stderr, "Error: input file read failure\n"); + err_flag = 1; + goto end; + } + printf("SUCCESS: Opened 2nd input file for sequence change: %s with file id = %d\n", + fileName2, pfs2); + + lseek(pfs2, 0, SEEK_SET); } - printf("SUCCESS: Opened input file: %s with file id = %d\n", - sdPara.fileName, pfs); - - lseek(pfs, 0, SEEK_END); - total_file_size = lseek(pfs, 0, SEEK_CUR); - lseek(pfs, 0, SEEK_SET); - unsigned long tmpFileSize = total_file_size; + */ if (mode == XCODER_APP_ENCODE || mode == XCODER_APP_HWUP_ENCODE) { @@ -4213,7 +7144,7 @@ int main(int argc, char *argv[]) g_curr_cache_pos = g_file_cache; data_left_size = total_file_size; - if (strcmp(rcPara.fileName, "null") != 0) + if (strcmp(rcPara.fileName, "null") != 0 && strcmp(rcPara.fileName, "/dev/null") != 0) { p_file = fopen(rcPara.fileName, "wb"); if (p_file == NULL) @@ -4222,12 +7153,17 @@ int main(int argc, char *argv[]) err_flag = 1; goto end; } + printf("SUCCESS: Opened output file: %s\n", rcPara.fileName); + } + else + { + printf("SUCCESS: output file %s implies dropping output\n", rcPara.fileName); } - printf("SUCCESS: Opened output file: %s\n", rcPara.fileName); // for H.264, probe the source and use the probed source info as defaults if (NI_CODEC_FORMAT_H264 == src_codec_format && - (mode == XCODER_APP_TRANSCODE || mode == XCODER_APP_DECODE)) + (mode == XCODER_APP_TRANSCODE || mode == XCODER_APP_DECODE || + mode == XCODER_APP_FILTER)) { if (probe_h264_stream_info(&SPS)) { @@ -4243,6 +7179,45 @@ int main(int argc, char *argv[]) bit_depth = SPS.bit_depth_luma; arg_width = SPS.width; arg_height = SPS.height; + } else if (NI_CODEC_FORMAT_H265 == src_codec_format && + (mode == XCODER_APP_DECODE)) + { + if (probe_h265_stream_info(&HEVC_SPS)) + { + fprintf(stderr, + "ERROR: H.265 file probing complete, source file format " + "not supported !\n"); + goto end; + } + bit_depth = HEVC_SPS.bit_depth_chroma; + arg_width = (int)(HEVC_SPS.width - + (HEVC_SPS.pic_conf_win.left_offset + + HEVC_SPS.pic_conf_win.right_offset)); + arg_height = (int)(HEVC_SPS.height - + (HEVC_SPS.pic_conf_win.top_offset + + HEVC_SPS.pic_conf_win.bottom_offset)); + ni_log(NI_LOG_INFO, + "Using probed H.265 source info: %d bits " + "resolution %dx%d\n", + HEVC_SPS.bit_depth_chroma, arg_width, arg_height); + } else if (NI_CODEC_FORMAT_VP9 == src_codec_format && + (mode == XCODER_APP_DECODE)) + { + if (probe_vp9_stream_info(&VP9_INFO)) + { + fprintf(stderr, + "ERROR: VP9 file probing complete, source file format " + "not supported !\n"); + goto end; + } + ni_log(NI_LOG_INFO, + "Using probed VP9 source info: %d profile " + "resolution %dx%d, timebase %d/%d\n", + VP9_INFO.profile, VP9_INFO.width, VP9_INFO.height, + VP9_INFO.timebase.den, VP9_INFO.timebase.num); + bit_depth = VP9_INFO.profile ? 10 : 8; + arg_width = VP9_INFO.width; + arg_height = VP9_INFO.height; } sdPara.arg_width = arg_width; @@ -4264,6 +7239,11 @@ int main(int argc, char *argv[]) ni_session_context_t dec_ctx = {0}; ni_session_context_t enc_ctx = {0}; ni_session_context_t upl_ctx = {0}; + ni_session_context_t sca_ctx = {0}; + ni_session_context_t crop_ctx = {0}; + ni_session_context_t pad_ctx = {0}; + ni_session_context_t ovly_ctx = {0}; + ni_session_context_t fmt_ctx = {0}; if (ni_device_session_context_init(&dec_ctx) < 0) { @@ -4281,12 +7261,52 @@ int main(int argc, char *argv[]) return -1; } + if (ni_device_session_context_init(&sca_ctx) < 0) + { + fprintf(stderr, "Error: init decoder context error\n"); + return -1; + } + + if (ni_device_session_context_init(&crop_ctx) < 0) + { + fprintf(stderr, "Error: init decoder context error\n"); + return -1; + } + + if (ni_device_session_context_init(&pad_ctx) < 0) + { + fprintf(stderr, "Error: init decoder context error\n"); + return -1; + } + + if (ni_device_session_context_init(&ovly_ctx) < 0) + { + fprintf(stderr, "Error: init decoder context error\n"); + return -1; + } + + if (ni_device_session_context_init(&fmt_ctx) < 0) + { + fprintf(stderr, "Error: init decoder context error\n"); + return -1; + } + sdPara.p_dec_ctx = (void *)&dec_ctx; sdPara.p_enc_ctx = (void *)&enc_ctx; sdPara.p_upl_ctx = (void *)&upl_ctx; + sdPara.p_sca_ctx = (void *)&sca_ctx; + sdPara.p_crop_ctx = (void *)&crop_ctx; + sdPara.p_pad_ctx = (void *)&pad_ctx; + sdPara.p_ovly_ctx = (void *)&ovly_ctx; + sdPara.p_fmt_ctx = (void *)&fmt_ctx; rcPara.p_dec_ctx = (void *)&dec_ctx; rcPara.p_enc_ctx = (void *)&enc_ctx; rcPara.p_upl_ctx = (void *)&upl_ctx; + rcPara.p_sca_ctx = (void *)&sca_ctx; + rcPara.p_crop_ctx = (void *)&crop_ctx; + rcPara.p_pad_ctx = (void *)&pad_ctx; + rcPara.p_ovly_ctx = (void *)&ovly_ctx; + rcPara.p_fmt_ctx = (void *)&fmt_ctx; enc_ctx.nb_rois = 0; enc_ctx.roi_side_data_size = 0; @@ -4296,14 +7316,16 @@ int main(int argc, char *argv[]) enc_ctx.codec_format = dst_codec_format; - if (mode == XCODER_APP_TRANSCODE || mode == XCODER_APP_DECODE) + if (mode == XCODER_APP_TRANSCODE || mode == XCODER_APP_DECODE || + mode == XCODER_APP_FILTER) { dec_ctx.p_session_config = NULL; dec_ctx.session_id = NI_INVALID_SESSION_ID; dec_ctx.codec_format = src_codec_format; // default decode the UDU; ToDo: make it configurable - dec_ctx.enable_user_data_sei_passthru = 1; + if (src_codec_format == NI_CODEC_FORMAT_H264) + dec_ctx.enable_user_data_sei_passthru = 1; // no need to directly allocate resource context rcPara.p_dec_rsrc_ctx = sdPara.p_dec_rsrc_ctx = NULL; @@ -4348,11 +7370,16 @@ int main(int argc, char *argv[]) } if (mode == XCODER_APP_TRANSCODE || mode == XCODER_APP_ENCODE || - mode == XCODER_APP_HWUP_ENCODE) + mode == XCODER_APP_HWUP_ENCODE || mode == XCODER_APP_FILTER) { // no need to directly allocate resource context for encoder rcPara.p_enc_rsrc_ctx = sdPara.p_enc_rsrc_ctx = NULL; rcPara.p_upl_rsrc_ctx = sdPara.p_upl_rsrc_ctx = NULL; + rcPara.p_sca_rsrc_ctx = sdPara.p_sca_rsrc_ctx = NULL; + rcPara.p_crop_rsrc_ctx = sdPara.p_crop_rsrc_ctx = NULL; + rcPara.p_pad_rsrc_ctx = sdPara.p_pad_rsrc_ctx = NULL; + rcPara.p_ovly_rsrc_ctx = sdPara.p_ovly_rsrc_ctx = NULL; + rcPara.p_fmt_rsrc_ctx = sdPara.p_fmt_rsrc_ctx = NULL; } // encoder session open, if needed, will be at the first frame arrival as it @@ -4382,7 +7409,7 @@ int main(int argc, char *argv[]) start_timestamp = privious_timestamp = current_timestamp = time(NULL); #if 0 -#ifdef __linux__ +#if __linux__ || __APPLE__ struct timespec start, end; clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start); #endif @@ -4395,6 +7422,14 @@ int main(int argc, char *argv[]) dec_ctx.hw_action); ni_session_data_io_t in_pkt = {0}; ni_session_data_io_t out_frame = {0}; + void *p_stream_info = NULL; + if (src_codec_format == NI_CODEC_FORMAT_H264) + p_stream_info = &SPS; + else if (src_codec_format == NI_CODEC_FORMAT_H265) + p_stream_info = &HEVC_SPS; + else if (src_codec_format == NI_CODEC_FORMAT_VP9) + p_stream_info = &VP9_INFO; + if (multi_thread) { ni_pthread_t dec_send_tid, dec_recv_tid; @@ -4409,7 +7444,7 @@ int main(int argc, char *argv[]) dec_send_param.print_time = 0; // not support now dec_send_param.p_total_bytes_sent = &total_bytes_sent; dec_send_param.p_xcodeState = &xcodeState; - dec_send_param.p_SPS = &SPS; + dec_send_param.p_stream_info = p_stream_info; dec_recv_param.p_dec_ctx = &dec_ctx; dec_recv_param.p_out_frame = &out_frame; @@ -4452,7 +7487,7 @@ int main(int argc, char *argv[]) send_fin_flag = decoder_send_data( &dec_ctx, &in_pkt, sos_flag, input_video_width, input_video_height, pkt_size, total_file_size, - &total_bytes_sent, print_time, &xcodeState, &SPS); + &total_bytes_sent, print_time, &xcodeState, p_stream_info); sos_flag = 0; if (send_fin_flag < 0) { @@ -4467,7 +7502,6 @@ int main(int argc, char *argv[]) &dec_ctx, &out_frame, output_video_width, output_video_height, p_file, &total_bytes_received, print_time, 1, &xcodeState); - ni_decoder_frame_buffer_free(&(out_frame.data.frame)); if (print_time) { @@ -4527,7 +7561,7 @@ int main(int argc, char *argv[]) api_param.video_full_range_flag); video_full_range_flag = api_param.video_full_range_flag; } - + // for encode from YUV, use all the parameters specified by user if (0 != (ret = encoder_open_session( @@ -4542,6 +7576,23 @@ int main(int argc, char *argv[]) ni_session_data_io_t in_frame = {0}; ni_session_data_io_t out_packet = {0}; + + /* // currently xcoder demo app does not support semi-planar - following is for future reference + int is_planar = 1; + in_frame.data.frame.pixel_format = + (is_planar ? NI_PIX_FMT_YUV420P : NI_PIX_FMT_NV12); + if (10 == bit_depth) + { + in_frame.data.frame.pixel_format = + (is_planar ? NI_PIX_FMT_YUV420P10LE : NI_PIX_FMT_P010LE); + } + */ + in_frame.data.frame.pixel_format = NI_PIX_FMT_YUV420P; + if (10 == bit_depth) + { + in_frame.data.frame.pixel_format = NI_PIX_FMT_YUV420P10LE; + } + if (multi_thread) { ni_pthread_t enc_send_tid, enc_recv_tid; @@ -4553,6 +7604,10 @@ int main(int argc, char *argv[]) enc_send_param.input_video_width = input_video_width; enc_send_param.input_video_height = input_video_height; enc_send_param.pfs = pfs; + memcpy(enc_send_param.input_arg_width, input_arg_width, sizeof(enc_send_param.input_arg_width)); + memcpy(enc_send_param.input_arg_height, input_arg_height, sizeof(enc_send_param.input_arg_height)); + memcpy(enc_send_param.input_bit_depth, input_bit_depth, sizeof(enc_send_param.input_bit_depth)); + memcpy(enc_send_param.input_arg_pfs, input_arg_pfs, sizeof(enc_send_param.input_arg_pfs)); enc_send_param.p_total_bytes_sent = &total_bytes_sent; enc_send_param.p_xcodeState = &xcodeState; enc_send_param.mode = mode; @@ -4560,6 +7615,7 @@ int main(int argc, char *argv[]) enc_send_param.dec_codec_format = -1; // not use heres enc_send_param.p_input_exhausted = NULL; // not use heres enc_send_param.p_hwframe_pool_tracker = NULL; // not use heres + enc_send_param.input_total = input_total; enc_recv_param.p_enc_ctx = &enc_ctx; enc_recv_param.p_out_packet = &out_packet; @@ -4570,6 +7626,7 @@ int main(int argc, char *argv[]) enc_recv_param.p_xcodeState = &xcodeState; enc_recv_param.mode = mode; enc_recv_param.p_hwframe_pool_tracker = NULL; + enc_recv_param.p_buffered_frame = &in_frame; if (ni_pthread_create(&enc_send_tid, NULL, encoder_send_thread, &enc_send_param)) @@ -4592,7 +7649,7 @@ int main(int argc, char *argv[]) (void)ni_gettimeofday(¤t_time, NULL); } else { - while (send_fin_flag == 0 || receive_fin_flag == 0) + while (send_fin_flag == NI_TEST_RETCODE_SUCCESS || receive_fin_flag == NI_TEST_RETCODE_SUCCESS) { (void)ni_gettimeofday(¤t_time, NULL); int print_time = @@ -4600,20 +7657,41 @@ int main(int argc, char *argv[]) // Sending send_fin_flag = encoder_send_data( - &enc_ctx, &in_frame, sos_flag, input_video_width, - input_video_height, pfs, total_file_size, &total_bytes_sent, - &xcodeState); + &enc_ctx, &in_frame, sos_flag, input_arg_width[input_index], + input_arg_height[input_index], input_arg_pfs[input_index], total_file_size, &total_bytes_sent, + &xcodeState, input_bit_depth[input_index], (input_index == (input_total-1))); sos_flag = 0; - if (send_fin_flag == 2) //Error + + if (send_fin_flag == NI_TEST_RETCODE_EAGAIN) //Error - impossible case, since write buffer full is handled by encoder_send_data need_to_resend { break; + } else if (send_fin_flag == NI_TEST_RETCODE_NEXT_INPUT) // next input (will trigger sequence change) + { + input_index++; + lseek(input_arg_pfs[input_index], 0, SEEK_END); + total_file_size = lseek(input_arg_pfs[input_index], 0, SEEK_CUR); + lseek(input_arg_pfs[input_index], 0, SEEK_SET); + data_left_size = total_file_size; + send_fin_flag = NI_TEST_RETCODE_SUCCESS; } + enc_receive: // Receiving receive_fin_flag = encoder_receive_data( &enc_ctx, &out_packet, output_video_width, output_video_height, p_file, &total_bytes_received, - print_time); + print_time, &in_frame); // in_frame is passed in for the new resolution info of sequence change + + if (enc_ctx.codec_format == NI_CODEC_FORMAT_AV1) + { + if (!out_packet.data.packet.av1_show_frame && + number_of_packets >= 2) + { + ni_log(NI_LOG_DEBUG, "AV1 got not shown frames\n"); + number_of_packets -= 1; + goto enc_receive; + } + } if (print_time) { @@ -4625,6 +7703,10 @@ int main(int argc, char *argv[]) out_packet.data.packet.end_of_stream) { break; + } else if (receive_fin_flag == NI_TEST_RETCODE_SEQ_CHANGE_DONE) + { + xcodeState.enc_seq_change = 0; + receive_fin_flag = NI_TEST_RETCODE_SUCCESS; } } } @@ -4732,7 +7814,7 @@ int main(int argc, char *argv[]) api_param.hwframes = 1; //to determine if from same device and buffer dimensions in memory //needs to be done where input frame is available to check - p_hwframe = p_ni_frame->p_data[3]; + p_hwframe = (niFrameSurface1_t *)p_ni_frame->p_data[3]; enc_ctx.sender_handle = (ni_device_handle_t)(int64_t)p_hwframe->device_handle; api_param.rootBufId = p_hwframe->ui16FrameIdx; @@ -4855,7 +7937,7 @@ int main(int argc, char *argv[]) api_param.hwframes = 1; //to determine if from same device and buffer dimensions in memory //needs to be done where input frame is available to check - p_hwframe = in_frame.data.frame.p_data[3]; + p_hwframe = (niFrameSurface1_t *)in_frame.data.frame.p_data[3]; enc_ctx.sender_handle = (ni_device_handle_t)(int64_t)p_hwframe->device_handle; api_param.rootBufId = p_hwframe->ui16FrameIdx; @@ -4887,8 +7969,18 @@ int main(int argc, char *argv[]) input_video_height, pfs, total_file_size, &total_bytes_sent, &input_exhausted)) { - fprintf(stderr, "Error: upload frame error\n"); - return -1; + if ((&upl_ctx)->status == + NI_RETCODE_NVME_SC_WRITE_BUFFER_FULL) + { + ni_log( + NI_LOG_DEBUG, + "No space to write to, try to read a packet\n"); + goto receive_pkt; + } else + { + fprintf(stderr, "Error: upload frame error\n"); + return -1; + } } } @@ -4919,16 +8011,17 @@ int main(int argc, char *argv[]) sizeof(niFrameSurface1_t)); } + receive_pkt: // Receiving prev_num_pkt = number_of_packets; receive_fin_flag = encoder_receive_data( &enc_ctx, &out_packet, output_video_width, output_video_height, p_file, &total_bytes_received, - print_time); + print_time, &in_frame); // in_frame is passed in for future sequence change support (XCODER_APP_HWUP_ENCODE does not support sequence change yet) recycle_index = out_packet.data.packet.recycle_index; if (prev_num_pkt < number_of_packets && enc_ctx.hw_action && recycle_index > 0 && - recycle_index < NI_MAX_HWDESC_FRAME_INDEX) + recycle_index < NI_GET_MAX_HWDESC_FRAME_INDEX(enc_ctx.ddr_config)) //encoder only returns valid recycle index //when there's something to recycle. //This range is suitable for all memory bins @@ -4942,6 +8035,16 @@ int main(int argc, char *argv[]) hwframe_pool_tracker[recycle_index].ui16FrameIdx = 0; } } + if (enc_ctx.codec_format == NI_CODEC_FORMAT_AV1) + { + if (!out_packet.data.packet.av1_show_frame && + number_of_packets >= 2) + { + ni_log(NI_LOG_DEBUG, "AV1 got not shown frames\n"); + number_of_packets -= 1; + goto receive_pkt; + } + } if (print_time) { previous_time = current_time; @@ -4977,6 +8080,273 @@ int main(int argc, char *argv[]) ni_frame_buffer_free(&(in_frame.data.frame)); ni_frame_buffer_free(&(swin_frame.data.frame)); ni_packet_buffer_free(&(out_packet.data.packet)); + } else if (mode == XCODER_APP_FILTER) + { +#ifndef _WIN32 + // not support on windows + + printf("Scaling Mode\n"); + // default filter params + ni_filter_params_t filter_params = {0}; + filter_params.scale_width = 1280; + filter_params.scale_height = 720; + filter_params.format = GC620_I420; + + if (0 != + (ret = retrieve_filter_params(scaConfXcoderParams, &filter_params))) + { + return -1; + } + int is_p2p = filter_params.p2p; + int scale_width = filter_params.scale_width; + int scale_height = filter_params.scale_height; + int out_format = filter_params.format; + if (is_p2p) + { + sca_ctx.isP2P = 1; + if (out_format != GC620_I420) + fmt_ctx.isP2P = 1; + else + ovly_ctx.isP2P = 1; + } + + niFrameSurface1_t dec_hwframe_tracker = {0}; + niFrameSurface1_t scaler_hwframe_tracker = {0}; + niFrameSurface1_t drawbox_hwframe_tracker = {0}; + disp_buffer_t *disp1 = NULL; + disp_buffer_t *disp2 = NULL; + if (is_p2p) + { + disp1 = calloc(1, sizeof(disp_buffer_t)); + disp2 = calloc(1, sizeof(disp_buffer_t)); + } + + ni_session_data_io_t in_pkt = {0}; + ni_session_data_io_t out_frame = {0}; + FILE *p_ovly_out = NULL; + if (p_file) + { + char *ovly_outfile; + char *p = strtok(rcPara.fileName, "."); + if (!p) + { + ovly_outfile = strcat(rcPara.fileName, "_overlay"); + } + while (p) + { + char *name = (char *)malloc(strlen(p)); + strcpy(name, p); + strcat(name, "_overlay."); + p = strtok(NULL, "."); + ovly_outfile = strcat(name, p); + break; + } + printf("overlay output filename %s\n", ovly_outfile); + p_ovly_out = fopen(ovly_outfile, "wb"); + } + + while (send_fin_flag == 0 || receive_fin_flag == 0) + { + (void)ni_gettimeofday(¤t_time, NULL); + int print_time = ((current_time.tv_sec - previous_time.tv_sec) > 1); + + // Sending + send_fin_flag = decoder_send_data( + &dec_ctx, &in_pkt, sos_flag, input_video_width, + input_video_height, pkt_size, total_file_size, + &total_bytes_sent, print_time, &xcodeState, &SPS); + sos_flag = 0; + if (send_fin_flag < 0) + { + fprintf(stderr, "Error: decoder_send_data() failed, rc: %d\n", + send_fin_flag); + break; + } + + // Receiving + receive_fin_flag = decoder_receive_data( + &dec_ctx, &out_frame, output_video_width, output_video_height, + p_file, &total_bytes_received, print_time, 0, + &xcodeState); // not write to file + if (print_time) + { + previous_time = current_time; + } + + if (receive_fin_flag < 0 || out_frame.data.frame.end_of_stream) + { + ni_frame_buffer_free(&(out_frame.data.frame)); + break; + } else if (receive_fin_flag != 2) + { + // got yuv hwframe from decoder. save dec hwframe idx + memcpy(&dec_hwframe_tracker, + (uint8_t *)out_frame.data.frame.p_data[3], + sizeof(niFrameSurface1_t)); + niFrameSurface1_t *decoded_surface = + (niFrameSurface1_t *)(out_frame.data.frame.p_data[3]); + + // set decoded frame params + decoded_surface->ui16width = output_video_width; + decoded_surface->ui16height = output_video_height; + decoded_surface->bit_depth = 1; + decoded_surface->encoding_type = NI_PIXEL_PLANAR_FORMAT_PLANAR; + + // scale the decoded frame(always yuv) and write to output file + ni_session_data_io_t scale_session_data = {0}; + ret = scale_filter(&sca_ctx, &(out_frame.data.frame), + &scale_session_data, scale_width, + scale_height, out_format); + if (ret != 0) + break; + // Save scaler HwFrameIdx + memcpy(&scaler_hwframe_tracker, + (uint8_t *)(scale_session_data.data.frame.p_data[3]), + sizeof(niFrameSurface1_t)); + ret = scaler_output_write(&sca_ctx, &scale_session_data, + scale_width, scale_height, out_format, + p_file, disp1); + if (ret != 0) + break; + if (scaler_hwframe_tracker.ui16FrameIdx) + { + ni_hwframe_buffer_recycle( + &scaler_hwframe_tracker, + scaler_hwframe_tracker.device_handle); + scaler_hwframe_tracker.ui16FrameIdx = 0; + } + + // draw box on the decoded frame and write to output file + ni_session_data_io_t drawbox_session_data = {0}; + ret = drawbox_filter(&crop_ctx, &pad_ctx, &ovly_ctx, &fmt_ctx, + &(out_frame.data.frame), + &drawbox_session_data, NULL, out_format); + if (ret != 0) + break; + // Save drawbox HwFrameIdx + memcpy(&drawbox_hwframe_tracker, + (uint8_t *)(drawbox_session_data.data.frame.p_data[3]), + sizeof(niFrameSurface1_t)); + if (out_format == GC620_I420) + ret = scaler_output_write( + &ovly_ctx, &drawbox_session_data, output_video_width, + output_video_height, out_format, p_ovly_out, disp2); + else + ret = scaler_output_write( + &fmt_ctx, &drawbox_session_data, output_video_width, + output_video_height, out_format, p_ovly_out, disp2); + if (ret != 0) + break; + if (drawbox_hwframe_tracker.ui16FrameIdx) + { + ni_hwframe_buffer_recycle( + &drawbox_hwframe_tracker, + drawbox_hwframe_tracker.device_handle); + drawbox_hwframe_tracker.ui16FrameIdx = 0; + } + + // free decoded hw frame + if (dec_hwframe_tracker.ui16FrameIdx) + { + ni_hwframe_buffer_recycle( + &dec_hwframe_tracker, + dec_hwframe_tracker.device_handle); + dec_hwframe_tracker.ui16FrameIdx = 0; + } + // free decoded frame and scaler output frame + ni_frame_buffer_free(&(out_frame.data.frame)); + ni_frame_buffer_free(&(scale_session_data.data.frame)); + ni_frame_buffer_free(&(drawbox_session_data.data.frame)); + + } else + { + ni_frame_buffer_free(&(out_frame.data.frame)); + } + } + + unsigned int time_diff = + (unsigned int)(current_time.tv_sec - start_time.tv_sec); + if (time_diff == 0) + time_diff = 1; + + printf("[R] Got: Frames= %u fps=%f Total bytes %llu\n", + number_of_frames, ((float)number_of_frames / (float)time_diff), + total_bytes_received); + + // close device + if (is_p2p) + { + if (disp1) + { + if (disp1->fd >= 0) + { + if (disp1->mmap_data != MAP_FAILED) + { + munmap((void *)disp1->mmap_data, disp1->len); + } + close(disp1->fd); + free(disp1->data); + } + free(disp1); + } + if (disp2) + { + if (disp2->fd >= 0) + { + if (disp2->mmap_data != MAP_FAILED) + { + munmap((void *)disp2->mmap_data, disp2->len); + } + close(disp2->fd); + free(disp2->data); + } + free(disp2); + } + } + + ni_device_session_close(&dec_ctx, 1, NI_DEVICE_TYPE_DECODER); + ni_device_session_close(&sca_ctx, 1, NI_DEVICE_TYPE_SCALER); + ni_device_session_close(&crop_ctx, 1, NI_DEVICE_TYPE_SCALER); + ni_device_session_close(&pad_ctx, 1, NI_DEVICE_TYPE_SCALER); + ni_device_session_close(&ovly_ctx, 1, NI_DEVICE_TYPE_SCALER); + if (fmt_ctx.device_handle != NI_INVALID_DEVICE_HANDLE) + ni_device_session_close(&fmt_ctx, 1, NI_DEVICE_TYPE_SCALER); + ni_rsrc_free_device_context(sdPara.p_dec_rsrc_ctx); + ni_rsrc_free_device_context(sdPara.p_sca_rsrc_ctx); + ni_rsrc_free_device_context(sdPara.p_crop_rsrc_ctx); + ni_rsrc_free_device_context(sdPara.p_pad_rsrc_ctx); + ni_rsrc_free_device_context(sdPara.p_ovly_rsrc_ctx); + ni_rsrc_free_device_context(sdPara.p_fmt_rsrc_ctx); + rcPara.p_dec_rsrc_ctx = NULL; + rcPara.p_sca_rsrc_ctx = NULL; + rcPara.p_crop_rsrc_ctx = NULL; + rcPara.p_pad_rsrc_ctx = NULL; + rcPara.p_ovly_rsrc_ctx = NULL; + rcPara.p_fmt_rsrc_ctx = NULL; + sdPara.p_dec_rsrc_ctx = NULL; + sdPara.p_sca_rsrc_ctx = NULL; + sdPara.p_crop_rsrc_ctx = NULL; + sdPara.p_pad_rsrc_ctx = NULL; + sdPara.p_ovly_rsrc_ctx = NULL; + sdPara.p_fmt_rsrc_ctx = NULL; + + // Recycle hwframe + if (dec_hwframe_tracker.ui16FrameIdx) + ni_hwframe_buffer_recycle(&dec_hwframe_tracker, + dec_hwframe_tracker.device_handle); + + if (scaler_hwframe_tracker.ui16FrameIdx) + ni_hwframe_buffer_recycle(&scaler_hwframe_tracker, + scaler_hwframe_tracker.device_handle); + + if (drawbox_hwframe_tracker.ui16FrameIdx) + ni_hwframe_buffer_recycle(&drawbox_hwframe_tracker, + drawbox_hwframe_tracker.device_handle); + + ni_packet_buffer_free(&(in_pkt.data.packet)); + ni_frame_buffer_free(&(out_frame.data.frame)); +#endif + } else if (mode == XCODER_APP_TRANSCODE) { printf("Xcoding Mode: %dx%d to %dx%d\n", input_video_width, @@ -4988,6 +8358,11 @@ int main(int argc, char *argv[]) ni_session_data_io_t out_packet = {0}; uint32_t prev_num_pkt; ni_frame_t *p_ni_frame = NULL; + void *p_stream_info = NULL; + if (src_codec_format == NI_CODEC_FORMAT_H264) + p_stream_info = &SPS; + else if (src_codec_format == NI_CODEC_FORMAT_H265) + p_stream_info = &HEVC_SPS; if (multi_thread) { @@ -5010,8 +8385,7 @@ int main(int argc, char *argv[]) dec_send_param.print_time = 0; // not support now dec_send_param.p_total_bytes_sent = &total_bytes_sent; dec_send_param.p_xcodeState = &xcodeState; - dec_send_param.p_SPS = &SPS; - + dec_send_param.p_stream_info = p_stream_info; dec_recv_param.p_dec_ctx = &dec_ctx; dec_recv_param.p_out_frame = NULL; dec_recv_param.output_video_width = output_video_width; @@ -5157,7 +8531,7 @@ int main(int argc, char *argv[]) api_param.hwframes = 1; //to determine if from same device and buffer dimensions in memory //needs to be done where input frame is available to check - p_hwframe = p_ni_frame->p_data[3]; + p_hwframe = (niFrameSurface1_t *)p_ni_frame->p_data[3]; enc_ctx.sender_handle = (ni_device_handle_t)(int64_t)p_hwframe->device_handle; api_param.rootBufId = p_hwframe->ui16FrameIdx; @@ -5240,7 +8614,7 @@ int main(int argc, char *argv[]) send_fin_flag = decoder_send_data( &dec_ctx, &in_pkt, sos_flag, input_video_width, input_video_height, pkt_size, total_file_size, - &total_bytes_sent, print_time, &xcodeState, &SPS); + &total_bytes_sent, print_time, &xcodeState, p_stream_info); sos_flag = 0; if (send_fin_flag == 2) //Error @@ -5404,7 +8778,7 @@ int main(int argc, char *argv[]) api_param.hwframes = 1; //to determine if from same device and buffer dimensions in memory //needs to be done where input frame is available to check - p_hwframe = out_frame.data.frame.p_data[3]; + p_hwframe = (niFrameSurface1_t *)out_frame.data.frame.p_data[3]; enc_ctx.sender_handle = (ni_device_handle_t)( int64_t)p_hwframe->device_handle; @@ -5479,11 +8853,11 @@ int main(int argc, char *argv[]) prev_num_pkt = number_of_packets; receive_fin_flag = encoder_receive_data( &enc_ctx, &out_packet, output_video_width, - output_video_height, p_file, &xcodeRecvTotal, print_time); + output_video_height, p_file, &xcodeRecvTotal, print_time, &out_frame); // out_frame is passed in for future sequence change support (XCODER_APP_TRANSCODE does not support sequence change yet) recycle_index = out_packet.data.packet.recycle_index; if (prev_num_pkt < number_of_packets && //skip if nothing read enc_ctx.hw_action && recycle_index > 0 && - recycle_index < NI_MAX_HWDESC_FRAME_INDEX) + recycle_index < NI_GET_MAX_HWDESC_FRAME_INDEX(enc_ctx.ddr_config)) //encoder only returns valid recycle index //when there's something to recycle. This range is suitable for all memory bins { @@ -5545,11 +8919,57 @@ int main(int argc, char *argv[]) end: +/* // disable as the following can't pass clang-tidy + if ((int32_t)dec_ctx.blk_io_handle != (int32_t)NI_INVALID_DEVICE_HANDLE && (int32_t)dec_ctx.device_handle !=(int32_t) NI_INVALID_DEVICE_HANDLE) + { + ni_log(NI_LOG_DEBUG, "xcoder app end - close decoder blk_io_handle %d device_handle %d\n", dec_ctx.blk_io_handle, dec_ctx.device_handle); +#ifdef _WIN32 + ni_device_close(dec_ctx.device_handle); +#elif __linux__ + ni_device_close(dec_ctx.device_handle); + ni_device_close(dec_ctx.blk_io_handle); +#endif + } + + if ((int32_t)enc_ctx.blk_io_handle != (int32_t)NI_INVALID_DEVICE_HANDLE && (int32_t)enc_ctx.device_handle != (int32_t)NI_INVALID_DEVICE_HANDLE) + { + ni_log(NI_LOG_DEBUG, "xcoder app end - close encoder blk_io_handle %d device_handle %d\n", enc_ctx.blk_io_handle, enc_ctx.device_handle); +#ifdef _WIN32 + ni_device_close(enc_ctx.device_handle); +#elif __linux__ + ni_device_close(enc_ctx.device_handle); + ni_device_close(enc_ctx.blk_io_handle); +#endif + } + + if ((int32_t)upl_ctx.blk_io_handle != (int32_t)NI_INVALID_DEVICE_HANDLE && (int32_t)upl_ctx.device_handle != (int32_t)NI_INVALID_DEVICE_HANDLE) + { + ni_log(NI_LOG_DEBUG, "xcoder app end - close uploader blk_io_handle %d device_handle %d\n", upl_ctx.blk_io_handle, upl_ctx.device_handle); +#ifdef _WIN32 + ni_device_close(upl_ctx.device_handle); +#elif __linux__ + ni_device_close(upl_ctx.device_handle); + ni_device_close(upl_ctx.blk_io_handle); +#endif + } +*/ + ni_device_session_context_clear(&dec_ctx); ni_device_session_context_clear(&enc_ctx); ni_device_session_context_clear(&upl_ctx); + ni_device_session_context_clear(&sca_ctx); + ni_device_session_context_clear(&crop_ctx); + ni_device_session_context_clear(&pad_ctx); + ni_device_session_context_clear(&ovly_ctx); + ni_device_session_context_clear(&fmt_ctx); - close(pfs); + for (input_index = 0; input_index < input_total; input_index++) + { + if (input_arg_pfs[input_index]) + { + close(input_arg_pfs[input_index]); + } + } if (p_file) { fclose(p_file); diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_test.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_test.h old mode 100644 new mode 100755 index 34de297f..b6286ba9 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_test.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_device_test.h @@ -66,20 +66,33 @@ #define XCODER_APP_DECODE 1 #define XCODER_APP_ENCODE 2 #define XCODER_APP_HWUP_ENCODE 3 +#define XCODER_APP_FILTER 4 #define ENC_CONF_STRUCT_SIZE 0x100 +#define MAX_INPUT_FILES 3 + +#define NI_TEST_RETCODE_FAILURE -1 +#define NI_TEST_RETCODE_SUCCESS 0 +#define NI_TEST_RETCODE_END_OF_STREAM 1 +#define NI_TEST_RETCODE_EAGAIN 2 +#define NI_TEST_RETCODE_NEXT_INPUT 3 +#define NI_TEST_RETCODE_SEQ_CHANGE_DONE 4 + +#define NI_ALIGN(x, a) (((x)+(a)-1)&~((a)-1)) + typedef struct _device_state { int dec_eos_sent; int dec_eos_received; int enc_eos_sent; int enc_eos_received; + int enc_seq_change; } device_state_t; typedef struct _tx_data { - char fileName[FILE_NAME_LEN]; + char fileName[MAX_INPUT_FILES][FILE_NAME_LEN]; uint32_t DataSizeLimit; int device_handle; @@ -87,9 +100,19 @@ typedef struct _tx_data ni_session_context_t *p_dec_ctx; ni_session_context_t *p_enc_ctx; ni_session_context_t *p_upl_ctx; + ni_session_context_t *p_sca_ctx; + ni_session_context_t *p_crop_ctx; + ni_session_context_t *p_pad_ctx; + ni_session_context_t *p_ovly_ctx; + ni_session_context_t *p_fmt_ctx; ni_device_context_t *p_dec_rsrc_ctx; ni_device_context_t *p_enc_rsrc_ctx; ni_device_context_t *p_upl_rsrc_ctx; + ni_device_context_t *p_sca_rsrc_ctx; + ni_device_context_t *p_crop_rsrc_ctx; + ni_device_context_t *p_pad_rsrc_ctx; + ni_device_context_t *p_ovly_rsrc_ctx; + ni_device_context_t *p_fmt_rsrc_ctx; int arg_width; int arg_height; } tx_data_t; @@ -104,14 +127,32 @@ typedef struct RecvDataStruct_ ni_session_context_t *p_dec_ctx; ni_session_context_t *p_enc_ctx; ni_session_context_t *p_upl_ctx; + ni_session_context_t *p_sca_ctx; + ni_session_context_t *p_crop_ctx; + ni_session_context_t *p_pad_ctx; + ni_session_context_t *p_ovly_ctx; + ni_session_context_t *p_fmt_ctx; ni_device_context_t *p_dec_rsrc_ctx; ni_device_context_t *p_enc_rsrc_ctx; ni_device_context_t *p_upl_rsrc_ctx; + ni_device_context_t *p_sca_rsrc_ctx; + ni_device_context_t *p_crop_rsrc_ctx; + ni_device_context_t *p_pad_rsrc_ctx; + ni_device_context_t *p_ovly_rsrc_ctx; + ni_device_context_t *p_fmt_rsrc_ctx; int arg_width; int arg_height; } rx_data_t; +typedef struct _ni_drawbox_params +{ + int box_w; + int box_h; + int box_x; + int box_y; +} box_params_t; + /** * Sequence parameter set */ @@ -181,11 +222,235 @@ typedef struct _ni_h264_sps_t size_t data_size; } ni_h264_sps_t; +#define HEVC_MAX_SUB_LAYERS 7 +#define HEVC_MAX_SHORT_TERM_REF_PIC_SETS 64 +#define HEVC_MAX_LONG_TERM_REF_PICS 32 +#define HEVC_MAX_SPS_COUNT 16 +#define HEVC_MAX_REFS 16 +#define HEVC_MAX_LOG2_CTB_SIZE 6 + +typedef struct _ni_h265_window_t +{ + unsigned int left_offset; + unsigned int right_offset; + unsigned int top_offset; + unsigned int bottom_offset; +} ni_h265_window_t; + +typedef struct VUI +{ + ni_rational_t sar; + + int overscan_info_present_flag; + int overscan_appropriate_flag; + + int video_signal_type_present_flag; + int video_format; + int video_full_range_flag; + int colour_description_present_flag; + uint8_t colour_primaries; + uint8_t transfer_characteristic; + uint8_t matrix_coeffs; + + int chroma_loc_info_present_flag; + int chroma_sample_loc_type_top_field; + int chroma_sample_loc_type_bottom_field; + int neutra_chroma_indication_flag; + + int field_seq_flag; + int frame_field_info_present_flag; + + int default_display_window_flag; + ni_h265_window_t def_disp_win; + + int vui_timing_info_present_flag; + uint32_t vui_num_units_in_tick; + uint32_t vui_time_scale; + int vui_poc_proportional_to_timing_flag; + int vui_num_ticks_poc_diff_one_minus1; + int vui_hrd_parameters_present_flag; + + int bitstream_restriction_flag; + int tiles_fixed_structure_flag; + int motion_vectors_over_pic_boundaries_flag; + int restricted_ref_pic_lists_flag; + int min_spatial_segmentation_idc; + int max_bytes_per_pic_denom; + int max_bits_per_min_cu_denom; + int log2_max_mv_length_horizontal; + int log2_max_mv_length_vertical; +} VUI; + +typedef struct PTLCommon +{ + uint8_t profile_space; + uint8_t tier_flag; + uint8_t profile_idc; + uint8_t profile_compatibility_flag[32]; + uint8_t progressive_source_flag; + uint8_t interlaced_source_flag; + uint8_t non_packed_constraint_flag; + uint8_t frame_only_constraint_flag; + uint8_t max_12bit_constraint_flag; + uint8_t max_10bit_constraint_flag; + uint8_t max_8bit_constraint_flag; + uint8_t max_422chroma_constraint_flag; + uint8_t max_420chroma_constraint_flag; + uint8_t max_monochrome_constraint_flag; + uint8_t intra_constraint_flag; + uint8_t one_picture_only_constraint_flag; + uint8_t lower_bit_rate_constraint_flag; + uint8_t max_14bit_constraint_flag; + uint8_t inbld_flag; + uint8_t level_idc; +} PTLCommon; + +typedef struct PTL +{ + PTLCommon general_ptl; + PTLCommon sub_layer_ptl[HEVC_MAX_SUB_LAYERS]; + + uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS]; + uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS]; +} PTL; + +typedef struct ScalingList +{ + /* This is a little wasteful, since sizeID 0 only needs 8 coeffs, + * and size ID 3 only has 2 arrays, not 6. */ + uint8_t sl[4][6][64]; + uint8_t sl_dc[2][6]; +} ScalingList; + +typedef struct ShortTermRPS +{ + unsigned int num_negative_pics; + int num_delta_pocs; + int rps_idx_num_delta_pocs; + int32_t delta_poc[32]; + uint8_t used[32]; +} ShortTermRPS; + +/** + * HEVC Sequence parameter set + */ +typedef struct _ni_h265_sps_t +{ + unsigned vps_id; + int chroma_format_idc; + uint8_t separate_colour_plane_flag; + + ni_h265_window_t output_window; + ni_h265_window_t pic_conf_win; + + int bit_depth; + int bit_depth_chroma; + int pixel_shift; + int pix_fmt; + + unsigned int log2_max_poc_lsb; + int pcm_enabled_flag; + + int max_sub_layers; + struct + { + int max_dec_pic_buffering; + int num_reorder_pics; + int max_latency_increase; + } temporal_layer[HEVC_MAX_SUB_LAYERS]; + uint8_t temporal_id_nesting_flag; + + VUI vui; + PTL ptl; + + uint8_t scaling_list_enable_flag; + ScalingList scaling_list; + + unsigned int nb_st_rps; + ShortTermRPS st_rps[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; + + uint8_t amp_enabled_flag; + uint8_t sao_enabled; + + uint8_t long_term_ref_pics_present_flag; + uint16_t lt_ref_pic_poc_lsb_sps[HEVC_MAX_LONG_TERM_REF_PICS]; + uint8_t used_by_curr_pic_lt_sps_flag[HEVC_MAX_LONG_TERM_REF_PICS]; + uint8_t num_long_term_ref_pics_sps; + + struct + { + uint8_t bit_depth; + uint8_t bit_depth_chroma; + unsigned int log2_min_pcm_cb_size; + unsigned int log2_max_pcm_cb_size; + uint8_t loop_filter_disable_flag; + } pcm; + uint8_t sps_temporal_mvp_enabled_flag; + uint8_t sps_strong_intra_smoothing_enable_flag; + + unsigned int log2_min_cb_size; + unsigned int log2_diff_max_min_coding_block_size; + unsigned int log2_min_tb_size; + unsigned int log2_max_trafo_size; + unsigned int log2_ctb_size; + unsigned int log2_min_pu_size; + + int max_transform_hierarchy_depth_inter; + int max_transform_hierarchy_depth_intra; + + int sps_range_extension_flag; + int transform_skip_rotation_enabled_flag; + int transform_skip_context_enabled_flag; + int implicit_rdpcm_enabled_flag; + int explicit_rdpcm_enabled_flag; + int extended_precision_processing_flag; + int intra_smoothing_disabled_flag; + int high_precision_offsets_enabled_flag; + int persistent_rice_adaptation_enabled_flag; + int cabac_bypass_alignment_enabled_flag; + + ///< coded frame dimension in various units + int width; + int height; + int ctb_width; + int ctb_height; + int ctb_size; + int min_cb_width; + int min_cb_height; + int min_tb_width; + int min_tb_height; + int min_pu_width; + int min_pu_height; + int tb_mask; + + int hshift[3]; + int vshift[3]; + + int qp_bd_offset; + + uint8_t data[4096]; + int data_size; +} ni_h265_sps_t; + +typedef struct _ni_vp9_header_info +{ + int profile; + uint16_t header_length; + uint16_t width; + uint16_t height; + struct + { + uint32_t den; + uint32_t num; + } timebase; + uint32_t total_frames; +} ni_vp9_header_info_t; + int decoder_send_data(ni_session_context_t * p_dec_ctx, ni_session_data_io_t * p_in_data, int stFlag, int input_video_width, int input_video_height, int pfs, unsigned int fileSize, unsigned long *sentTotal, - int printT, device_state_t *xState, ni_h264_sps_t *sps); + int printT, device_state_t *xState, void *stream_info); int decoder_receive_data(ni_session_context_t * p_dec_ctx, ni_session_data_io_t * p_out_data, @@ -196,7 +461,8 @@ int decoder_receive_data(ni_session_context_t * p_dec_ctx, int encoder_send_data( ni_session_context_t * p_enc_ctx, ni_session_data_io_t * p_in_data, int stFlag, int input_video_width, int input_video_height, int pfs, - unsigned int fileSize, unsigned long *sentSize, device_state_t *xState); + unsigned int fileSize, unsigned long *sentSize, device_state_t *xState, + int bit_depth, int is_last_input); int encoder_send_data2( ni_session_context_t * p_enc_ctx, uint32_t dec_codec_format, @@ -204,6 +470,34 @@ int encoder_send_data2( int stFlag, int input_video_width, int input_video_height, int pfs, unsigned int fileSize, unsigned long *sentSize, device_state_t *xState); +int encoder_close_session(ni_session_context_t *p_enc_ctx, + ni_session_data_io_t *p_in_data, + ni_session_data_io_t *p_out_data); + +int encoder_init_session(ni_session_context_t *p_enc_ctx, + ni_session_data_io_t *p_in_data, + ni_session_data_io_t *p_out_data, + int arg_width, + int arg_height, + int bit_depth); + +int encoder_sequence_change(ni_session_context_t *p_enc_ctx, + ni_session_data_io_t *p_in_data, + ni_session_data_io_t *p_out_data, + int width, + int height, + int bit_depth_factor); + +int scale_filter(ni_session_context_t * p_ctx, ni_frame_t * p_frame_in, + ni_session_data_io_t * p_data_out, int scale_width, + int scale_height, int out_format); + +int drawbox_filter( + ni_session_context_t * p_crop_ctx, ni_session_context_t * p_pad_ctx, + ni_session_context_t * p_overlay_ctx, ni_session_context_t * p_fmt_ctx, + ni_frame_t * p_frame_in, ni_session_data_io_t * p_data_out, + box_params_t * p_box_params, int output_format); + #ifdef __cplusplus } #endif diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_getopt.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_getopt.c index ce5e5638..237d12ef 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_getopt.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_getopt.c @@ -26,25 +26,26 @@ * *******************************************************************************/ -#ifdef _WIN32 - #include +#include + #include "ni_getopt.h" -TCHAR *optarg = NULL; // global argument pointer -int optind = 0; // global argv index +char *optarg = NULL; // global argument pointer +int optind = 0; // global argv index +int opterr = 1; // global erroneous switch +int optopt = 0; // global erroneous option character -int getopt(int argc, TCHAR *argv[], const TCHAR *optstring) +int getopt(int argc, char *argv[], const char *optstring) { - static TCHAR *nextchar = NULL; + static char *nextchar = NULL; - if (nextchar == NULL || nextchar == _T('\0')) + if (nextchar == NULL || *nextchar == '\0') { if (optind == 0) optind++; - if (optind >= argc || argv[optind][0] != _T('-') || - argv[optind][1] == _T('\0')) + if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') { optarg = NULL; if (optind < argc) @@ -52,7 +53,7 @@ int getopt(int argc, TCHAR *argv[], const TCHAR *optstring) return EOF; } - if (_tcsncmp(argv[optind], _T("--"), _tcslen(_T("--"))) == 0) + if (strncmp(argv[optind], "--", strlen("--")) == 0) { optind++; optarg = NULL; @@ -62,68 +63,78 @@ int getopt(int argc, TCHAR *argv[], const TCHAR *optstring) } nextchar = argv[optind]; - nextchar += _tcslen(_T("-")); + nextchar += strlen("-"); optind++; } - TCHAR c = *nextchar++; - TCHAR *cp = _tcschr(optstring, c); - - if (cp == NULL || c == _T(':')) - return _T('?'); + char c = *nextchar++; + char *cp = strchr(optstring, c); + optopt = (int)c; + if (cp == NULL || c == ':') + { + return '?'; + } cp++; - if (*cp == _T(':')) + if (*cp == ':') { - if (*nextchar != _T('\0')) + if (*nextchar != '\0') { optarg = nextchar; - nextchar = NULL; // for next invocation - } else if (optind < argc) + nextchar = NULL; // for next invocation + } + else if (optind < argc) { optarg = argv[optind]; optind++; - } else + } + else { - return _T('?'); + return '?'; } } return c; } -int getopt_long(int argc, TCHAR *argv[], const TCHAR *optstring, - const struct option *longopts, int *longindex) + +int getopt_long(int argc, char* argv[], const char* optstring, + const struct option* longopts, int* longindex) { - int i; - static TCHAR *nextchar = NULL; + int i, parse_long_mismatch = 0; + static char* nextchar = NULL; - if (nextchar == NULL || *nextchar == _T('\0')) + if (nextchar == NULL || *nextchar == '\0') { if (optind == 0) { optind++; } - if (optind >= argc || argv[optind][0] != _T('-') || - argv[optind][1] == _T('\0')) + if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') { optarg = NULL; if (optind < argc) + { optarg = argv[optind]; + } return EOF; } nextchar = argv[optind]; - if (_tcsncmp(argv[optind], _T("--"), 2) == 0) + if (strncmp(argv[optind], "--", 2) == 0) { - nextchar += _tcslen(_T("--")); + parse_long_mismatch = 1; + nextchar += strlen("--"); optarg = NULL; if (optind < argc) + { optarg = argv[optind]; - } else + } + } + else { - nextchar += _tcslen(_T("-")); + nextchar += strlen("-"); } optind++; @@ -132,79 +143,102 @@ int getopt_long(int argc, TCHAR *argv[], const TCHAR *optstring, // Parse long option string for (i = 0; longopts != NULL && longopts[i].name != NULL; i++) { - size_t optlen = _tcslen(_T(longopts[i].name)); - if (_tcsncmp(nextchar, _T(longopts[i].name), optlen) == 0) + size_t optlen = strlen(longopts[i].name); + if (strncmp(nextchar, longopts[i].name, optlen) == 0) { - optarg = nextchar + optlen; + nextchar += optlen; switch (longopts[i].has_arg) { - case 0: - if (*optarg != _T('\0') || argv[optind][0] != _T('-')) - { - return _T('?'); - } else - { - return longopts[i].flag == NULL ? longopts[i].val : 0; - } - case 1: - if (*optarg == _T('=')) - { - optarg += _tcslen(_T("=")); - return longopts[i].flag == NULL ? longopts[i].val : 0; - } else if (*optarg != _T('\0') || - argv[optind][0] == _T('-')) - { - return _T('?'); - } else + case 0: + if (*nextchar != '\0' || (optind < argc && argv[optind][0] != '-')) + { + optind++; + return '?'; + } + else + { + optind++; + return longopts[i].flag == NULL ? longopts[i].val : 0; + } + case 1: + if (*nextchar == '=') + { + optarg = nextchar + 1; + optind++; + return longopts[i].flag == NULL ? longopts[i].val : 0; + } + else if (*nextchar != '\0' || (optind < argc && argv[optind][0] == '-')) + { + optind++; + return '?'; + } + else if (optind < argc) + { + optarg = argv[optind]; + optind++; + return longopts[i].flag == NULL ? longopts[i].val : 0; + } + else + { + return '?'; + } + case 2: + if (*nextchar == '=') + { + optarg = nextchar + 1; + } + else if (*nextchar == '\0' || (optind < argc && argv[optind][0] == '-')) + { + optarg = NULL; + } + else + { + if (*nextchar == '\0' && optind < argc) { optarg = argv[optind]; - return longopts[i].flag == NULL ? longopts[i].val : 0; - } - case 2: - if (*optarg == _T('\0') || argv[optind][0] == _T('-')) - { - optarg = NULL; - } else - { - if (*optarg == _T('\0')) - { - optarg = argv[optind]; - } } - return longopts[i].flag == NULL ? longopts[i].val : 0; - default: - return _T('?'); + } + optind++; + return longopts[i].flag == NULL ? longopts[i].val : 0; + default: + return '?'; } } } - // Parse short option string - TCHAR c = *nextchar++; - TCHAR *cp = _tcschr(optstring, c); + if (parse_long_mismatch) + { + return '?'; + } - if (cp == NULL || c == _T(':')) + // Parse short option string + char c = *nextchar++; + char* cp = strchr(optstring, c); + optopt = (int)c; + if (cp == NULL || c == ':') { - return _T('?'); + return '?'; } cp++; // Whether there is any argument - if (*cp == _T(':')) + if (*cp == ':') { - if (*nextchar != _T('\0')) + if (*nextchar != '\0') { optarg = nextchar; - nextchar = NULL; // for next invocation - } else if (optind < argc) + nextchar = NULL; // for next invocation + } + else if (optind < argc) { optarg = argv[optind]; optind++; - } else + } + else { - return _T('?'); + return '?'; } } return c; } -#endif diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_getopt.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_getopt.h index ca9516fd..e1d85dd3 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_getopt.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_getopt.h @@ -28,14 +28,27 @@ #pragma once -#include - #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -extern int optind, opterr, optopt; -extern TCHAR *optarg; +#ifdef _WIN32 +#ifdef XCODER_DLL +#ifdef LIB_EXPORTS +#define LIB_API_GETOPT __declspec(dllexport) +#else +#define LIB_API_GETOPT __declspec(dllimport) +#endif +#else +#define LIB_API_GETOPT +#endif +#elif __linux__ || __APPLE__ +#define LIB_API_GETOPT +#endif + +extern LIB_API_GETOPT int optind, opterr, optopt; +extern LIB_API_GETOPT char *optarg; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector @@ -70,14 +83,13 @@ struct option /* Names for the values of the 'has_arg' field of 'struct option'. */ -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 -int getopt(int argc, TCHAR *argv[], const TCHAR *optstring); -int getopt_long(int argc, TCHAR *argv[], const TCHAR *optstring, - const struct option *longopts, int *longindex); +extern LIB_API_GETOPT int getopt(int argc, char *argv[], const char *optstring); +extern LIB_API_GETOPT int getopt_long(int argc, char* argv[], const char* optstring, const struct option *longopts, int *longindex); #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_lat_meas.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_lat_meas.c new file mode 100644 index 00000000..075147c9 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_lat_meas.c @@ -0,0 +1,241 @@ +/******************************************************************************* + * + * Copyright (C) 2022 NETINT Technologies + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ******************************************************************************/ + +/*!***************************************************************************** +* \file ni_lat_meas.c +* +* \brief utility functions for measuring frame latency +* +*******************************************************************************/ + +#ifdef __linux__ +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "ni_lat_meas.h" +#include "ni_log.h" +#include "ni_util.h" + +/*!***************************************************************************** + * \brief Create a latency measurement queue object of a given capacity + * + * \param capacity maximum size of queue + * + * \return ni_lat_meas_q_t latency measurement queue structure + * + ******************************************************************************/ +ni_lat_meas_q_t *ni_lat_meas_q_create(int capacity) +{ + if (1 > capacity) + { + ni_log(NI_LOG_ERROR, + "ERROR: ni_lat_meas_q_create() called with capacity less than 1" + "\n"); + return NULL; + } + + ni_lat_meas_q_t *queue = (ni_lat_meas_q_t *)malloc(sizeof(ni_lat_meas_q_t)); + if (!queue) + { + ni_log(NI_LOG_ERROR, + "ERROR %d: Failed to allocate memory for " + "lat_meas-queue queue\n", + NI_ERRNO); + return NULL; + } + queue->capacity = capacity; + queue->front = queue->size = 0; + queue->rear = capacity - 1; + queue->array = (ni_lat_meas_q_entry_t *)malloc( + queue->capacity * sizeof(ni_lat_meas_q_entry_t)); + if (!queue->array) + { + ni_log(NI_LOG_ERROR, + "ERROR %d: Failed to allocate memory for " + "lat_meas_queue queue->array\n", + NI_ERRNO); + free(queue); + return NULL; + } + return queue; +} + +/*!***************************************************************************** + * \brief Destroy a latency measurement queue object + * + * \param frame_time_q pointer to ni_lat_meas_q_t object + * + * \return + * + ******************************************************************************/ +void ni_lat_meas_q_destroy(ni_lat_meas_q_t *frame_time_q) +{ + free(frame_time_q->array); + free(frame_time_q); +} + +/*!***************************************************************************** + * \brief Push an item onto the queue + * + * \param queue pointer to latency queue + * \param item ni_lat_meas_q_entry_t item to push onto the queue + * + * \return void 1 if success, NULL if failed + * + ******************************************************************************/ +void *ni_lat_meas_q_enqueue(ni_lat_meas_q_t *queue, ni_lat_meas_q_entry_t item) +{ + if (queue->size == queue->capacity) + { + return NULL; + } + queue->rear = (queue->rear + 1) % queue->capacity; + queue->array[queue->rear] = item; + queue->size = queue->size + 1; + return (void *)1; +} + +/*!***************************************************************************** + * \brief Pop an item from the queue + * + * \param queue pointer to latency queue + * + * \return void pointer to popped item + * + ******************************************************************************/ +void *ni_lat_meas_q_dequeue(ni_lat_meas_q_t *queue) +{ + ni_lat_meas_q_entry_t *dequeue_item; + if (queue->size == 0) + { + return NULL; + } + dequeue_item = &queue->array[queue->front]; + queue->front = (queue->front + 1) % queue->capacity; + queue->size = queue->size - 1; + return dequeue_item; +} + +/*!***************************************************************************** + * \brief Get a pointer to rear of queue + * + * \param queue pointer to latency queue + * + * \return void pointer to rear of queue + * + ******************************************************************************/ +void *ni_lat_meas_q_rear(ni_lat_meas_q_t *queue) +{ + return queue->size == 0 ? NULL : &queue->array[queue->rear]; +} + +/*!***************************************************************************** + * \brief Get a pointer to front of queue + * + * \param queue pointer to latency queue + * + * \return void pointer to front of queue + * + ******************************************************************************/ +void *ni_lat_meas_q_front(ni_lat_meas_q_t *queue) +{ + return queue->size == 0 ? NULL : &queue->array[queue->front]; +} + +/*!***************************************************************************** + * \brief Add a new entry to latency queue + * + * \param frame_time_q pointer to latency queue + * \param abs_time frame start time for latency comparison + * \param ts_time reference frame timestamp time + * + * \return void 1 if success, NULL if failed + * + ******************************************************************************/ +void *ni_lat_meas_q_add_entry(ni_lat_meas_q_t *frame_time_q, uint64_t abs_time, + int64_t ts_time) +{ + // ni_log(NI_LOG_DEBUG, "ni_lat_meas_q_add_entry abs_time=%lu ts_time=" + // "%ld\n", abs_time, ts_time); + ni_lat_meas_q_entry_t entry = {.abs_timenano = abs_time, + .ts_time = ts_time}; + return ni_lat_meas_q_enqueue(frame_time_q, entry); +} + +/*!***************************************************************************** + * \brief Check latency of a frame referenced by its timestamp + * + * \param frame_time_q pointer to latency queue + * \param abs_time frame end time for latency comparison + * \param ts_time reference frame timestamp time + * + * \return uint64_t value of latency if suceeded, -1 if failed + * + ******************************************************************************/ +uint64_t ni_lat_meas_q_check_latency(ni_lat_meas_q_t *frame_time_q, + uint64_t abs_time, int64_t ts_time) +{ + // ni_log(NI_LOG_DEBUG, "ni_lat_meas_q_check_latency abs_time=%lu ts_time=" + // "%ld\n", abs_time, ts_time); + uint32_t dequeue_count = 0; + ni_lat_meas_q_entry_t *entry = ni_lat_meas_q_front(frame_time_q); + + if (entry == NULL) + { + return -1; + } + + if (entry->ts_time == ts_time) + { + ni_lat_meas_q_dequeue(frame_time_q); + dequeue_count++; + } else + { // queue miss, perhaps frame was not decoded properly or TS was offset + while (entry->ts_time < ts_time) + { + entry = ni_lat_meas_q_dequeue(frame_time_q); + dequeue_count++; + if (entry == NULL) + { + return -1; + } + } + } + ni_log(NI_LOG_DEBUG, "DQ_CNT:%u,QD:%d", dequeue_count, frame_time_q->size); + + if ((entry == NULL) || (entry->ts_time > ts_time)) + { // queue overrun OR + // queue miss, perhaps frame was not enqueued properly or TS was offset + return -1; + } else if (entry->ts_time == ts_time) + { // queue item is perfectly matched, calculate latency + return (abs_time - entry->abs_timenano); + } + + return -1; +} diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_lat_meas.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_lat_meas.h new file mode 100644 index 00000000..0910871c --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_lat_meas.h @@ -0,0 +1,54 @@ +/******************************************************************************* + * + * Copyright (C) 2022 NETINT Technologies + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ******************************************************************************/ + +/*!***************************************************************************** +* \file ni_lat_meas.h +* +* \brief utility functions for measuring frame latency +* +*******************************************************************************/ + +#pragma once + +#include + +typedef struct _ni_lat_meas_q_entry_t +{ + uint64_t abs_timenano; + int64_t ts_time; +} ni_lat_meas_q_entry_t; + +typedef struct _ni_lat_meas_q_t +{ + int front, rear, size, capacity; + ni_lat_meas_q_entry_t *array; +} ni_lat_meas_q_t; + +// NI latency measurement queue operations +ni_lat_meas_q_t *ni_lat_meas_q_create(int capacity); + +void ni_lat_meas_q_destroy(ni_lat_meas_q_t *frame_time_q); + +void *ni_lat_meas_q_add_entry(ni_lat_meas_q_t *frame_time_q, uint64_t abs_time, + int64_t ts_time); + +uint64_t ni_lat_meas_q_check_latency(ni_lat_meas_q_t *frame_time_q, + uint64_t abs_time, int64_t ts_time); \ No newline at end of file diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_libxcoder_dynamic_loading.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_libxcoder_dynamic_loading.h new file mode 100644 index 00000000..3d7ca7a8 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_libxcoder_dynamic_loading.h @@ -0,0 +1,388 @@ +/******************************************************************************* + * + * Copyright (C) 2022 NETINT Technologies + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ******************************************************************************/ + +/*!***************************************************************************** +* \file ni_libxcoder_dynamic_loading.h +* +* \brief Libxcoder API dynamic loading support for Linux +* +* \author Netflix, Inc. (2022) +* +*******************************************************************************/ + +#pragma once + +#ifndef _NETINTLIBXCODERAPI_H_ +#define _NETINTLIBXCODERAPI_H_ + +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" + +#ifndef _NETINT_LIBXCODER_DYNAMIC_LOADING_TEST_ +#include +#include +#include +#else +#include "ni_av_codec.h" +#include "ni_util.h" +#include "ni_device_api.h" +#endif + +#pragma GCC diagnostic pop + +#define LIB_API + +/* + * Defines API function pointers + */ +// +// Function pointers for ni_av_codec.h +// +typedef int (LIB_API* PNISHOULDSENDSEIWITHFRAME) (ni_session_context_t *p_enc_ctx, ni_pic_type_t pic_type, ni_xcoder_params_t *p_param); +typedef void (LIB_API* PNIDECRETRIEVEAUXDATA) (ni_frame_t *frame); +typedef void (LIB_API* PNIENCPREPAUXDATA) (ni_session_context_t *p_enc_ctx, ni_frame_t *p_enc_frame, ni_frame_t *p_dec_frame, ni_codec_format_t codec_format, int should_send_sei_with_frame, uint8_t *mdcv_data, uint8_t *cll_data, uint8_t *cc_data, uint8_t *udu_data, uint8_t *hdrp_data); +typedef void (LIB_API* PNIENCCOPYAUXDATA) (ni_session_context_t *p_enc_ctx, ni_frame_t *p_enc_frame, ni_frame_t *p_dec_frame, ni_codec_format_t codec_format, const uint8_t *mdcv_data, const uint8_t *cll_data, const uint8_t *cc_data, const uint8_t *udu_data, const uint8_t *hdrp_data, int is_hwframe, int is_nv12frame); +// +// Function pointers for ni_util.h +// +typedef void (LIB_API* PNIGETHWYUV420PDIM) (int width, int height, int bit_depth_factor, int is_nv12, int plane_stride[NI_MAX_NUM_DATA_POINTERS], int plane_height[NI_MAX_NUM_DATA_POINTERS]); +typedef void (LIB_API* PNICOPYHWYUV420P) (uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS], int width, int height, int bit_depth_factor, int is_nv12, int conf_win_right, int dst_stride[NI_MAX_NUM_DATA_POINTERS], int dst_height[NI_MAX_NUM_DATA_POINTERS], int src_stride[NI_MAX_NUM_DATA_POINTERS], int src_height[NI_MAX_NUM_DATA_POINTERS]); +typedef int (LIB_API* PNIINSERTEMULATIONPREVENTBYTES) (uint8_t *buf, int size); +typedef int (LIB_API* PNIREMOVEEMULATIONPREVENTBYTES) (uint8_t *buf, int size); +typedef int32_t (LIB_API* PNIGETTIMEOFDAY) (struct timeval *p_tp, void *p_tzp); +typedef uint64_t (LIB_API* PNIGETTIMENS) (void); +typedef void (LIB_API* PNIUSLEEP) (int64_t usec); +typedef ni_retcode_t (LIB_API* PNINETWORKLAYERCONVERTOUTPUT) (float *dst, uint32_t num, ni_packet_t *p_packet, ni_network_data_t *p_network, uint32_t layer); +typedef uint32_t (LIB_API* PNIAINETWORKLAYERSIZE) (ni_network_layer_params_t *p_param); +typedef uint32_t (LIB_API* PNIAINETWORKLAYERDIMS) (ni_network_layer_params_t *p_param); +typedef ni_retcode_t (LIB_API* PNINETWORKLAYERCONVERTTENSOR) (uint8_t *dst, uint32_t dst_len, const char *tensor_file, ni_network_layer_params_t *p_param); +typedef ni_retcode_t (LIB_API* PNINETWORKCONVERTTENSORTODATA) (uint8_t *dst, uint32_t dst_len, float *src, uint32_t src_len, ni_network_layer_params_t *p_param); +typedef ni_retcode_t (LIB_API* PNINETWORKCONVERTDATATOTENSOR) (float *dst, uint32_t dst_len, uint8_t *src, uint32_t src_len, ni_network_layer_params_t *p_param); +typedef void (LIB_API* PNICALCULATESHA256) (const uint8_t aui8Data[], size_t ui32DataLength, uint8_t aui8Hash[]); +typedef void (LIB_API* PNICOPYHWDESCRIPTORS) (uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS]); +typedef char* (LIB_API* PNIGETLIBXCODERAPIVER) (void); +typedef char* (LIB_API* PNIGETCOMPATFWAPIVER) (void); +typedef char* (LIB_API* PNIGETLIBXCODERRELEASEVER) (void); +// +// Function pointers for ni_device_api.h +// +typedef ni_session_context_t * (LIB_API* PNIDEVICESESSIONCONTEXTALLOCINIT) (void); +typedef ni_retcode_t (LIB_API* PNIDEVICESESSIONCONTEXTINIT) (ni_session_context_t *p_ctx); +typedef void (LIB_API* PNIDEVICESESSIONCONTEXTCLEAR) (ni_session_context_t *p_ctx); +typedef void (LIB_API* PNIDEVICESESSIONCONTEXTFREE) (ni_session_context_t *p_ctx); +typedef ni_event_handle_t (LIB_API* PNICREATEEVENT) (); +typedef void (LIB_API* PNICLOSEEVENT) (ni_event_handle_t event_handle); +typedef ni_device_handle_t (LIB_API* PNIDEVICEOPEN) (const char *dev, uint32_t *p_max_io_size_out); +typedef void (LIB_API* PNIDEVICECLOSE) (ni_device_handle_t dev); +typedef ni_retcode_t (LIB_API* PNIDEVICECAPABILITYQUERY) (ni_device_handle_t device_handle, ni_device_capability_t *p_cap); +typedef ni_retcode_t (LIB_API* PNIDEVICESESSIONOPEN) (ni_session_context_t *p_ctx, ni_device_type_t device_type); +typedef ni_retcode_t (LIB_API* PNIDEVICESESSIONCLOSE) (ni_session_context_t *p_ctx, int eos_received, ni_device_type_t device_type); +typedef ni_retcode_t (LIB_API* PNIDEVICESESSIONFLUSH) (ni_session_context_t *p_ctx, ni_device_type_t device_type); +typedef ni_retcode_t (LIB_API* PNIDEVICEDECSESSIONSAVEHDRS) (ni_session_context_t *p_ctx, uint8_t *hdr_data, uint8_t hdr_size); +typedef ni_retcode_t (LIB_API* PNIDEVICEDECSESSIONFLUSH) (ni_session_context_t *p_ctx); +typedef int (LIB_API* PNIDEVICESESSIONWRITE) (ni_session_context_t *p_ctx, ni_session_data_io_t *p_data, ni_device_type_t device_type); +typedef int (LIB_API* PNIDEVICESESSIONREAD) (ni_session_context_t *p_ctx, ni_session_data_io_t *p_data, ni_device_type_t device_type); +typedef ni_retcode_t (LIB_API* PNIDEVICESESSIONQUERY) (ni_session_context_t *p_ctx, ni_device_type_t device_type); +typedef ni_retcode_t (LIB_API* PNIFRAMEBUFFERALLOC) (ni_frame_t *p_frame, int video_width, int video_height, int alignment, int metadata_flag, int factor, int hw_frame_count, int is_planar); +typedef ni_retcode_t (LIB_API* PNIDECODERFRAMEBUFFERALLOC) (ni_buf_pool_t *p_pool, ni_frame_t *pframe, int alloc_mem, int video_width, int video_height, int alignment, int factor, int is_planar); +typedef ni_retcode_t (LIB_API* PNIENCODERFRAMEBUFFERALLOC) (ni_frame_t *pframe, int video_width, int video_height, int linesize[], int alignment, int extra_len, bool alignment_2pass_wa); +typedef ni_retcode_t (LIB_API* PNIFRAMEBUFFERALLOCNV) (ni_frame_t *p_frame, int video_width, int video_height, int linesize[], int extra_len, bool alignment_2pass_wa); +typedef ni_retcode_t (LIB_API* PNIENCODERSWFRAMEBUFFERALLOC) (bool planar, ni_frame_t *p_frame, int video_width, int video_height, int linesize[], int alignment, int extra_len, bool alignment_2pass_wa); +typedef ni_retcode_t (LIB_API* PNIFRAMEBUFFERFREE) (ni_frame_t *pframe); +typedef ni_retcode_t (LIB_API* PNIDECODERFRAMEBUFFERFREE) (ni_frame_t *pframe); +typedef void (LIB_API* PNIDECODERFRAMEBUFFERPOOLRETURNBUF) (ni_buf_t *buf, ni_buf_pool_t *p_buffer_pool); +typedef ni_retcode_t (LIB_API* PNIPACKETBUFFERALLOC) (ni_packet_t *ppacket, int packet_size); +typedef ni_retcode_t (LIB_API* PNICUSTOMPACKETBUFFERALLOC) (void *p_buffer, ni_packet_t *p_packet, int buffer_size); +typedef ni_retcode_t (LIB_API* PNIPACKETBUFFERFREE) (ni_packet_t *ppacket); +typedef ni_retcode_t (LIB_API* PNIPACKETBUFFERFREEAV1) (ni_packet_t *ppacket); +typedef int (LIB_API* PNIPACKETCOPY) (void *p_destination, const void *const p_source, int cur_size, void *p_leftover, int *p_prev_size); +typedef ni_aux_data_t * (LIB_API* PNIFRAMENEWAUXDATA) (ni_frame_t *frame, ni_aux_data_type_t type, int data_size); +typedef ni_aux_data_t * (LIB_API* PNIFRAMENEWAUXDATAFROMRAWDATA) (ni_frame_t *frame, ni_aux_data_type_t type, const uint8_t *raw_data, int data_size); +typedef ni_aux_data_t * (LIB_API* PNIFRAMEGETAUXDATA) (const ni_frame_t *frame, ni_aux_data_type_t type); +typedef void (LIB_API* PNIFRAMEFREEAUXDATA) (ni_frame_t *frame, ni_aux_data_type_t type); +typedef void (LIB_API* PNIFRAMEWIPEAUXDATA) (ni_frame_t *frame); +typedef ni_retcode_t (LIB_API* PNIENCODERINITDEFAULTPARAMS) (ni_xcoder_params_t *p_param, int fps_num, int fps_denom, long bit_rate, int width, int height, ni_codec_format_t codec_format); +typedef ni_retcode_t (LIB_API* PNIDECODERINITDEFAULTPARAMS) (ni_xcoder_params_t *p_param, int fps_num, int fps_denom, long bit_rate, int width, int height); +typedef ni_retcode_t (LIB_API* PNIENCODERPARAMSSETVALUE) (ni_xcoder_params_t *p_params, const char *name, const char *value); +typedef ni_retcode_t (LIB_API* PNIDECODERPARAMSSETVALUE) (ni_xcoder_params_t *p_params, const char *name, char *value); +typedef ni_retcode_t (LIB_API* PNIENCODERGOPPARAMSSETVALUE) (ni_xcoder_params_t *p_params, const char *name, const char *value); +typedef ni_retcode_t (LIB_API* PNIDEVICESESSIONCOPY) (ni_session_context_t *src_p_ctx, ni_session_context_t *dst_p_ctx); +typedef int (LIB_API* PNIDEVICESESSIONINITFRAMEPOOL) (ni_session_context_t *p_ctx, uint32_t pool_size, uint32_t pool); +typedef int (LIB_API* PNIDEVICESESSIONREADHWDESC) (ni_session_context_t *p_ctx, ni_session_data_io_t *p_data, ni_device_type_t device_type); +typedef int (LIB_API* PNIDEVICESESSIONHWDL) (ni_session_context_t *p_ctx, ni_session_data_io_t *p_data, niFrameSurface1_t *hwdesc); +typedef int (LIB_API* PNIDEVICESESSIONHWUP) (ni_session_context_t* p_ctx, ni_session_data_io_t *p_src_data, niFrameSurface1_t* hwdesc); +typedef ni_retcode_t (LIB_API* PNIFRAMEBUFFERALLOCHWENC) (ni_frame_t *pframe, int video_width, int video_height, int extra_len); +typedef ni_retcode_t (LIB_API* PNIHWFRAMEBUFFERRECYCLE) (niFrameSurface1_t *surface, int32_t device_handle); +typedef ni_retcode_t (LIB_API* PNISCALERSETPARAMS) (ni_session_context_t *p_ctx, ni_scaler_params_t *p_params); +typedef ni_retcode_t (LIB_API* PNIDEVICEALLOCFRAME) (ni_session_context_t* p_ctx, int width, int height, int format, int options, int rectangle_width, int rectangle_height, int rectangle_x, int rectangle_y, int rgba_color, int frame_index, ni_device_type_t device_type); +typedef ni_retcode_t (LIB_API* PNIDEVICECONFIGFRAME) (ni_session_context_t *p_ctx, ni_frame_config_t *p_cfg); +typedef ni_retcode_t (LIB_API* PNIFRAMEBUFFERALLOCPIXFMT) (ni_frame_t *pframe, int pixel_format, int video_width, int video_height, int linesize[], int alignment, int extra_len); +typedef ni_retcode_t (LIB_API* PNIAICONFIGNETWORKBINARY) (ni_session_context_t *p_ctx, ni_network_data_t *p_network, const char *file); +typedef ni_retcode_t (LIB_API* PNIAIFRAMEBUFFERALLOC) (ni_frame_t *p_frame, ni_network_data_t *p_network); +typedef ni_retcode_t (LIB_API* PNIAIPACKETBUFFERALLOC) (ni_packet_t *p_packet, ni_network_data_t *p_network); +typedef ni_retcode_t (LIB_API* PNIRECONFIGBITRATE) (ni_session_context_t *p_ctx, int32_t bitrate); +typedef ni_retcode_t (LIB_API* PNIFORCEIDRFRAMETYPE) (ni_session_context_t *p_ctx); +typedef ni_retcode_t (LIB_API* PNISETLTR) (ni_session_context_t *p_ctx, ni_long_term_ref_t *ltr); +typedef ni_retcode_t (LIB_API* PNISETLTRINTERVAL) (ni_session_context_t *p_ctx, int32_t ltr_interval); +typedef ni_retcode_t (LIB_API* PNISETFRAMEREFINVALID) (ni_session_context_t *p_ctx, int32_t frame_num); +typedef ni_retcode_t (LIB_API* PNIRECONFIGFRAMERATE) (ni_session_context_t *p_ctx, ni_framerate_t *framerate); +typedef int (LIB_API* PNIDEVICESESSIONACQUIRE) (ni_session_context_t *p_upl_ctx, ni_frame_t *p_frame); +typedef ni_retcode_t (LIB_API* PNIUPLOADERFRAMEBUFFERLOCK) (ni_session_context_t *p_upl_ctx, ni_frame_t *p_frame); +typedef ni_retcode_t (LIB_API* PNIUPLOADERFRAMEBUFFERUNLOCK) (ni_session_context_t *p_upl_ctx, ni_frame_t *p_frame); +typedef ni_retcode_t (LIB_API* PNIUPLOADERP2PTESTSEND) (ni_session_context_t *p_upl_ctx, uint8_t *p_data, uint32_t len, ni_frame_t *p_hwframe); +typedef ni_retcode_t (LIB_API* PNIENCODERSETINPUTFRAMEFORMAT) (ni_session_context_t *p_enc_ctx, ni_xcoder_params_t *p_enc_params, int width, int height, int bit_depth, int src_endian, int planar); +typedef ni_retcode_t (LIB_API* PNIUPLOADERSETFRAMEFORMAT) (ni_session_context_t *p_upl_ctx, int width, int height, ni_pix_fmt_t pixel_format, int isP2P); +typedef ni_retcode_t (LIB_API* PNIHWFRAMEP2PBUFFERRECYCLE) (ni_frame_t *p_frame); +typedef int (LIB_API* PNIENCODERSESSIONREADSTREAMHEADER) (ni_session_context_t *p_ctx, ni_session_data_io_t *p_data); +typedef int32_t (LIB_API* PNIGETDMABUFFILEDESCRIPTOR) (const ni_frame_t* p_frame); +typedef ni_retcode_t (LIB_API* PNIDEVICESESSIONSEQUENCECHANGE) (ni_session_context_t *p_ctx, int width, int height, int bit_depth_factor, ni_device_type_t device_type); + +/* End API function pointers */ + + + +/* + * Definition of _NETINT_LIBXCODER_API_FUNCTION_LIST + */ +typedef struct _NETINT_LIBXCODER_API_FUNCTION_LIST +{ + // + // API function list for ni_av_codec.h + // + PNISHOULDSENDSEIWITHFRAME niShouldSendSeiWithFrame; /** Client should access ::ni_should_send_sei_with_frame API through this pointer */ + PNIDECRETRIEVEAUXDATA niDecRetrieveAuxData; /** Client should access ::ni_dec_retrieve_aux_data API through this pointer */ + PNIENCPREPAUXDATA niEncPrepAuxData; /** Client should access ::ni_enc_prep_aux_data API through this pointer */ + PNIENCCOPYAUXDATA niEncCopyAuxData; /** Client should access ::ni_enc_copy_aux_data API through this pointer */ + // + // API function list for ni_util.h + // + PNIGETHWYUV420PDIM niGetHwYuv420PDim; /** Client should access ::ni_get_hw_yuv420p_dim API through this pointer */ + PNICOPYHWYUV420P niCopyHwYuv420P; /** Client should access ::ni_copy_hw_yuv420p API through this pointer */ + PNIINSERTEMULATIONPREVENTBYTES niInsertEmulationPreventBytes; /** Client should access ::ni_insert_emulation_prevent_bytes API through this pointer */ + PNIREMOVEEMULATIONPREVENTBYTES niRemoveEmulationPreventBytes; /** Client should access ::ni_remove_emulation_prevent_bytes API through this pointer */ + PNIGETTIMEOFDAY niGettimeofday; /** Client should access ::ni_gettimeofday API through this pointer */ + PNIGETTIMENS niGettimeNs; /** Client should access ::ni_gettime_ns API through this pointer */ + PNIUSLEEP niUsleep; /** Client should access ::ni_usleep API through this pointer */ + PNINETWORKLAYERCONVERTOUTPUT niNetworkLayerConvertOutput; /** Client should access ::ni_network_layer_convert_output API through this pointer */ + PNIAINETWORKLAYERSIZE niAiNetworkLayerSize; /** Client should access ::ni_ai_network_layer_size API through this pointer */ + PNIAINETWORKLAYERDIMS niAiNetworkLayerDims; /** Client should access ::ni_ai_network_layer_dims API through this pointer */ + PNINETWORKLAYERCONVERTTENSOR niNetworkLayerConvertTensor; /** Client should access ::ni_network_layer_convert_tensor API through this pointer */ + PNINETWORKCONVERTTENSORTODATA niNetworkConvertTensorToData; /** Client should access ::ni_network_convert_tensor_to_data API through this pointer */ + PNINETWORKCONVERTDATATOTENSOR niNetworkConvertDataToTensor; /** Client should access ::ni_network_convert_data_to_tensor API through this pointer */ + PNICALCULATESHA256 niCalculateSha256; /** Client should access ::ni_calculate_sha256 API through this pointer */ + PNICOPYHWDESCRIPTORS niCopyHwDescriptors; /** Client should access ::ni_copy_hw_descriptors API through this pointer */ + PNIGETLIBXCODERAPIVER niGetLibxcoderApiVer; /** Client should access ::ni_get_libxcoder_api_ver API through this pointer */ + PNIGETCOMPATFWAPIVER niGetCompatFwApiVer; /** Client should access ::ni_get_compat_fw_api_ver API through this pointer */ + PNIGETLIBXCODERRELEASEVER niGetLibxcoderReleaseVer; /** Client should access ::ni_get_libxcoder_release_ver API through this pointer */ + // + // API function list for ni_device_api.h + // + PNIDEVICESESSIONCONTEXTALLOCINIT niDeviceSessionContextAllocInit; /** Client should access ::ni_device_session_context_alloc_init API through this pointer */ + PNIDEVICESESSIONCONTEXTINIT niDeviceSessionContextInit; /** Client should access ::ni_device_session_context_init API through this pointer */ + PNIDEVICESESSIONCONTEXTCLEAR niDeviceSessionContextClear; /** Client should access ::ni_device_session_context_clear API through this pointer */ + PNIDEVICESESSIONCONTEXTFREE niDeviceSessionContextFree; /** Client should access ::ni_device_session_context_free API through this pointer */ + PNICREATEEVENT niCreateEvent; /** Client should access ::ni_create_event API through this pointer */ + PNICLOSEEVENT niCloseEvent; /** Client should access ::ni_close_event API through this pointer */ + PNIDEVICEOPEN niDeviceOpen; /** Client should access ::ni_device_open API through this pointer */ + PNIDEVICECLOSE niDeviceClose; /** Client should access ::ni_device_close API through this pointer */ + PNIDEVICECAPABILITYQUERY niDeviceCapabilityQuery; /** Client should access ::ni_device_capability_query API through this pointer */ + PNIDEVICESESSIONOPEN niDeviceSessionOpen; /** Client should access ::ni_device_session_open API through this pointer */ + PNIDEVICESESSIONCLOSE niDeviceSessionClose; /** Client should access ::ni_device_session_close API through this pointer */ + PNIDEVICESESSIONFLUSH niDeviceSessionFlush; /** Client should access ::ni_device_session_flush API through this pointer */ + PNIDEVICEDECSESSIONSAVEHDRS niDeviceDecSessionSaveHdrs; /** Client should access ::ni_device_dec_session_save_hdrs API through this pointer */ + PNIDEVICEDECSESSIONFLUSH niDeviceDecSessionFlush; /** Client should access ::ni_device_dec_session_flush API through this pointer */ + PNIDEVICESESSIONWRITE niDeviceSessionWrite; /** Client should access ::ni_device_session_write API through this pointer */ + PNIDEVICESESSIONREAD niDeviceSessionRead; /** Client should access ::ni_device_session_read API through this pointer */ + PNIDEVICESESSIONQUERY niDeviceSessionQuery; /** Client should access ::ni_device_session_query API through this pointer */ + PNIFRAMEBUFFERALLOC niFrameBufferAlloc; /** Client should access ::ni_frame_buffer_alloc API through this pointer */ + PNIDECODERFRAMEBUFFERALLOC niDecoderFrameBufferAlloc; /** Client should access ::ni_decoder_frame_buffer_alloc API through this pointer */ + PNIENCODERFRAMEBUFFERALLOC niEncoderFrameBufferAlloc; /** Client should access ::ni_encoder_frame_buffer_alloc API through this pointer */ + PNIFRAMEBUFFERALLOCNV niFrameBufferAllocNv; /** Client should access ::ni_frame_buffer_alloc_nv API through this pointer */ + PNIENCODERSWFRAMEBUFFERALLOC niEncoderSwFrameBufferAlloc; /** Client should access ::ni_encoder_sw_frame_buffer_alloc API through this pointer */ + PNIFRAMEBUFFERFREE niFrameBufferFree; /** Client should access ::ni_frame_buffer_free API through this pointer */ + PNIDECODERFRAMEBUFFERFREE niDecoderFrameBufferFree; /** Client should access ::ni_decoder_frame_buffer_free API through this pointer */ + PNIDECODERFRAMEBUFFERPOOLRETURNBUF niDecoderFrameBufferPoolReturnBuf; /** Client should access ::ni_decoder_frame_buffer_pool_return_buf API through this pointer */ + PNIPACKETBUFFERALLOC niPacketBufferAlloc; /** Client should access ::ni_packet_buffer_alloc API through this pointer */ + PNICUSTOMPACKETBUFFERALLOC niCustomPacketBufferAlloc; /** Client should access ::ni_custom_packet_buffer_alloc API through this pointer */ + PNIPACKETBUFFERFREE niPacketBufferFree; /** Client should access ::ni_packet_buffer_free API through this pointer */ + PNIPACKETBUFFERFREEAV1 niPacketBufferFreeAv1; /** Client should access ::ni_packet_buffer_free_av1 API through this pointer */ + PNIPACKETCOPY niPacketCopy; /** Client should access ::ni_packet_copy API through this pointer */ + PNIFRAMENEWAUXDATA niFrameNewAuxData; /** Client should access ::ni_frame_new_aux_data API through this pointer */ + PNIFRAMENEWAUXDATAFROMRAWDATA niFrameNewAuxDataFromRawData; /** Client should access ::ni_frame_new_aux_data_from_raw_data API through this pointer */ + PNIFRAMEGETAUXDATA niFrameGetAuxData; /** Client should access ::ni_frame_get_aux_data API through this pointer */ + PNIFRAMEFREEAUXDATA niFrameFreeAuxData; /** Client should access ::ni_frame_free_aux_data API through this pointer */ + PNIFRAMEWIPEAUXDATA niFrameWipeAuxData; /** Client should access ::ni_frame_wipe_aux_data API through this pointer */ + PNIENCODERINITDEFAULTPARAMS niEncoderInitDefaultParams; /** Client should access ::ni_encoder_init_default_params API through this pointer */ + PNIDECODERINITDEFAULTPARAMS niDecoderInitDefaultParams; /** Client should access ::ni_decoder_init_default_params API through this pointer */ + PNIENCODERPARAMSSETVALUE niEncoderParamsSetValue; /** Client should access ::ni_encoder_params_set_value API through this pointer */ + PNIDECODERPARAMSSETVALUE niDecoderParamsSetValue; /** Client should access ::ni_decoder_params_set_value API through this pointer */ + PNIENCODERGOPPARAMSSETVALUE niEncoderGopParamsSetValue; /** Client should access ::ni_encoder_gop_params_set_value API through this pointer */ + PNIDEVICESESSIONCOPY niDeviceSessionCopy; /** Client should access ::ni_device_session_copy API through this pointer */ + PNIDEVICESESSIONINITFRAMEPOOL niDeviceSessionInitFramepool; /** Client should access ::ni_device_session_init_framepool API through this pointer */ + PNIDEVICESESSIONREADHWDESC niDeviceSessionReadHwdesc; /** Client should access ::ni_device_session_read_hwdesc API through this pointer */ + PNIDEVICESESSIONHWDL niDeviceSessionHwdl; /** Client should access ::ni_device_session_hwdl API through this pointer */ + PNIDEVICESESSIONHWUP niDeviceSessionHwup; /** Client should access ::ni_device_session_hwup API through this pointer */ + PNIFRAMEBUFFERALLOCHWENC niFrameBufferAllocHwenc; /** Client should access ::ni_frame_buffer_alloc_hwenc API through this pointer */ + PNIHWFRAMEBUFFERRECYCLE niHwframeBufferRecycle; /** Client should access ::ni_hwframe_buffer_recycle API through this pointer */ + PNISCALERSETPARAMS niScalerSetParams; /** Client should access ::ni_scaler_set_params API through this pointer */ + PNIDEVICEALLOCFRAME niDeviceAllocFrame; /** Client should access ::ni_device_alloc_frame API through this pointer */ + PNIDEVICECONFIGFRAME niDeviceConfigFrame; /** Client should access ::ni_device_config_frame API through this pointer */ + PNIFRAMEBUFFERALLOCPIXFMT niFrameBufferAllocPixfmt; /** Client should access ::ni_frame_buffer_alloc_pixfmt API through this pointer */ + PNIAICONFIGNETWORKBINARY niAiConfigNetworkBinary; /** Client should access ::ni_ai_config_network_binary API through this pointer */ + PNIAIFRAMEBUFFERALLOC niAiFrameBufferAlloc; /** Client should access ::ni_ai_frame_buffer_alloc API through this pointer */ + PNIAIPACKETBUFFERALLOC niAiPacketBufferAlloc; /** Client should access ::ni_ai_packet_buffer_alloc API through this pointer */ + PNIRECONFIGBITRATE niReconfigBitrate; /** Client should access ::ni_reconfig_bitrate API through this pointer */ + PNIFORCEIDRFRAMETYPE niForceIdrFrameType; /** Client should access ::ni_force_idr_frame_type API through this pointer */ + PNISETLTR niSetLtr; /** Client should access ::ni_set_ltr API through this pointer */ + PNISETLTRINTERVAL niSetLtrInterval; /** Client should access ::ni_set_ltr_interval API through this pointer */ + PNISETFRAMEREFINVALID niSetFrameRefInvalid; /** Client should access ::ni_set_frame_ref_invalid API through this pointer */ + PNIRECONFIGFRAMERATE niReconfigFramerate; /** Client should access ::ni_reconfig_framerate API through this pointer */ + PNIDEVICESESSIONACQUIRE niDeviceSessionAcquire; /** Client should access ::ni_device_session_acquire API through this pointer */ + PNIUPLOADERFRAMEBUFFERLOCK niUploaderFrameBufferLock; /** Client should access ::ni_uploader_frame_buffer_lock API through this pointer */ + PNIUPLOADERFRAMEBUFFERUNLOCK niUploaderFrameBufferUnlock; /** Client should access ::ni_uploader_frame_buffer_unlock API through this pointer */ + PNIUPLOADERP2PTESTSEND niUploaderP2PTestSend; /** Client should access ::ni_uploader_p2p_test_send API through this pointer */ + PNIENCODERSETINPUTFRAMEFORMAT niEncoderSetInputFrameFormat; /** Client should access ::ni_encoder_set_input_frame_format API through this pointer */ + PNIUPLOADERSETFRAMEFORMAT niUploaderSetFrameFormat; /** Client should access ::ni_uploader_set_frame_format API through this pointer */ + PNIHWFRAMEP2PBUFFERRECYCLE niHwframeP2PBufferRecycle; /** Client should access ::ni_hwframe_p2p_buffer_recycle API through this pointer */ + PNIENCODERSESSIONREADSTREAMHEADER niEncoderSessionReadStreamHeader; /** Client should access ::ni_encoder_session_read_stream_header API through this pointer */ + PNIGETDMABUFFILEDESCRIPTOR niGetDmaBufFileDescriptor; /** Client should access ::ni_get_dma_buf_file_descriptor API through this pointer */ + PNIDEVICESESSIONSEQUENCECHANGE niDeviceSessionSequenceChange; /** Client should access ::ni_device_session_sequence_change API through this pointer */ +} NETINT_LIBXCODER_API_FUNCTION_LIST; + +class NETINTLibxcoderAPI { +public: + // NiLibxcoderAPICreateInstance + /** + * Creates an instance of the NiLibxcoderAPI interface, and populates the + * pFunctionList with function pointers to the API routines implemented by the + * NiLibxcoderAPI interface. + */ + static void NiLibxcoderAPICreateInstance(void *lib, NETINT_LIBXCODER_API_FUNCTION_LIST *functionList) + { + // + // Function/symbol loading for ni_av_codec.h + // + functionList->niShouldSendSeiWithFrame = reinterpret_cast(dlsym(lib,"ni_should_send_sei_with_frame")); + functionList->niDecRetrieveAuxData = reinterpret_cast(dlsym(lib,"ni_dec_retrieve_aux_data")); + functionList->niEncPrepAuxData = reinterpret_cast(dlsym(lib,"ni_enc_prep_aux_data")); + functionList->niEncCopyAuxData = reinterpret_cast(dlsym(lib,"ni_enc_copy_aux_data")); + // + // Function/symbol loading for ni_util.h + // + functionList->niGetHwYuv420PDim = reinterpret_cast(dlsym(lib,"ni_get_hw_yuv420p_dim")); + functionList->niCopyHwYuv420P = reinterpret_cast(dlsym(lib,"ni_copy_hw_yuv420p")); + functionList->niInsertEmulationPreventBytes = reinterpret_cast(dlsym(lib,"ni_insert_emulation_prevent_bytes")); + functionList->niRemoveEmulationPreventBytes = reinterpret_cast(dlsym(lib,"ni_remove_emulation_prevent_bytes")); + functionList->niGettimeofday = reinterpret_cast(dlsym(lib,"ni_gettimeofday")); + functionList->niGettimeNs = reinterpret_cast(dlsym(lib,"ni_gettime_ns")); + functionList->niUsleep = reinterpret_cast(dlsym(lib,"ni_usleep")); + functionList->niNetworkLayerConvertOutput = reinterpret_cast(dlsym(lib,"ni_network_layer_convert_output")); + functionList->niAiNetworkLayerSize = reinterpret_cast(dlsym(lib,"ni_ai_network_layer_size")); + functionList->niAiNetworkLayerDims = reinterpret_cast(dlsym(lib,"ni_ai_network_layer_dims")); + functionList->niNetworkLayerConvertTensor = reinterpret_cast(dlsym(lib,"ni_network_layer_convert_tensor")); + functionList->niNetworkConvertTensorToData = reinterpret_cast(dlsym(lib,"ni_network_convert_tensor_to_data")); + functionList->niNetworkConvertDataToTensor = reinterpret_cast(dlsym(lib,"ni_network_convert_data_to_tensor")); + functionList->niCalculateSha256 = reinterpret_cast(dlsym(lib,"ni_calculate_sha256")); + functionList->niCopyHwDescriptors = reinterpret_cast(dlsym(lib,"ni_copy_hw_descriptors")); + functionList->niGetLibxcoderApiVer = reinterpret_cast(dlsym(lib,"ni_get_libxcoder_api_ver")); + functionList->niGetCompatFwApiVer = reinterpret_cast(dlsym(lib,"ni_get_compat_fw_api_ver")); + functionList->niGetLibxcoderReleaseVer = reinterpret_cast(dlsym(lib,"ni_get_libxcoder_release_ver")); + // + // Function/symbol loading for ni_device_api.h + // + functionList->niDeviceSessionContextAllocInit = reinterpret_cast(dlsym(lib,"ni_device_session_context_alloc_init")); + functionList->niDeviceSessionContextInit = reinterpret_cast(dlsym(lib,"ni_device_session_context_init")); + functionList->niDeviceSessionContextClear = reinterpret_cast(dlsym(lib,"ni_device_session_context_clear")); + functionList->niDeviceSessionContextFree = reinterpret_cast(dlsym(lib,"ni_device_session_context_free")); + functionList->niCreateEvent = reinterpret_cast(dlsym(lib,"ni_create_event")); + functionList->niCloseEvent = reinterpret_cast(dlsym(lib,"ni_close_event")); + functionList->niDeviceOpen = reinterpret_cast(dlsym(lib,"ni_device_open")); + functionList->niDeviceClose = reinterpret_cast(dlsym(lib,"ni_device_close")); + functionList->niDeviceCapabilityQuery = reinterpret_cast(dlsym(lib,"ni_device_capability_query")); + functionList->niDeviceSessionOpen = reinterpret_cast(dlsym(lib,"ni_device_session_open")); + functionList->niDeviceSessionClose = reinterpret_cast(dlsym(lib,"ni_device_session_close")); + functionList->niDeviceSessionFlush = reinterpret_cast(dlsym(lib,"ni_device_session_flush")); + functionList->niDeviceDecSessionSaveHdrs = reinterpret_cast(dlsym(lib,"ni_device_dec_session_save_hdrs")); + functionList->niDeviceDecSessionFlush = reinterpret_cast(dlsym(lib,"ni_device_dec_session_flush")); + functionList->niDeviceSessionWrite = reinterpret_cast(dlsym(lib,"ni_device_session_write")); + functionList->niDeviceSessionRead = reinterpret_cast(dlsym(lib,"ni_device_session_read")); + functionList->niDeviceSessionQuery = reinterpret_cast(dlsym(lib,"ni_device_session_query")); + functionList->niFrameBufferAlloc = reinterpret_cast(dlsym(lib,"ni_frame_buffer_alloc")); + functionList->niDecoderFrameBufferAlloc = reinterpret_cast(dlsym(lib,"ni_decoder_frame_buffer_alloc")); + functionList->niEncoderFrameBufferAlloc = reinterpret_cast(dlsym(lib,"ni_encoder_frame_buffer_alloc")); + functionList->niFrameBufferAllocNv = reinterpret_cast(dlsym(lib,"ni_frame_buffer_alloc_nv")); + functionList->niEncoderSwFrameBufferAlloc = reinterpret_cast(dlsym(lib,"ni_encoder_sw_frame_buffer_alloc")); + functionList->niFrameBufferFree = reinterpret_cast(dlsym(lib,"ni_frame_buffer_free")); + functionList->niDecoderFrameBufferFree = reinterpret_cast(dlsym(lib,"ni_decoder_frame_buffer_free")); + functionList->niDecoderFrameBufferPoolReturnBuf = reinterpret_cast(dlsym(lib,"ni_decoder_frame_buffer_pool_return_buf")); + functionList->niPacketBufferAlloc = reinterpret_cast(dlsym(lib,"ni_packet_buffer_alloc")); + functionList->niCustomPacketBufferAlloc = reinterpret_cast(dlsym(lib,"ni_custom_packet_buffer_alloc")); + functionList->niPacketBufferFree = reinterpret_cast(dlsym(lib,"ni_packet_buffer_free")); + functionList->niPacketBufferFreeAv1 = reinterpret_cast(dlsym(lib,"ni_packet_buffer_free_av1")); + functionList->niPacketCopy = reinterpret_cast(dlsym(lib,"ni_packet_copy")); + functionList->niFrameNewAuxData = reinterpret_cast(dlsym(lib,"ni_frame_new_aux_data")); + functionList->niFrameNewAuxDataFromRawData = reinterpret_cast(dlsym(lib,"ni_frame_new_aux_data_from_raw_data")); + functionList->niFrameGetAuxData = reinterpret_cast(dlsym(lib,"ni_frame_get_aux_data")); + functionList->niFrameFreeAuxData = reinterpret_cast(dlsym(lib,"ni_frame_free_aux_data")); + functionList->niFrameWipeAuxData = reinterpret_cast(dlsym(lib,"ni_frame_wipe_aux_data")); + functionList->niEncoderInitDefaultParams = reinterpret_cast(dlsym(lib,"ni_encoder_init_default_params")); + functionList->niDecoderInitDefaultParams = reinterpret_cast(dlsym(lib,"ni_decoder_init_default_params")); + functionList->niEncoderParamsSetValue = reinterpret_cast(dlsym(lib,"ni_encoder_params_set_value")); + functionList->niDecoderParamsSetValue = reinterpret_cast(dlsym(lib,"ni_decoder_params_set_value")); + functionList->niEncoderGopParamsSetValue = reinterpret_cast(dlsym(lib,"ni_encoder_gop_params_set_value")); + functionList->niDeviceSessionCopy = reinterpret_cast(dlsym(lib,"ni_device_session_copy")); + functionList->niDeviceSessionInitFramepool = reinterpret_cast(dlsym(lib,"ni_device_session_init_framepool")); + functionList->niDeviceSessionReadHwdesc = reinterpret_cast(dlsym(lib,"ni_device_session_read_hwdesc")); + functionList->niDeviceSessionHwdl = reinterpret_cast(dlsym(lib,"ni_device_session_hwdl")); + functionList->niDeviceSessionHwup = reinterpret_cast(dlsym(lib,"ni_device_session_hwup")); + functionList->niFrameBufferAllocHwenc = reinterpret_cast(dlsym(lib,"ni_frame_buffer_alloc_hwenc")); + functionList->niHwframeBufferRecycle = reinterpret_cast(dlsym(lib,"ni_hwframe_buffer_recycle")); + functionList->niScalerSetParams = reinterpret_cast(dlsym(lib,"ni_scaler_set_params")); + functionList->niDeviceAllocFrame = reinterpret_cast(dlsym(lib,"ni_device_alloc_frame")); + functionList->niDeviceConfigFrame = reinterpret_cast(dlsym(lib,"ni_device_config_frame")); + functionList->niFrameBufferAllocPixfmt = reinterpret_cast(dlsym(lib,"ni_frame_buffer_alloc_pixfmt")); + functionList->niAiConfigNetworkBinary = reinterpret_cast(dlsym(lib,"ni_ai_config_network_binary")); + functionList->niAiFrameBufferAlloc = reinterpret_cast(dlsym(lib,"ni_ai_frame_buffer_alloc")); + functionList->niAiPacketBufferAlloc = reinterpret_cast(dlsym(lib,"ni_ai_packet_buffer_alloc")); + functionList->niReconfigBitrate = reinterpret_cast(dlsym(lib,"ni_reconfig_bitrate")); + functionList->niForceIdrFrameType = reinterpret_cast(dlsym(lib,"ni_force_idr_frame_type")); + functionList->niSetLtr = reinterpret_cast(dlsym(lib,"ni_set_ltr")); + functionList->niSetLtrInterval = reinterpret_cast(dlsym(lib,"ni_set_ltr_interval")); + functionList->niSetFrameRefInvalid = reinterpret_cast(dlsym(lib,"ni_set_frame_ref_invalid")); + functionList->niReconfigFramerate = reinterpret_cast(dlsym(lib,"ni_reconfig_framerate")); + functionList->niDeviceSessionAcquire = reinterpret_cast(dlsym(lib,"ni_device_session_acquire")); + functionList->niUploaderFrameBufferLock = reinterpret_cast(dlsym(lib,"ni_uploader_frame_buffer_lock")); + functionList->niUploaderFrameBufferUnlock = reinterpret_cast(dlsym(lib,"ni_uploader_frame_buffer_unlock")); + functionList->niUploaderP2PTestSend = reinterpret_cast(dlsym(lib,"ni_uploader_p2p_test_send")); + functionList->niEncoderSetInputFrameFormat = reinterpret_cast(dlsym(lib,"ni_encoder_set_input_frame_format")); + functionList->niUploaderSetFrameFormat = reinterpret_cast(dlsym(lib,"ni_uploader_set_frame_format")); + functionList->niHwframeP2PBufferRecycle = reinterpret_cast(dlsym(lib,"ni_hwframe_p2p_buffer_recycle")); + functionList->niEncoderSessionReadStreamHeader = reinterpret_cast(dlsym(lib,"ni_encoder_session_read_stream_header")); + functionList->niGetDmaBufFileDescriptor = reinterpret_cast(dlsym(lib,"ni_get_dma_buf_file_descriptor")); + functionList->niDeviceSessionSequenceChange = reinterpret_cast(dlsym(lib,"ni_device_session_sequence_change")); + } +}; + + +#endif // _NETINTLIBXCODERAPI_H_ + diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_libxcoder_dynamic_loading_test.cpp b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_libxcoder_dynamic_loading_test.cpp new file mode 100644 index 00000000..c83cded1 --- /dev/null +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_libxcoder_dynamic_loading_test.cpp @@ -0,0 +1,85 @@ +/******************************************************************************* + * + * Copyright (C) 2022 NETINT Technologies + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ******************************************************************************/ + +/*!***************************************************************************** + * \file ni_libxcoder_dynamic_loading_test.c + * + * \brief Use ni_libxcoder_dynamic_loading.h to dynamically load libxcoder at + * runtime. Check all function pointers are mapped. Only for Linux. + * + ******************************************************************************/ + +#include +#include +#include + +#include +#include +#define _NETINT_LIBXCODER_DYNAMIC_LOADING_TEST_ +#include "ni_libxcoder_dynamic_loading.h" + +int main(int argc, char **argv) +{ + void *handle; + char *error; + NETINTLibxcoderAPI ni_libxcoder_api_dl; + NETINT_LIBXCODER_API_FUNCTION_LIST functionList; + int failed_func_ptr_check = 0; + + handle = dlopen ("libxcoder.so", RTLD_NOW); + if (!handle) { + fprintf(stderr, "%s\n", dlerror()); + exit(1); + } + + // Check load error on individual function + // functionList.niSetVui = reinterpret_cast(dlsym(handle,"ni_set_vui")); + // if ((error = dlerror()) != NULL) { + // fprintf(stderr, "%s\n", error); + // exit(1); + // } + + ni_libxcoder_api_dl.NiLibxcoderAPICreateInstance(handle, &functionList); + if ((error = dlerror()) != NULL) { + fprintf(stderr, "%s\n", error); + exit(1); + } + printf("Dynamically loaded functionList\n"); + + for (int i = 0; i < (sizeof(NETINT_LIBXCODER_API_FUNCTION_LIST) / \ + sizeof(void *)); i++) + { + if (((void *) *(((void **) &functionList) + i)) == NULL) + { + fprintf(stderr, "Failed to load function pointer at function %d in " + "NETINT_LIBXCODER_API_FUNCTION_LIST\n", i); + failed_func_ptr_check = 1; + } + } + + if (!failed_func_ptr_check) + { + printf("All functions in functionList were loaded.\nPass\n"); + } + + dlclose(handle); + exit(failed_func_ptr_check); +} \ No newline at end of file diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_log.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_log.c index 2bdff5bb..0b69a556 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_log.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_log.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -110,7 +109,12 @@ void ni_log_default_callback(int level, const char* fmt, va_list vl) #endif #ifdef _ANDROID - ALOGV(fmt, vl); + if (level == NI_LOG_INFO) + ALOGI(fmt, vl); + else if (level >= NI_LOG_ERROR) + ALOGE(fmt, vl); + else + ALOGV(fmt, vl); #else vfprintf(stderr, fmt, vl); #endif diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_log.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_log.h index 04f80059..791f9a81 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_log.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_log.h @@ -28,12 +28,14 @@ #pragma once +#include + #ifdef LIBXCODER_OBJS_BUILD #include "../build/xcoder_auto_headers.h" #endif #ifdef _WIN32 - #ifdef LIB_DLL + #ifdef XCODER_DLL #ifdef LIB_EXPORTS #define LIB_API_LOG __declspec(dllexport) #else @@ -42,7 +44,7 @@ #else #define LIB_API_LOG #endif -#elif __linux__ +#elif __linux__ || __APPLE__ #define LIB_API_LOG #endif diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_nvme.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_nvme.c index bbacd650..7cbc8f63 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_nvme.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_nvme.c @@ -36,11 +36,13 @@ #include #include #include -#elif __linux__ - #include - #include - #include - #include +#elif __linux__ || __APPLE__ +#if __linux__ +#include +#endif +#include +#include +#include #endif #include "ni_nvme.h" @@ -325,6 +327,7 @@ int32_t ni_nvme_send_admin_cmd(ni_nvme_admin_opcode_t opcode, rc = ni_nvme_get_identity(handle, NI_INVALID_EVENT_HANDLE, p_data); *p_result = NI_RETCODE_SUCCESS; } +#elif __APPLE__ #else ni_nvme_passthrough_cmd_t nvme_cmd = {0}; @@ -362,6 +365,7 @@ int32_t ni_nvme_send_io_cmd(ni_nvme_opcode_t opcode, ni_device_handle_t handle, { int32_t rc = -1; #ifdef _WIN32 +#elif __APPLE__ #else ni_nvme_passthrough_cmd_t nvme_cmd; //int32_t *p_addr = NULL; @@ -504,7 +508,7 @@ void ni_parse_lba(uint64_t lba) } /*!****************************************************************************** - * \brief Compose a io read command + * \brief Compose an io read command * * \param * @@ -551,7 +555,33 @@ int32_t ni_nvme_send_read_cmd(ni_device_handle_t handle, #else if (handle != 0 && p_data != NULL) { - rc = pread(handle, p_data, data_len, offset); + if (((uintptr_t)p_data) % NI_MEM_PAGE_ALIGNMENT) + { + ni_log(NI_LOG_DEBUG, + "%s: Buffer not %d aligned = %p! Reading to aligned memory " + "and copying.\n", + __func__, NI_MEM_PAGE_ALIGNMENT, p_data); + void *p_buf = NULL; + if (ni_posix_memalign(&p_buf, sysconf(_SC_PAGESIZE), data_len)) + { + ni_log(NI_LOG_ERROR, + "ERROR %d: %s() alloc data buffer failed\n", NI_ERRNO, + __func__); + rc = NI_RETCODE_ERROR_MEM_ALOC; + } + else + { + rc = pread(handle, p_buf, data_len, offset); + if (rc >= 0)//copy only if anything has been read + { + memcpy(p_data, p_buf, data_len); + } + ni_aligned_free(p_buf); + } + } else + { + rc = pread(handle, p_data, data_len, offset); + } ni_log(NI_LOG_TRACE, "%s: handle=%" PRIx64 ", offset 0x%lx, lba=0x%x, len=%d, rc=%d\n", @@ -629,7 +659,31 @@ int32_t ni_nvme_send_write_cmd(ni_device_handle_t handle, #else if (handle != 0 && p_data != NULL) { - rc = pwrite(handle, p_data, data_len, offset); + if (((uintptr_t)p_data) % NI_MEM_PAGE_ALIGNMENT) + { + ni_log(NI_LOG_DEBUG, + "%s: Buffer not %d aligned = %p! Copying to aligned memory " + "and writing.\n", + __func__, NI_MEM_PAGE_ALIGNMENT, p_data); + void *p_buf = NULL; + if (ni_posix_memalign(&p_buf, sysconf(_SC_PAGESIZE), data_len)) + { + ni_log(NI_LOG_ERROR, + "ERROR %d: %s() alloc data buffer failed\n", NI_ERRNO, + __func__); + rc = NI_RETCODE_ERROR_MEM_ALOC; + } + else + { + memcpy(p_buf, p_data, data_len); + rc = pwrite(handle, p_buf, data_len, offset); + ni_aligned_free(p_buf); + } + } + else + { + rc = pwrite(handle, p_data, data_len, offset); + } ni_log(NI_LOG_TRACE, "%s: handle=%" PRIx64 ", lba=0x%x, len=%d, rc=%d\n", __func__, (int64_t)handle, (lba << 3), data_len, rc); diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_nvme.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_nvme.h index 279fadf6..c5891b21 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_nvme.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_nvme.h @@ -37,6 +37,18 @@ extern "C" #define NI_NVME_IDENTITY_CMD_DATA_SZ 4096 +typedef struct _ni_nvme_command +{ + uint32_t cdw2; + uint32_t cdw3; + uint32_t cdw10; + uint32_t cdw11; + uint32_t cdw12; + uint32_t cdw13; + uint32_t cdw14; + uint32_t cdw15; +} ni_nvme_command_t; + typedef struct _ni_nvme_id_power_state { uint16_t ui16MaxPower; /*! centiwatts */ @@ -208,8 +220,9 @@ typedef struct _ni_nvme_identity uint8_t fw_commit_hash[41]; uint8_t fw_build_time[26]; uint8_t fw_build_id[256]; - uint8_t fw_repo_info_padding[3]; + uint8_t fw_repo_info_padding[2]; + uint8_t memory_cfg; // 0 == DR, 1 == SR // byte offset 469 (=468+1 due to alignment at hw0_max_video_width) // xcoder HW - version 2 (replaces/deprecates version 1) @@ -383,6 +396,7 @@ typedef enum _nvme_config_xcoder_config_session_subtype nvme_config_xcoder_config_session_read = 0x0001, nvme_config_xcoder_config_session_write = 0x0002, nvme_config_xcoder_config_session_keep_alive_timeout = 0x0003, + nvme_config_xcoder_config_session_sw_version = 0x0004, } nvme_config_xcoder_config_session_subtype_t; typedef enum _nvme_config_xcoder_config_instance_subtype @@ -397,7 +411,10 @@ typedef enum _nvme_config_xcoder_config_instance_subtype nvme_config_xcoder_config_set_network_binary = 0x0008, nvme_config_xcoder_config_set_enc_frame_params = 0x0009, nvme_config_xcoder_config_set_write_legth = 0x000c, - nvme_config_xcoder_config_alloc_frame = 0x000d, + nvme_config_xcoder_config_alloc_frame = 0x000d, // scaler only + nvme_config_xcoder_config_set_sequence_change = 0x000d, // encoder only + nvme_config_xcoder_instance_read_buf_size_busy_place_holder = 0x000e, // admin type taken by busy query read + nvme_config_xcoder_instance_write_buf_size_busy_place_holder = 0x000f, // admin type taken by busy query write } nvme_config_xcoder_config_instance_subtype_t; typedef struct _ni_nvme_write_complete_dw0_t @@ -706,6 +723,8 @@ int32_t ni_nvme_send_io_pass_through_command(ni_device_handle_t fd, ni_nvme_pass nvme_config_xcoder_config_instance,nvme_config_xcoder_config_set_enc_frame_params) #define CONFIG_INSTANCE_SetPktSize_W(sid,instance) HIGH_OFFSET_IN_4K(sid,instance) + CTL_OFFSET_IN_4K(GAP(nvme_admin_cmd_xcoder_config), \ nvme_config_xcoder_config_instance,nvme_config_xcoder_config_set_write_legth) +#define CONFIG_INSTANCE_SetSeqChange_W(sid,instance) HIGH_OFFSET_IN_4K(sid,instance) + CTL_OFFSET_IN_4K(GAP(nvme_admin_cmd_xcoder_config), \ + nvme_config_xcoder_config_instance,nvme_config_xcoder_config_set_sequence_change) #define CONFIG_INSTANCE_SetAiPara_W(sid, instance) \ HIGH_OFFSET_IN_4K(sid, instance) + \ CTL_OFFSET_IN_4K(GAP(nvme_admin_cmd_xcoder_config), \ @@ -733,6 +752,12 @@ int32_t ni_nvme_send_io_pass_through_command(ni_device_handle_t fd, ni_nvme_pass nvme_config_xcoder_config_session, \ nvme_config_xcoder_config_session_keep_alive_timeout) +#define CONFIG_SESSION_SWVersion_W(sid) \ + HIGH_OFFSET_IN_4K(sid, 0) + \ + CTL_OFFSET_IN_4K(GAP(nvme_admin_cmd_xcoder_config), \ + nvme_config_xcoder_config_session, \ + nvme_config_xcoder_config_session_sw_version) + int32_t ni_nvme_send_read_cmd(ni_device_handle_t handle, ni_event_handle_t event_handle, void *p_data, uint32_t data_len, uint32_t lba); int32_t ni_nvme_send_write_cmd(ni_device_handle_t handle, ni_event_handle_t event_handle, void *p_data, uint32_t data_len, uint32_t lba); diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_p2p_ioctl.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_p2p_ioctl.h index 418f7ceb..9560c727 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_p2p_ioctl.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_p2p_ioctl.h @@ -1,3 +1,31 @@ +/******************************************************************************* + * + * Copyright (C) 2022 NETINT Technologies + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + ******************************************************************************/ + +/*!***************************************************************************** +* \file ni_p2p_ioctl.h +* +* \brief Definitions related to NETINT P2P kernel driver interface +* +*******************************************************************************/ + #ifndef _NETINT_IOCTL_H #define _NETINT_IOCTL_H @@ -5,6 +33,12 @@ #define NI_DMABUF_SYNC_FILE_OUT_FENCE (1 << 1) #define NI_DMABUF_SYNC_FILE_IN_FENCE (1 << 2) +enum +{ + NI_DMABUF_READ_FROM_DEVICE = 0, + NI_DMABUF_WRITE_TO_DEVICE = 1, +}; + struct netint_iocmd_export_dmabuf { int fd; @@ -22,6 +56,7 @@ struct netint_iocmd_issue_request { int fd; unsigned int len; + int dir; unsigned char *data; }; diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_p2p_test.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_p2p_test.c index d1046f96..473e8ccf 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_p2p_test.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_p2p_test.c @@ -484,7 +484,7 @@ int encoder_receive_data(ni_session_context_t *p_enc_ctx, int rc = 0; int end_flag = 0; int rx_size = 0; - int meta_size = NI_FW_ENC_BITSTREAM_META_DATA_SIZE; + int meta_size = p_enc_ctx->meta_size; ni_packet_t *p_out_pkt = &(p_out_data->data.packet); static int received_stream_header = 0; @@ -533,10 +533,9 @@ int encoder_receive_data(ni_session_context_t *p_enc_ctx, *total_bytes_received += (rx_size - meta_size); number_of_packets++; received_stream_header = 1; - } - else if (rc != 0) + } else if (rc != 0) { - fprintf(stderr, "Error: reading header %d\n",rc); + fprintf(stderr, "Error: reading header %d\n", rc); return -1; } @@ -547,8 +546,8 @@ int encoder_receive_data(ni_session_context_t *p_enc_ctx, { timeDiff = 1; } - printf("[R] Got:%d Packets= %u fps=%u Total bytes %llu\n", rx_size, - number_of_packets, number_of_packets / timeDiff, + printf("[R] Got:%d Packets= %u fps=%u Total bytes %llu\n", + rx_size, number_of_packets, number_of_packets / timeDiff, *total_bytes_received); } @@ -556,8 +555,7 @@ int encoder_receive_data(ni_session_context_t *p_enc_ctx, if (p_out_pkt->end_of_stream) { return 1; - } - else if (rc == 0) + } else if (rc == 0) { return 2; } @@ -741,7 +739,7 @@ int uploader_open_session(ni_session_context_t *p_upl_ctx, int *iXcoderGUID, void print_usage(void) { printf("Video encoder/P2P application directly using Netint " - "Libxcoder API v%s\n" + "Libxcoder release v%s\n" "Usage: xcoderp2p [options]\n" "\n" "options:\n" @@ -818,11 +816,12 @@ void parse_arguments(int argc, char *argv[], char *input_filename, print_usage(); exit(0); case 'v': - printf("Ver: %s\n" - "Date: %s\n" - "ID: %s\n", - NI_XCODER_REVISION, NI_SW_RELEASE_TIME, - NI_SW_RELEASE_ID); + printf("Release ver: %s\n" + "API ver: %s\n" + "Date: %s\n" + "ID: %s\n", + NI_XCODER_REVISION, LIBXCODER_API_VERSION, + NI_SW_RELEASE_TIME, NI_SW_RELEASE_ID); exit(0); case 'l': log_level = arg_to_ni_log_level(optarg); diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_release_info.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_release_info.h index c37531bb..c9e18d22 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_release_info.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_release_info.h @@ -1,9 +1,21 @@ /******************************************************************************* * - * Copyright (C) 2018 by NETINT Technologies + * Copyright (C) 2022 NETINT Technologies * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted. + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. * ******************************************************************************/ @@ -14,5 +26,5 @@ * *******************************************************************************/ -#define NI_SW_RELEASE_TIME "2022-04-15_01:11:24_-0700" -#define NI_SW_RELEASE_ID "Netint_Quadra_release_v3.0.0_RC2" +#define NI_SW_RELEASE_TIME "2022-08-05_11:04:57_-0700" +#define NI_SW_RELEASE_ID "Netint_Quadra_release_v4.0.0_RCB" diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_api.cpp b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_api.cpp old mode 100755 new mode 100644 index b3bcb376..9d4562f5 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_api.cpp +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_api.cpp @@ -33,7 +33,7 @@ #include #include -#ifdef __linux__ +#if __linux__ || __APPLE__ #include #include /* For O_* constants */ #include @@ -48,9 +48,6 @@ #include "ni_rsrc_priv.h" #include "ni_util.h" -static uint32_t g_xcoder_guid[NI_DEVICE_TYPE_XCODER_MAX] = {0}; -static char g_xcoder_dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0}; -static int g_xcoder_dev_count = 0; // Decoder/Encoder reference (resolution_width, resolution_height, framerate) table ni_rsrc_device_video_ref_cap_t g_device_reference_table[2][2] = @@ -84,6 +81,65 @@ static bool is_str_in_str_array(const char key[], return false; } +void print_device(ni_device_t *p_device) +{ + if (!p_device) + { + ni_log(NI_LOG_INFO, "WARNING: NULL parameter passed in!\n"); + return; + } + + ni_device_info_t *p_dev_info = NULL; + for (size_t xcoder_index_1 = 0; + xcoder_index_1 < p_device->xcoder_cnt[NI_DEVICE_TYPE_DECODER]; + xcoder_index_1++) + { + p_dev_info = &p_device->xcoders[NI_DEVICE_TYPE_DECODER][xcoder_index_1]; + ni_log(NI_LOG_INFO, "Device #%zu:\n", xcoder_index_1); + ni_log(NI_LOG_INFO, " Serial number: %.*s\n", + (int)sizeof(p_dev_info->serial_number), + p_dev_info->serial_number); + ni_log(NI_LOG_INFO, " Model number: %.*s\n", + (int)sizeof(p_dev_info->model_number), + p_dev_info->model_number); + ni_log(NI_LOG_INFO, " F/W rev: %.*s\n", + (int)sizeof(p_dev_info->fw_rev), p_dev_info->fw_rev); + ni_log(NI_LOG_INFO, " F/W & S/W compatibility: %s\n", + p_dev_info->fw_ver_compat_warning ? + "no, possible missing features" : "yes"); + ni_log(NI_LOG_INFO, " F/W branch: %s\n", + p_dev_info->fw_branch_name); + ni_log(NI_LOG_INFO, " F/W commit time: %s\n", + p_dev_info->fw_commit_time); + ni_log(NI_LOG_INFO, " F/W commit hash: %s\n", + p_dev_info->fw_commit_hash); + ni_log(NI_LOG_INFO, " F/W build time: %s\n", + p_dev_info->fw_build_time); + ni_log(NI_LOG_INFO, " F/W build id: %s\n",p_dev_info->fw_build_id); + ni_log(NI_LOG_INFO, " DeviceID: %s\n", p_dev_info->dev_name); + ni_log(NI_LOG_INFO, " BlockDeviceID: %s\n", p_dev_info->blk_name); + ni_log(NI_LOG_INFO, " PixelFormats: yuv420p, yuv420p10le, nv12, p010le" + ", ni_quadra\n"); + + for (size_t dev_type = NI_DEVICE_TYPE_DECODER; + dev_type != NI_DEVICE_TYPE_XCODER_MAX; dev_type++) + { + for (size_t xcoder_index_2 = 0; + xcoder_index_2 < p_device->xcoder_cnt[NI_DEVICE_TYPE_DECODER]; + xcoder_index_2++) + { + if (strcmp(p_dev_info->dev_name, + p_device->xcoders[dev_type][xcoder_index_2].dev_name) + == 0 && p_dev_info->module_id >= 0) + { + ni_rsrc_print_device_info(&(p_device->xcoders[dev_type] + [xcoder_index_2])); + } + } + } + } +} + /*!***************************************************************************** * \brief Scan and refresh all resources on the host, taking into account * hot-plugged and pulled out cards. @@ -99,66 +155,58 @@ static bool is_str_in_str_array(const char key[], ******************************************************************************/ ni_retcode_t ni_rsrc_refresh(int should_match_rev) { + char xcoder_dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0}; + int xcoder_dev_count = 0; char curr_dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0}; int curr_dev_count = 0; int i = 0; - ni_device_t *p_saved_coders; - - p_saved_coders = (ni_device_t *)malloc(sizeof(ni_device_t)); - if (p_saved_coders == NULL) - { - printf("Memory allocation failed, fatal error, exiting ...\n"); - return NI_RETCODE_FAILURE; - } + ni_device_t saved_coders = {0}; - if (0 == g_xcoder_dev_count) + // retrieve saved info from resource pool at start up + if (NI_RETCODE_SUCCESS == + ni_rsrc_list_devices( + NI_DEVICE_TYPE_DECODER, + saved_coders.xcoders[NI_DEVICE_TYPE_DECODER], + &(saved_coders.xcoder_cnt[NI_DEVICE_TYPE_DECODER]))) { - // retrieve saved info from resource pool at start up - if (NI_RETCODE_SUCCESS == - ni_rsrc_list_devices( - NI_DEVICE_TYPE_DECODER, - p_saved_coders->xcoders[NI_DEVICE_TYPE_DECODER], - &p_saved_coders->xcoder_cnt[NI_DEVICE_TYPE_DECODER])) - { - for (i = 0; i < p_saved_coders->xcoder_cnt[NI_DEVICE_TYPE_DECODER]; - i++) - { - strcpy(g_xcoder_dev_names[i], - p_saved_coders->xcoders[NI_DEVICE_TYPE_DECODER][i] - .dev_name); - } - g_xcoder_dev_count = - p_saved_coders->xcoder_cnt[NI_DEVICE_TYPE_DECODER]; - ni_log(NI_LOG_INFO, - "%d devices retrieved from current pool at start up\n", - g_xcoder_dev_count); - } else + for (i = 0; i < saved_coders.xcoder_cnt[NI_DEVICE_TYPE_DECODER]; + i++) { - ni_log(NI_LOG_ERROR, "Error retrieving from current pool at start " - "up\n"); + strcpy(xcoder_dev_names[i], + saved_coders.xcoders[NI_DEVICE_TYPE_DECODER][i] + .dev_name); } + xcoder_dev_count = + saved_coders.xcoder_cnt[NI_DEVICE_TYPE_DECODER]; + ni_log(NI_LOG_INFO, + "%d devices retrieved from current pool at start up\n", + xcoder_dev_count); + } else + { + ni_log(NI_LOG_ERROR, "Error retrieving from current pool at start " + "up\n"); } curr_dev_count = ni_rsrc_get_local_device_list(curr_dev_names, NI_MAX_DEVICE_CNT); // remove from resource pool any device that is not available now - for (i = 0; i < g_xcoder_dev_count; i++) + for (i = 0; i < xcoder_dev_count; i++) { - if (!is_str_in_str_array(g_xcoder_dev_names[i], curr_dev_names, + if (!is_str_in_str_array(xcoder_dev_names[i], curr_dev_names, curr_dev_count)) { ni_log(NI_LOG_INFO, "\n\n%d. %s NOT in current scanned list, removing !\n", i, - g_xcoder_dev_names[i]); + xcoder_dev_names[i]); if (NI_RETCODE_SUCCESS == - ni_rsrc_remove_device(g_xcoder_dev_names[i])) + ni_rsrc_remove_device(xcoder_dev_names[i])) { ni_log(NI_LOG_INFO, "%s deleted successfully !\n", - g_xcoder_dev_names[i]); + xcoder_dev_names[i]); } else { ni_log(NI_LOG_ERROR, "%s failed to delete !\n", - g_xcoder_dev_names[i]); + xcoder_dev_names[i]); } } } @@ -166,8 +214,8 @@ ni_retcode_t ni_rsrc_refresh(int should_match_rev) // and add into resource pool any newly discoved ones for (i = 0; i < curr_dev_count; i++) { - if (!is_str_in_str_array(curr_dev_names[i], g_xcoder_dev_names, - g_xcoder_dev_count)) + if (!is_str_in_str_array(curr_dev_names[i], xcoder_dev_names, + xcoder_dev_count)) { ni_log(NI_LOG_INFO, "\n\n%s NOT in previous list, adding !\n", curr_dev_names[i]); @@ -182,14 +230,6 @@ ni_retcode_t ni_rsrc_refresh(int should_match_rev) } } - // update the saved device name list - for (i = 0; i < curr_dev_count; i++) - { - strcpy(g_xcoder_dev_names[i], curr_dev_names[i]); - } - g_xcoder_dev_count = curr_dev_count; - - free(p_saved_coders); return NI_RETCODE_SUCCESS; } @@ -365,6 +405,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) HANDLE map_file_handle = NULL; ni_device_capability_t device_capabilites = { 0 }; ni_device_handle_t handle; + uint32_t xcoder_guid[NI_DEVICE_TYPE_XCODER_MAX] = {0}; map_file_handle = CreateFileMapping( INVALID_HANDLE_VALUE, // use paging file @@ -409,7 +450,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) else if (0 == xcoder_device_cnt) { ni_log(NI_LOG_INFO, "NVMe Devices not ready, will retry again ...\n"); - if (stop_process) + if (g_xcoder_stop_process) { ni_log(NI_LOG_ERROR, "Requested to stop, exiting ...\n"); CloseHandle(map_file_handle); @@ -527,9 +568,12 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) sizeof(device_info.blk_name)); device_info.hw_id = device_capabilites.xcoder_devices[j].hw_id; device_info.fw_ver_compat_warning = fw_ver_compat_warning; + memcpy(device_info.serial_number, device_capabilites.serial_number, + sizeof(device_info.serial_number)); + memcpy(device_info.model_number, device_capabilites.model_number, + sizeof(device_info.model_number)); memcpy(device_info.fw_rev, device_capabilites.fw_rev, sizeof(device_info.fw_rev)); - memcpy(device_info.fw_branch_name, device_capabilites.fw_branch_name, sizeof(device_info.fw_branch_name) - 1); memcpy(device_info.fw_commit_time, device_capabilites.fw_commit_time, @@ -592,14 +636,14 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) { /*! add the h/w device_info entry */ p_device_info->module_id = - g_xcoder_guid[device_info.device_type]++; + xcoder_guid[device_info.device_type]++; p_device_queue->xcoder_cnt[device_info.device_type] = - g_xcoder_guid[device_info.device_type]; + xcoder_guid[device_info.device_type]; p_device_queue->xcoders[device_info.device_type] [p_device_info->module_id] = p_device_info->module_id; ni_rsrc_get_one_device_info(&device_info); - } + } } } /*! for each device_info */ } /*! if device supports xcoder */ @@ -617,9 +661,8 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) for (k = 0; k < NI_DEVICE_TYPE_XCODER_MAX; k++) { - p_device_queue->xcoder_cnt[k] = g_xcoder_guid[k]; + p_device_queue->xcoder_cnt[k] = xcoder_guid[k]; } - rc = NI_RETCODE_SUCCESS; if (NULL != p_device_queue) { @@ -750,9 +793,15 @@ ni_device_context_t* ni_rsrc_get_device_context(ni_device_type_t device_type, in return p_device_context; } -#elif __linux__ +#elif __linux__ || __APPLE__ jmp_buf shm_open_test_buf; +#if __APPLE__ +#define DEV_NAME_PREFIX "rdisk" +#else +#define DEV_NAME_PREFIX "nvme" +#endif + /*!***************************************************************************** * \brief Scans system for all NVMe devices and returns the system device * names to the user which were identified as NETINT transcoder deivices. @@ -804,9 +853,9 @@ int ni_rsrc_get_local_device_list(char ni_devices[][NI_MAX_DEVICE_NAME_LEN], /* pick only those files with name nvmeX where X consists of 1-n digits */ size_t lenstr = strlen(in_file->d_name); - if (!strncmp(in_file->d_name, "nvme", strlen("nvme"))) + if (!strncmp(in_file->d_name, DEV_NAME_PREFIX, strlen(DEV_NAME_PREFIX))) { - for (i = strlen("nvme"); i < lenstr; i++) + for (i = strlen(DEV_NAME_PREFIX); i < lenstr; i++) { if (!isdigit(in_file->d_name[i])) { @@ -869,18 +918,18 @@ int ni_rsrc_get_local_device_list(char ni_devices[][NI_MAX_DEVICE_NAME_LEN], *******************************************************************************/ ni_device_pool_t* ni_rsrc_get_device_pool(void) { - int shm_fd; + int shm_fd = 0; ni_device_queue_t* p_device_queue = NULL; ni_lock_handle_t lock; ni_device_pool_t* p_device_pool = NULL; #ifdef _ANDROID - char workDir[] = "/dev/shm_netint"; - if (0 != access(workDir, 0)) + if (0 != access(LOCK_DIR, 0)) { - if (0 != mkdir(workDir, 777)) + if (0 != mkdir(LOCK_DIR, 777)) { - ni_log(NI_LOG_ERROR, "Error create /dev/shm_netint folder..."); + ni_log(NI_LOG_ERROR, "ERROR: Could not create the %s directory", + LOCK_DIR); return NULL; } } @@ -974,11 +1023,15 @@ ni_device_pool_t* ni_rsrc_get_device_pool(void) lockf(lock, F_ULOCK, 0); + if (NULL == p_device_pool) + { + close(lock); + } #ifndef _ANDROID - close(shm_fd); + close(shm_fd); #endif - return p_device_pool; + return p_device_pool; } #ifndef _ANDROID @@ -1000,32 +1053,30 @@ static void handle_sigbus(int sig) static void rm_shm_files() { - // remove /dev/shm/* - // Q058279 verifies that these dont exist: - //'SHM_CODERS','LCK_CODERS','RETRY_LCK_DECODERS','RETRY_LCK_SCALERS','RETRY_LCK_ENCODERS','RETRY_LCK_AI' - //Need To Check(NTC):are there others as well - int temp_ret = system("rm -f /dev/shm/SHM_CODERS"); + // remove shm files + // Q058279 verifies that these dont exist + int temp_ret = system("rm -f " LOCK_DIR "/NI_SHM_CODERS"); (void)temp_ret; - temp_ret = system("rm -f /dev/shm/LCK_CODERS"); + temp_ret = system("rm -f " LOCK_DIR "/NI_LCK_CODERS"); (void)temp_ret; - temp_ret = system("rm -f /dev/shm/RETRY_LCK_DECODERS"); + temp_ret = system("rm -f " LOCK_DIR "/NI_RETRY_LCK_DECODERS"); (void)temp_ret; - temp_ret = system("rm -f /dev/shm/RETRY_LCK_SCALERS"); + temp_ret = system("rm -f " LOCK_DIR "/NI_RETRY_LCK_SCALERS"); (void)temp_ret; - temp_ret = system("rm -f /dev/shm/RETRY_LCK_ENCODERS"); + temp_ret = system("rm -f " LOCK_DIR "/NI_RETRY_LCK_ENCODERS"); (void)temp_ret; - temp_ret = system("rm -f /dev/shm/RETRY_LCK_AI"); + temp_ret = system("rm -f " LOCK_DIR "/NI_RETRY_LCK_AI"); (void)temp_ret; - temp_ret = system("rm -f /dev/shm/lck_*"); + temp_ret = system("rm -f " LOCK_DIR "/NI_lck_*"); (void)temp_ret; - temp_ret = system("rm -f /dev/shm/shm_*"); + temp_ret = system("rm -f " LOCK_DIR "/NI_shm_*"); (void)temp_ret; } /*!****************************************************************************** * \brief This function sets up a SIGBUS handler, opens the the file and * does a test. If the read results in SIGBUS the handler - * cleans up the /dev/shm/ + * cleans up the LOCK_DIR * * \return * file descriptor on success @@ -1036,6 +1087,7 @@ static int shm_open_and_test() { struct sigaction new_act, old_act; bool pool_locked = false; + int cleanup = 0; // save the old handler sigaction(SIGINT, NULL, &old_act); @@ -1067,18 +1119,36 @@ static int shm_open_and_test() ni_device_queue_t *p_device_queue = NULL; p_device_queue = p_device_pool->p_device_queue; + // test the file and sig handle - if (0 == sigsetjmp(shm_open_test_buf, 0)) + if (0 == (cleanup = sigsetjmp(shm_open_test_buf, 0))) { //volatile to escape optimization, without this there were some hangs //when reading the following field later - volatile int count = p_device_queue->xcoder_cnt[NI_DEVICE_TYPE_DECODER]; + volatile int count = 0; + count = p_device_queue->xcoder_cnt[NI_DEVICE_TYPE_DECODER]; + cleanup |= count == 0 ? 1 : 0; + ni_log(NI_LOG_DEBUG, "DEBUG: Decoder cnt = %d/*\n", count); + + count = p_device_queue->xcoder_cnt[NI_DEVICE_TYPE_ENCODER]; + cleanup |= count == 0 ? 1 : 0; + ni_log(NI_LOG_DEBUG, "DEBUG: Encoder cnt = %d/*\n", count); + + count = p_device_queue->xcoder_cnt[NI_DEVICE_TYPE_SCALER]; + cleanup |= count == 0 ? 1 : 0; + ni_log(NI_LOG_DEBUG, "DEBUG: Scaler cnt = %d/*\n", count); + + count = p_device_queue->xcoder_cnt[NI_DEVICE_TYPE_AI]; + cleanup |= count == 0 ? 1 : 0; + ni_log(NI_LOG_DEBUG, "DEBUG: AI cnt = %d/*\n", count); + + count = p_device_queue->xcoders[NI_DEVICE_TYPE_AI][NI_MAX_DEVICE_CNT-1]; (void)count; - } else + } + if (1 == cleanup) { - ni_log(NI_LOG_ERROR, - "ERROR: Caught a SIGBUS. Removing files in " - "/dev/shm/*\n"); + ni_log(NI_LOG_ERROR, "ERROR: Caught a SIGBUS or invalid device count! Removing files in %s/*\n", + LOCK_DIR); lockf(p_device_pool->lock, F_ULOCK, 0); pool_locked = false; close(shm_fd); @@ -1137,17 +1207,18 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) ni_device_handle_t dev_handle = NI_INVALID_DEVICE_HANDLE; ni_device_capability_t device_capabilites; ni_retcode_t rc; + uint32_t xcoder_guid[NI_DEVICE_TYPE_XCODER_MAX] = {0}; /*! return if init has already been done */ #ifdef _ANDROID ret = ni_rsrc_android_init(); - char workDir[] = "/dev/shm_netint"; - if (0 != access(workDir, 0)) + if (0 != access(LOCK_DIR, 0)) { - if (0 != mkdir(workDir, 777)) + if (0 != mkdir(LOCK_DIR, 777)) { - perror("Error create /dev/shm_netint folder..."); + ni_log(NI_LOG_ERROR, "ERROR: Could not create the %s directory", + LOCK_DIR); return 1; } } @@ -1233,9 +1304,9 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) /*! pick only those files with name nvmeX where X consists of 1-n digits */ size_t lenstr = strlen(in_file->d_name); - if (!strncmp(in_file->d_name, "nvme", strlen("nvme"))) + if (!strncmp(in_file->d_name, DEV_NAME_PREFIX, strlen(DEV_NAME_PREFIX))) { - for (i = strlen("nvme"); i < lenstr; i++) + for (i = strlen(DEV_NAME_PREFIX); i < lenstr; i++) { if (!isdigit(in_file->d_name[i])) { @@ -1253,7 +1324,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) if (num_dev == 0) { ni_log(NI_LOG_INFO, "NVMe Devices not ready, wait ..\n"); - if (stop_process) + if (g_xcoder_stop_process) { ni_log(NI_LOG_ERROR, "Requested to stop ..\n"); return 1; @@ -1322,7 +1393,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) if (0 == xcoder_device_cnt) { ni_log(NI_LOG_INFO, "NVMe Devices supporting XCoder not ready, wait ..\n"); - if (stop_process) + if (g_xcoder_stop_process) { ni_log(NI_LOG_ERROR, "Requested to stop ..\n"); return 1; @@ -1403,7 +1474,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) { ni_log(NI_LOG_ERROR, "ERROR %s() ftruncate() shm_fd: %s\n", __func__, strerror(NI_ERRNO)); - //TODO: Return without closing the shared memory file descriptor flose(shm_fd)!!! + close(shm_fd); return 1; } #endif @@ -1414,7 +1485,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) { ni_log(NI_LOG_ERROR, "ERROR: %s() mmap() ni_device_queue_t: %s\n", __func__, strerror(NI_ERRNO)); - //TODO: Return without closing the shared memory file descriptor flose(shm_fd)!!! + close(shm_fd); return 1; } @@ -1429,7 +1500,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) { ni_log(NI_LOG_ERROR, "ERROR %s() open() CODERS_LCK_NAME: %s\n", __func__, strerror(NI_ERRNO)); - //TODO: Return without umappint the shared memory munmap(p_device_queue)!!! + munmap(p_device_queue, sizeof(ni_device_queue_t)); return 1; } @@ -1443,7 +1514,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) { ni_log(NI_LOG_ERROR, "ERROR %s() open() XCODERS_RETRY_LCK_NAME[%d]: " "%s\n", __func__, k, strerror(NI_ERRNO)); - //TODO: Return without umappint the shared memory munmap(p_device_queue)!!! + munmap(p_device_queue, sizeof(ni_device_queue_t)); return 1; } @@ -1509,9 +1580,12 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) device_info.hw_id = device_capabilites.xcoder_devices[j].hw_id; device_info.fw_ver_compat_warning = fw_ver_compat_warning; + memcpy(device_info.serial_number, device_capabilites.serial_number, + sizeof(device_info.serial_number)); + memcpy(device_info.model_number, device_capabilites.model_number, + sizeof(device_info.model_number)); memcpy(device_info.fw_rev, device_capabilites.fw_rev, sizeof(device_info.fw_rev)); - memcpy(device_info.fw_branch_name, device_capabilites.fw_branch_name, sizeof(device_info.fw_branch_name) - 1); memcpy(device_info.fw_commit_time, device_capabilites.fw_commit_time, @@ -1575,14 +1649,14 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) { /*! add the h/w device_info entry */ p_device_info->module_id = - g_xcoder_guid[device_info.device_type]++; + xcoder_guid[device_info.device_type]++; p_device_queue->xcoder_cnt[device_info.device_type] = - g_xcoder_guid[device_info.device_type]; + xcoder_guid[device_info.device_type]; p_device_queue->xcoders[device_info.device_type] [p_device_info->module_id] = p_device_info->module_id; ni_rsrc_get_one_device_info(&device_info); - } + } } } /*! for each device_info module */ @@ -1602,7 +1676,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) for (k = 0; k < NI_DEVICE_TYPE_XCODER_MAX; k++) { - p_device_queue->xcoder_cnt[k] = g_xcoder_guid[k]; + p_device_queue->xcoder_cnt[k] = xcoder_guid[k]; } return 0; } @@ -1625,7 +1699,7 @@ int ni_rsrc_init(int should_match_rev, int timeout_seconds) ni_device_context_t* ni_rsrc_get_device_context(ni_device_type_t device_type, int guid) { /*! get names of shared mem and lock by GUID */ - int shm_fd; + int shm_fd = 0; int lock; char shm_name[32] = { 0 }; char lck_name[32] = { 0 }; @@ -1749,7 +1823,7 @@ void ni_rsrc_free_device_context(ni_device_context_t *p_device_context) #ifdef _WIN32 UnmapViewOfFile(p_device_context->p_device_info); ReleaseMutex(p_device_context->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ close(p_device_context->lock); munmap((void *)p_device_context->p_device_info, sizeof(ni_device_info_t)); #endif @@ -1802,7 +1876,7 @@ ni_retcode_t ni_rsrc_list_devices(ni_device_type_t device_type, retval = NI_RETCODE_FAILURE; LRETURN; } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_LOCK, 0); #endif @@ -1831,7 +1905,7 @@ ni_retcode_t ni_rsrc_list_devices(ni_device_type_t device_type, memcpy(&p_device_info[i], p_device_context->p_device_info, sizeof(ni_device_info_t)); ReleaseMutex(p_device_context->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_LOCK, 0); memcpy(&p_device_info[i], p_device_context->p_device_info, sizeof(ni_device_info_t)); lockf(p_device_context->lock, F_ULOCK, 0); @@ -1853,7 +1927,7 @@ ni_retcode_t ni_rsrc_list_devices(ni_device_type_t device_type, { #ifdef _WIN32 ReleaseMutex(p_device_pool->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_ULOCK, 0); #endif } @@ -1904,6 +1978,148 @@ ni_retcode_t ni_rsrc_list_all_devices(ni_device_t *p_device) return retval; } +/*!****************************************************************************** +* \brief Grabs information for every initialized and uninitialized +* device. + +* \param list_uninitialized Flag to determine if uninitialized devices +* should be grabbed. +* +* \return +* NI_RETCODE_SUCCESS +* NI_RETCODE_INVALID_PARAM +* NI_RETCODE_FAILURE +* +* Note: Caller is responsible for allocating memory for "p_device". +*******************************************************************************/ +LIB_API ni_retcode_t ni_rsrc_list_all_devices2(ni_device_t* p_device, bool list_uninitialized) +{ + ni_retcode_t retval = NI_RETCODE_SUCCESS; + if (!p_device) + { + retval = NI_RETCODE_INVALID_PARAM; + return retval; + } + + /* Grab initialized devices. */ + + ni_log_level_t log_level = ni_log_get_level(); + + if (list_uninitialized) + { + ni_log_set_level(NI_LOG_NONE); + } + + ni_rsrc_list_all_devices(p_device); + + if (!list_uninitialized) + { + return retval; + } + + ni_log_set_level(log_level); + + /* Store device names of initialized devices. */ + + ni_device_info_t *p_dev_info; + char initialized_dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0}; + + for (int dev_index = 0; + dev_index < p_device->xcoder_cnt[NI_DEVICE_TYPE_DECODER]; dev_index++) + { + p_dev_info = &p_device->xcoders[NI_DEVICE_TYPE_DECODER][dev_index]; + strcpy(initialized_dev_names[dev_index], p_dev_info->dev_name); + } + + /* Retrieve uninitialized devices. */ + + char dev_names[NI_MAX_DEVICE_CNT][NI_MAX_DEVICE_NAME_LEN] = {0}; + int dev_count = ni_rsrc_get_local_device_list(dev_names, NI_MAX_DEVICE_CNT); + + uint32_t tmp_io_size; + ni_device_capability_t capability; + ni_device_handle_t fd; + ni_device_info_t dev_info; + + for (int dev_index = 0; dev_index < dev_count; dev_index++) + { + if (is_str_in_str_array(dev_names[dev_index], + initialized_dev_names, NI_MAX_DEVICE_CNT)) + { + continue; + } + + memset(&dev_info, 0, sizeof(ni_device_info_t)); + + strcpy(dev_info.dev_name, dev_names[dev_index]); + + retval = ni_find_blk_name(dev_info.dev_name, dev_info.blk_name, + sizeof(dev_info.blk_name)); + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_ERROR, "Failed to find block device ID for %s\n", + dev_info.dev_name); + return retval; + } + + fd = ni_device_open(dev_info.blk_name, &tmp_io_size); + if (NI_INVALID_DEVICE_HANDLE == fd) + { + ni_log(NI_LOG_ERROR, "Failed to open device: %s\n", + dev_info.dev_name); + return NI_RETCODE_FAILURE; + } + + retval = ni_device_capability_query(fd, &capability); + if (NI_RETCODE_SUCCESS != retval) + { + ni_device_close(fd); + ni_log(NI_LOG_ERROR, "Failed to query device capability: %s\n", + dev_info.dev_name); + return retval; + } + + for (int dev_type = 0; dev_type < NI_DEVICE_TYPE_XCODER_MAX; dev_type++) + { + p_device->xcoder_cnt[dev_type]++; + + p_dev_info = &p_device->xcoders[dev_type][dev_index]; + memcpy(p_dev_info->serial_number, capability.serial_number, + sizeof(capability.serial_number)); + memcpy(p_dev_info->model_number, capability.model_number, + sizeof(capability.model_number)); + memcpy(p_dev_info->fw_rev, capability.fw_rev, + sizeof(capability.fw_rev)); + if (ni_is_fw_compatible(capability.fw_rev) == 2) + { + p_dev_info->fw_ver_compat_warning = 1; + } + memcpy(p_dev_info->fw_branch_name, capability.fw_branch_name, + sizeof(capability.fw_branch_name)); + memcpy(p_dev_info->fw_commit_time, capability.fw_commit_time, + sizeof(capability.fw_commit_time)); + memcpy(p_dev_info->fw_commit_hash, capability.fw_commit_hash, + sizeof(capability.fw_commit_hash)); + memcpy(p_dev_info->fw_build_time, capability.fw_build_time, + sizeof(capability.fw_build_time)); + memcpy(p_dev_info->fw_build_id, capability.fw_build_id, + sizeof(capability.fw_build_id)); + memcpy(p_dev_info->dev_name, dev_info.dev_name, + sizeof(dev_info.dev_name)); + memcpy(p_dev_info->blk_name, dev_info.blk_name, + sizeof(dev_info.blk_name)); + p_dev_info->device_type = (ni_device_type_t)dev_type; + p_dev_info->module_id = -1; /* special value to indicate device is + not initialized */ + } + + ni_device_close(fd); + } + + return retval; +} + + void ni_rsrc_print_device_info(const ni_device_info_t *p_device_info) { int i; @@ -1924,14 +2140,14 @@ void ni_rsrc_print_device_info(const ni_device_info_t *p_device_info) { ni_log(NI_LOG_INFO, " Capabilities:\n"); ni_log(NI_LOG_INFO, - " Operations: Crop (ni_crop), Scale (ni_scale), Pad " - "(ni_pad), Overlay (ni_overlay)\n"); + " Operations: Crop (ni_quadra_crop), Scale (ni_quadra_scale), Pad " + "(ni_quadra_pad), Overlay (ni_quadra_overlay)\n"); } else if (NI_DEVICE_TYPE_AI == p_device_info->device_type) { ni_log(NI_LOG_INFO, " Capabilities:\n"); ni_log( NI_LOG_INFO, - " Operations: ROI (ni_roi), Background Replace (ni_bg)\n"); + " Operations: ROI (ni_quadra_roi), Background Replace (ni_quadra_bg)\n"); } else if (NI_DEVICE_TYPE_DECODER == p_device_info->device_type || NI_DEVICE_TYPE_ENCODER == p_device_info->device_type) { @@ -1986,66 +2202,36 @@ void ni_rsrc_print_device_info(const ni_device_info_t *p_device_info) *******************************************************************************/ LIB_API void ni_rsrc_print_all_devices_capability(void) { - int32_t i, j, k; - ni_device_t *p_xcoders = NULL; - - p_xcoders = (ni_device_t *)malloc(sizeof(ni_device_t)); + ni_device_t device = {0}; - if (NULL != p_xcoders) + if (NI_RETCODE_SUCCESS != ni_rsrc_list_all_devices(&device)) { - if (NI_RETCODE_SUCCESS == ni_rsrc_list_all_devices(p_xcoders)) - { - ni_device_info_t *p_device_info = NULL; + return; + } - for (i = 0; i < p_xcoders->xcoder_cnt[0]; i++) - { - p_device_info = &(p_xcoders->xcoders[0][i]); - ni_log(NI_LOG_INFO, "Device #%d:\n", i); - ni_log(NI_LOG_INFO, " F/W rev: %.*s\n", - (int)sizeof(p_device_info->fw_rev), - p_device_info->fw_rev); - ni_log(NI_LOG_INFO, " F/W & S/W compatibility: %s\n", - p_device_info->fw_ver_compat_warning ? - "no, possible missing features" : - "yes"); - ni_log(NI_LOG_INFO, " F/W branch: %s\n", - p_device_info->fw_branch_name); - ni_log(NI_LOG_INFO, " F/W commit time: %s\n", - p_device_info->fw_commit_time); - ni_log(NI_LOG_INFO, " F/W commit hash: %s\n", - p_device_info->fw_commit_hash); - ni_log(NI_LOG_INFO, " F/W build time: %s\n", - p_device_info->fw_build_time); - ni_log(NI_LOG_INFO, " F/W build id: %s\n", - p_device_info->fw_build_id); - ni_log(NI_LOG_INFO, " DeviceID: %s\n", - p_device_info->dev_name); - ni_log(NI_LOG_INFO, " BlockDeviceID: %s\n", - p_device_info->blk_name); - ni_log(NI_LOG_INFO, - " PixelFormats: yuv420p, yuv420p10le, nv12, p010le, " - "ni\n"); - - // print out all modules on the same card - for (j = 0; j < NI_DEVICE_TYPE_XCODER_MAX; j++) - { - for (k = 0; k < p_xcoders->xcoder_cnt[j]; k++) - { - if (0 == - strcmp(p_device_info->dev_name, - p_xcoders->xcoders[j][k].dev_name)) - { - ni_rsrc_print_device_info( - &(p_xcoders->xcoders[j][k])); - } - } - } + print_device(&device); +} - ni_log(NI_LOG_INFO, "\n"); - } - } - free(p_xcoders); +/*!***************************************************************************** +* \brief Prints detailed capability information for all initialized +* devices and general information about uninitialized devices. + +* \param list_uninitialized Flag to determine if uninitialized devices +* should be grabbed. +* +* \return none +* +*******************************************************************************/ +LIB_API void ni_rsrc_print_all_devices_capability2(bool list_uninitialized) +{ + ni_device_t device = {0}; + + if (NI_RETCODE_SUCCESS != ni_rsrc_list_all_devices2(&device, list_uninitialized)) + { + return; } + + print_device(&device); } /*!****************************************************************************** @@ -2125,7 +2311,7 @@ int ni_rsrc_get_available_device(int width, int height, int frame_rate, { int i, rc; int guid = -1; - int num_sw_instances = 0; + uint32_t num_sw_instances = 0; ni_device_pool_t *p_device_pool = NULL; ni_device_info_t *p_dev_info = NULL; ni_device_context_t *p_device_context = NULL; @@ -2151,7 +2337,7 @@ int ni_rsrc_get_available_device(int width, int height, int frame_rate, ni_rsrc_free_device_pool(p_device_pool); return NI_RETCODE_FAILURE; } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_LOCK, 0); #endif @@ -2202,14 +2388,25 @@ int ni_rsrc_get_available_device(int width, int height, int frame_rate, //ni_rsrc_free_device_pool(p_device_pool); //return -1; } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_LOCK, 0); #endif ni_rsrc_update_record(p_device_context, &p_session_context); p_dev_info = p_device_context->p_device_info; - if (i == 0 || p_dev_info->model_load < least_model_load || + // here we select the best load + // for decoder/encoder: check the model_load + // for hwuploader: check directly hwupload count in query result + if (NI_DEVICE_TYPE_UPLOAD == device_type) + { + if (i == 0 || p_session_context.load_query.active_hwuploaders < num_sw_instances) + { + guid = tmp_id; + num_sw_instances = p_session_context.load_query.active_hwuploaders; + memcpy(&dev_info, p_dev_info, sizeof(ni_device_info_t)); + } + } else if (i == 0 || p_dev_info->model_load < least_model_load || (p_dev_info->model_load == least_model_load && p_dev_info->active_num_inst < num_sw_instances)) { @@ -2222,13 +2419,13 @@ int ni_rsrc_get_available_device(int width, int height, int frame_rate, #ifdef _WIN32 ReleaseMutex(p_device_context->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_ULOCK, 0); #endif ni_rsrc_free_device_context(p_device_context); } - // TODO: how should scaler (and AI in the future) be handled here? + // scaler and AI load handling will be considered in the future if (guid >= 0) { // calculate the load this stream will generate based on its resolution and @@ -2268,7 +2465,7 @@ int ni_rsrc_get_available_device(int width, int height, int frame_rate, #ifdef _WIN32 ReleaseMutex(p_device_pool->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_ULOCK, 0); #endif @@ -2320,7 +2517,7 @@ int ni_rsrc_update_device_load(ni_device_context_t *p_device_context, int load, __func__, p_device_context->lock); return NI_RETCODE_FAILURE; } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_LOCK, 0); #endif @@ -2333,7 +2530,7 @@ int ni_rsrc_update_device_load(ni_device_context_t *p_device_context, int load, #ifdef _WIN32 ReleaseMutex(p_device_context->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_ULOCK, 0); #endif @@ -2425,7 +2622,7 @@ ni_device_context_t *ni_rsrc_allocate_auto int i, count, rc; int guid = -1; int load = 0; - int num_sw_instances = 0; + uint32_t num_sw_instances = 0; int least_model_load = 0; unsigned long job_mload = 0; @@ -2439,7 +2636,7 @@ ni_device_context_t *ni_rsrc_allocate_auto { ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n", __func__, p_device_pool->lock); } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_LOCK, 0); #endif @@ -2489,7 +2686,7 @@ ni_device_context_t *ni_rsrc_allocate_auto ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n", __func__, p_device_context->lock); } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_LOCK, 0); #endif ni_rsrc_update_record(p_device_context, &p_session_context); @@ -2541,7 +2738,7 @@ ni_device_context_t *ni_rsrc_allocate_auto #ifdef _WIN32 ReleaseMutex(p_device_context->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_ULOCK, 0); #endif ni_rsrc_free_device_context(p_device_context); @@ -2572,7 +2769,7 @@ ni_device_context_t *ni_rsrc_allocate_auto ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n", __func__, p_device_context->lock); } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_LOCK, 0); #endif p_device_context->p_device_info->xcode_load_pixel += job_mload; @@ -2580,7 +2777,7 @@ ni_device_context_t *ni_rsrc_allocate_auto //p_device_context->p_device_info->model_load = (int)((double)(p_device_context->p_device_info->xcode_load_pixel) * 100 / total_cap); #ifdef _WIN32 ReleaseMutex(p_device_context->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ if (msync((void *)p_device_context->p_device_info, sizeof(ni_device_info_t), MS_SYNC | MS_INVALIDATE)) { @@ -2603,7 +2800,7 @@ ni_device_context_t *ni_rsrc_allocate_auto END: #ifdef _WIN32 ReleaseMutex(p_device_pool->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_ULOCK, 0); #endif ni_rsrc_free_device_pool(p_device_pool); @@ -2662,7 +2859,7 @@ ni_device_context_t *ni_rsrc_allocate_direct ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n", __func__, p_device_context->lock); } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_LOCK, 0); #endif @@ -2680,7 +2877,7 @@ ni_device_context_t *ni_rsrc_allocate_direct p_device_context->p_device_info->xcode_load_pixel += job_mload; // Remove as the value is getting from the FW //p_device_context->p_device_info->model_load = (int)((double)(p_device_context->p_device_info->xcode_load_pixel) * 100 / total_cap); -#ifdef __linux__ +#if __linux__ || __APPLE__ if (msync((void *)p_device_context->p_device_info, sizeof(ni_device_info_t), MS_SYNC | MS_INVALIDATE)) { @@ -2693,7 +2890,7 @@ ni_device_context_t *ni_rsrc_allocate_direct #ifdef _WIN32 ReleaseMutex(p_device_context->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_ULOCK, 0); #endif @@ -2714,7 +2911,7 @@ ni_device_context_t *ni_rsrc_allocate_direct ni_rsrc_move_device_to_end_of_pool(device_type, guid, p_device_pool); ReleaseMutex(p_device_pool->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_LOCK, 0); ni_rsrc_move_device_to_end_of_pool(device_type, guid, p_device_pool); @@ -2784,7 +2981,7 @@ void ni_rsrc_release_resource(ni_device_context_t *p_device_context, ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n", __func__, p_device_context->lock); } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_LOCK, 0); #endif @@ -2798,7 +2995,7 @@ void ni_rsrc_release_resource(ni_device_context_t *p_device_context, p_device_context->p_device_info->xcode_load_pixel -= load; // Remove as the value is getting from the FW // p_device_context->p_device_info->model_load = (int)((double)(p_device_context->p_device_info->xcode_load_pixel) * 100 / total_cap); -#ifdef __linux__ +#if __linux__ || __APPLE__ if (msync((void *)p_device_context->p_device_info, sizeof(ni_device_info_t), MS_SYNC | MS_INVALIDATE)) { ni_log(NI_LOG_ERROR, "ERROR %s() msync() p_device_context->" @@ -2809,11 +3006,196 @@ void ni_rsrc_release_resource(ni_device_context_t *p_device_context, #ifdef _WIN32 ReleaseMutex(p_device_context->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_context->lock, F_ULOCK, 0); #endif } +/*!***************************************************************************** +* \brief check the NetInt h/w device in resource pool on the host. +* +* \param[in] guid the global unique device index in resource pool +* device_type NI_DEVICE_TYPE_DECODER or NI_DEVICE_TYPE_ENCODER +* +* \return +* NI_RETCODE_SUCCESS +*******************************************************************************/ +int ni_rsrc_check_hw_available(int guid, ni_device_type_t device_type) +{ + ni_device_pool_t *p_device_pool = NULL; + ni_device_context_t *p_device_ctx = NULL; + ni_session_context_t session_ctx = {0}; + ni_xcoder_params_t api_param = {0}; + uint32_t max_nvme_io_size = 0; + bool b_release_pool_mtx = false; + ni_retcode_t retval = NI_RETCODE_SUCCESS; + int retry_cnt = 0; + + if (guid < 0) + { + ni_log(NI_LOG_ERROR, "ERROR invalid guid:%d\n", guid); + return NI_RETCODE_INVALID_PARAM; + } + + if (!(NI_DEVICE_TYPE_DECODER == device_type || + NI_DEVICE_TYPE_ENCODER == device_type)) + { + ni_log(NI_LOG_ERROR, "ERROR: Unknown device type:%d\n", device_type); + return NI_RETCODE_INVALID_PARAM; + } + + ni_device_session_context_init(&session_ctx); + session_ctx.keep_alive_timeout = NI_DEFAULT_KEEP_ALIVE_TIMEOUT; + session_ctx.src_bit_depth = 8; + session_ctx.hw_id = guid; + + if (NI_DEVICE_TYPE_DECODER == device_type) + { + if (ni_decoder_init_default_params(&api_param, 30, 1, NI_MIN_BITRATE, + XCODER_MIN_ENC_PIC_WIDTH, + XCODER_MIN_ENC_PIC_HEIGHT) < 0) + { + ni_log(NI_LOG_ERROR, "ERROR: set decoder default params error\n"); + return NI_RETCODE_INVALID_PARAM; + } + } else + { + if (ni_encoder_init_default_params( + &api_param, 30, 1, NI_MIN_BITRATE, XCODER_MIN_ENC_PIC_WIDTH, + XCODER_MIN_ENC_PIC_HEIGHT, NI_CODEC_FORMAT_H264) < 0) + { + ni_log(NI_LOG_ERROR, "ERROR: set encoder default params error\n"); + return NI_RETCODE_INVALID_PARAM; + } + } + session_ctx.p_session_config = &api_param; + + p_device_pool = ni_rsrc_get_device_pool(); + if (!p_device_pool) + { + ni_log(NI_LOG_ERROR, "ERROR: get device poll failed\n"); + retval = NI_RETCODE_ERROR_GET_DEVICE_POOL; + LRETURN; + } + +#ifdef _WIN32 + if (WAIT_ABANDONED == + WaitForSingleObject(p_device_pool->lock, + INFINITE)) // no time-out interval) + { + ni_log(NI_LOG_INFO, + "ERROR: ni_rsrc_list_devices() failed to obtain mutex: %p\n", + p_device_pool->lock); + retval = NI_RETCODE_FAILURE; + LRETURN; + } +#elif __linux__ + lockf(p_device_pool->lock, F_LOCK, 0); +#endif + b_release_pool_mtx = true; + + // get device context + p_device_ctx = ni_rsrc_get_device_context(device_type, guid); + if (p_device_ctx) + { + session_ctx.device_handle = ni_device_open( + p_device_ctx->p_device_info->blk_name, &max_nvme_io_size); + session_ctx.blk_io_handle = session_ctx.device_handle; + if (NI_INVALID_DEVICE_HANDLE == session_ctx.device_handle) + { + ni_log(NI_LOG_ERROR, "open device failed: %d\n", errno); + retval = NI_RETCODE_ERROR_INVALID_HANDLE; + } else + { +#ifdef _WIN32 + session_ctx.event_handle = ni_create_event(); + if (NI_INVALID_EVENT_HANDLE == session_ctx.event_handle) + { + ni_log(NI_LOG_INFO, "Error create envent:%d\n", GetLastError()); + retval = NI_RETCODE_FAILURE; + LRETURN; + } +#endif + retval = ni_device_session_query(&session_ctx, device_type); + if (NI_RETCODE_SUCCESS != retval) + { + ni_log(NI_LOG_ERROR, + "guid %d. %s, %s is not avaiable, type: %d, retval:%d\n", + guid, p_device_ctx->p_device_info->dev_name, + p_device_ctx->p_device_info->blk_name, device_type, + retval); + retval = NI_RETCODE_FAILURE; + } else + { + while (1) + { + retry_cnt++; + retval = ni_device_session_open(&session_ctx, device_type); + ni_device_session_close(&session_ctx, 0, device_type); + if (retval == NI_RETCODE_SUCCESS) + { + ni_log(NI_LOG_INFO, "guid %d. %s %s is avaiable\n", + guid, p_device_ctx->p_device_info->dev_name, + p_device_ctx->p_device_info->blk_name); + break; + } else if ( + retry_cnt < 10 && + retval == + NI_RETCODE_ERROR_VPU_RECOVERY) // max 2 seconds + { + ni_log(NI_LOG_INFO, + "vpu recovery happened on guid %d. %s %s, retry " + "cnt:%d\n", + guid, p_device_ctx->p_device_info->dev_name, + p_device_ctx->p_device_info->blk_name, + retry_cnt); +#ifndef _WIN32 + ni_usleep(200000); // 200 ms +#endif + continue; + } else + { + ni_log(NI_LOG_ERROR, + "session open error guid %d. %s, %s, type: %d, " + "retval:%d\n", + guid, p_device_ctx->p_device_info->dev_name, + p_device_ctx->p_device_info->blk_name, + device_type, retval); + retval = NI_RETCODE_FAILURE; + break; + } + } + } + } + } else + { + ni_log(NI_LOG_ERROR, + "Error get device resource: guid %d, device_ctx %p\n", guid, + p_device_ctx); + retval = NI_RETCODE_FAILURE; + } + +END: + + if (b_release_pool_mtx) + { +#ifdef _WIN32 + ReleaseMutex(p_device_pool->lock); +#elif __linux__ + lockf(p_device_pool->lock, F_ULOCK, 0); +#endif + } + + ni_close_event(session_ctx.event_handle); + ni_device_close(session_ctx.device_handle); + + ni_rsrc_free_device_context(p_device_ctx); + + ni_rsrc_free_device_pool(p_device_pool); + + return retval; +} + /*!***************************************************************************** * \brief Remove an NetInt h/w device from resource pool on the host. * @@ -2842,13 +3224,12 @@ int ni_rsrc_remove_device(const char* dev) ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n", __func__, p_device_pool->lock); } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_LOCK, 0); #endif p_device_queue = p_device_pool->p_device_queue; - // TODO: this part of logic need review // assume all XCODER types are grouped count = p_device_queue->xcoder_cnt[NI_DEVICE_TYPE_DECODER]; int guid; @@ -2912,7 +3293,7 @@ int ni_rsrc_remove_device(const char* dev) } } rc = NI_RETCODE_SUCCESS; -#elif __linux__ +#elif __linux__ || __APPLE__ #ifndef _ANDROID for (k = 0; k < NI_DEVICE_TYPE_XCODER_MAX; k++) @@ -2956,7 +3337,7 @@ int ni_rsrc_remove_device(const char* dev) p_device_queue->xcoders[k][count - 1] = -1; p_device_queue->xcoder_cnt[k]--; } -#ifdef __linux__ +#if __linux__ || __APPLE__ if (msync((void *)p_device_pool->p_device_queue, sizeof(ni_device_queue_t), MS_SYNC | MS_INVALIDATE)) { @@ -2973,7 +3354,7 @@ int ni_rsrc_remove_device(const char* dev) #ifdef _WIN32 ReleaseMutex(p_device_pool->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_ULOCK, 0); #endif ni_rsrc_free_device_pool(p_device_pool); @@ -3019,7 +3400,7 @@ int ni_rsrc_add_device(const char* dev, int should_match_rev) ni_log(NI_LOG_ERROR, "ERROR: %s() failed to obtain mutex: %p\n", __func__, p_device_pool->lock); } -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_LOCK, 0); #endif @@ -3163,7 +3544,7 @@ int ni_rsrc_add_device(const char* dev, int should_match_rev) ni_rsrc_free_device_context(p_device_context); } } // for each device_info module -#ifdef __linux__ +#if __linux__ || __APPLE__ if (msync((void *)p_device_pool->p_device_queue, sizeof(ni_device_queue_t), MS_SYNC | MS_INVALIDATE)) { @@ -3191,7 +3572,7 @@ int ni_rsrc_add_device(const char* dev, int should_match_rev) #ifdef _WIN32 ReleaseMutex(p_device_pool->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ lockf(p_device_pool->lock, F_ULOCK, 0); #endif @@ -3216,7 +3597,7 @@ void ni_rsrc_free_device_pool(ni_device_pool_t* p_device_pool) { #ifdef _WIN32 CloseHandle(p_device_pool->lock); -#elif __linux__ +#elif __linux__ || __APPLE__ close(p_device_pool->lock); #endif } @@ -3330,35 +3711,36 @@ int ni_rsrc_unlock(int device_type, ni_lock_handle_t lock) { return NI_RETCODE_FAILURE; } - else + + int count = 0; + ni_lock_handle_t status = NI_INVALID_LOCK_HANDLE; + do { - int count = 0; - ni_lock_handle_t status = NI_INVALID_LOCK_HANDLE; - do + if (count >= 1) { - if (count >= 1) - { - ni_usleep(LOCK_WAIT); - } + ni_usleep(LOCK_WAIT); + } #ifdef _WIN32 - if (ReleaseMutex(lock)) - { - status = (ni_lock_handle_t)(0); - } + if (ReleaseMutex(lock)) + { + status = (ni_lock_handle_t)(0); + } #else - status = lockf(lock, F_ULOCK, 0); + status = lockf(lock, F_ULOCK, 0); #endif - count++; - if (count > MAX_LOCK_RETRY) - { - ni_log(NI_LOG_ERROR, "Can not unlock the lock after 6s"); - return NI_RETCODE_ERROR_UNLOCK_DEVICE; - } - } while (status != (ni_lock_handle_t)(0)); - } -#ifdef __linux__ + count++; + if (count > MAX_LOCK_RETRY) + { + ni_log(NI_LOG_ERROR, "Can not unlock the lock after 6s"); + return NI_RETCODE_ERROR_UNLOCK_DEVICE; + } + } while (status != (ni_lock_handle_t)(0)); + +#ifdef _WIN32 + CloseHandle(lock); +#else close(lock); -#endif //__linux__ defined +#endif //_WIN32 defined return NI_RETCODE_SUCCESS; } diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_api.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_api.h index 23dab878..44984853 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_api.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_api.h @@ -58,22 +58,22 @@ typedef enum static const char *ni_codec_format_str[] = {"H.264", "H.265", "VP9", "JPEG", "AV1"}; -static const char *ni_dec_name_str[] = {"h264_ni_dec", "h265_ni_dec", - "vp9_ni_dec", "jpeg_ni_dec"}; -static const char *ni_enc_name_str[] = {"h264_ni_enc", "h265_ni_enc", "empty", - "jpeg_ni_enc", "av1_ni_enc"}; +static const char *ni_dec_name_str[] = {"h264_ni_quadra_dec", "h265_ni_quadra_dec", + "vp9_ni_quadra_dec", "jpeg_ni_quadra_dec"}; +static const char *ni_enc_name_str[] = {"h264_ni_quadra_enc", "h265_ni_quadra_enc", "empty", + "jpeg_ni_quadra_enc", "av1_ni_quadra_enc"}; typedef enum { - EN_IDLE, - EN_ACTIVE -}ni_sw_instance_status_t; + EN_IDLE, + EN_ACTIVE +} ni_sw_instance_status_t; -typedef enum +typedef enum { - EN_ALLOC_LEAST_LOAD, - EN_ALLOC_LEAST_INSTANCE -}ni_alloc_rule_t; + EN_ALLOC_LEAST_LOAD, + EN_ALLOC_LEAST_INSTANCE +} ni_alloc_rule_t; typedef struct _ni_device_queue { @@ -127,10 +127,13 @@ typedef struct _ni_device_info uint8_t fw_build_time[26]; uint8_t fw_build_id[256]; + uint8_t serial_number[20]; + uint8_t model_number[40]; + /*! general capability attributes */ int max_fps_4k; /*! max fps for 4K */ int max_instance_cnt; /*! max number of instances */ - int active_num_inst; /*! active numver of instances */ + uint32_t active_num_inst; /*! active numver of instances */ ni_device_type_t device_type; /*! decoder or encoder */ /*! decoder/encoder/scaler/ai codec support capabilities */ @@ -140,6 +143,7 @@ typedef struct _ni_device_info ni_lock_handle_t lock; } ni_device_info_t; +// This structure is very big (2.6MB). Recommend storing in heap typedef struct _ni_device { int xcoder_cnt[NI_DEVICE_TYPE_XCODER_MAX]; @@ -153,15 +157,6 @@ typedef struct _ni_device_context ni_device_info_t * p_device_info; } ni_device_context_t; -typedef struct _ni_card_info -{ - char *name; - int index; - bool isActive; - const char *fwVer; - const char *hwVer; -} ni_card_info_t; - /*!****************************************************************************** * \brief Initialize and create all resources required to work with NETINT NVMe * transcoder devices. This is a high level API function which is used @@ -271,6 +266,23 @@ LIB_API ni_retcode_t ni_rsrc_list_devices(ni_device_type_t device_type, *******************************************************************************/ LIB_API ni_retcode_t ni_rsrc_list_all_devices(ni_device_t* p_device); +/*!****************************************************************************** +* \brief Grabs information for every initialized and uninitialized +* device. + +* \param[out] p_device The device information returned. +* \param list_uninitialized Flag to determine if uninitialized devices +* should be grabbed. +* +* \return +* NI_RETCODE_SUCCESS +* NI_RETCODE_INVALID_PARAM +* NI_RETCODE_FAILURE +* +* Note: Caller is responsible for allocating memory for "p_device". +*******************************************************************************/ +LIB_API ni_retcode_t ni_rsrc_list_all_devices2(ni_device_t* p_device, bool list_uninitialized); + /*!***************************************************************************** * \brief Print detailed capability information of all devices * on the system. @@ -282,6 +294,18 @@ LIB_API ni_retcode_t ni_rsrc_list_all_devices(ni_device_t* p_device); *******************************************************************************/ LIB_API void ni_rsrc_print_all_devices_capability(void); +/*!***************************************************************************** +* \brief Prints detailed capability information for all initialized +* devices and general information about uninitialized devices. + +* \param list_uninitialized Flag to determine if uninitialized devices +* should be grabbed. +* +* \return none +* +*******************************************************************************/ +LIB_API void ni_rsrc_print_all_devices_capability2(bool list_uninitialized); + /*!****************************************************************************** * \brief Query a specific device with detailed information on the system @@ -426,6 +450,17 @@ ni_device_context_t *ni_rsrc_allocate_simple_direct LIB_API void ni_rsrc_release_resource(ni_device_context_t *p_ctxt, unsigned long load); +/*!***************************************************************************** +* \brief check the NetInt h/w device in resource pool on the host. +* +* \param[in] guid the global unique device index in resource pool +* device_type NI_DEVICE_TYPE_DECODER or NI_DEVICE_TYPE_ENCODER +* +* \return +* NI_RETCODE_SUCCESS +*******************************************************************************/ +LIB_API int ni_rsrc_check_hw_available(int guid, ni_device_type_t device_type); + /*!***************************************************************************** * \brief Remove an NetInt h/w device from resource pool on the host. * diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_list.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_list.c index a4682f92..dbe0f060 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_list.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_list.c @@ -31,7 +31,7 @@ * ******************************************************************************/ -#ifdef __linux__ +#if __linux__ || __APPLE__ #include #include #elif _WIN32 @@ -55,18 +55,23 @@ int32_t main(int argc, char *argv[]) { int opt; - ni_log_level_t log_level; + bool list_uninitialized = false; + ni_log_level_t log_level = NI_LOG_INFO; // arg handling - while ((opt = getopt(argc, argv, "hvl:")) != -1) + while ((opt = getopt(argc, argv, "ahvl:")) != -1) { switch (opt) { + case 'a': + list_uninitialized = true; + break; case 'h': // help message printf("-------- ni_rsrc_list v%s --------\n" - "Display information for detected Netint hardware.\n" + "Display information for NETINT hardware.\n" "\n" + "-a Print includes info for uninitialized cards.\n" "-h Display this help and exit.\n" "-v Print version info.\n" "-l Set loglevel of libxcoder API.\n" @@ -75,10 +80,12 @@ int32_t main(int argc, char *argv[]) NI_XCODER_REVISION); return 0; case 'v': - printf("Ver: %s\n" - "Date: %s\n" - "ID: %s\n", - NI_XCODER_REVISION, NI_SW_RELEASE_TIME, NI_SW_RELEASE_ID); + printf("Release ver: %s\n" + "API ver: %s\n" + "Date: %s\n" + "ID: %s\n", + NI_XCODER_REVISION, LIBXCODER_API_VERSION, + NI_SW_RELEASE_TIME, NI_SW_RELEASE_ID); return 0; case 'l': log_level = arg_to_ni_log_level(optarg); @@ -97,6 +104,6 @@ int32_t main(int argc, char *argv[]) } } - ni_rsrc_print_all_devices_capability(); + ni_rsrc_print_all_devices_capability2(list_uninitialized); return 0; } diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_mon.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_mon.c index 5db09d0f..0d57a901 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_mon.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_mon.c @@ -31,7 +31,7 @@ * ******************************************************************************/ -#ifdef __linux__ +#if __linux__ || __APPLE__ #include #include #endif @@ -60,7 +60,7 @@ static BOOL WINAPI console_ctrl_handler(DWORD ctrl_type) { - stop_process = 1; + g_xcoder_stop_process = 1; return TRUE; /*! switch (ctrl_type) @@ -71,7 +71,7 @@ static BOOL WINAPI console_ctrl_handler(DWORD ctrl_type) case CTRL_LOGOFF_EVENT: // User logs off. Passed only to services! case CTRL_SHUTDOWN_EVENT: // System is shutting down. Passed only to services! { - stop_process = 1; + g_xcoder_stop_process = 1; break; return TRUE; } @@ -96,7 +96,7 @@ void sig_handler(int sig) { if (sig == SIGTERM || sig == SIGINT || sig == SIGHUP) { - stop_process = 1; + g_xcoder_stop_process = 1; } } @@ -308,7 +308,7 @@ int main(int argc, char *argv[]) char buf[64] = {0}; time_t hours, minutes, seconds; int opt; - ni_log_level_t log_level; + ni_log_level_t log_level = NI_LOG_INFO; checkInterval = 0; @@ -388,10 +388,12 @@ int main(int argc, char *argv[]) NI_XCODER_REVISION); return 0; case 'v': - printf("Ver: %s\n" - "Date: %s\n" - "ID: %s\n", - NI_XCODER_REVISION, NI_SW_RELEASE_TIME, NI_SW_RELEASE_ID); + printf("Release ver: %s\n" + "API ver: %s\n" + "Date: %s\n" + "ID: %s\n", + NI_XCODER_REVISION, LIBXCODER_API_VERSION, NI_SW_RELEASE_TIME, + NI_SW_RELEASE_ID); return 0; case '?': if (isprint(opt)) @@ -437,7 +439,7 @@ int main(int argc, char *argv[]) #ifdef _ANDROID system("chown mediacodec:mediacodec /dev/shm_netint/*"); #endif - while (!stop_process) + while (!g_xcoder_stop_process) { now = time(NULL); ltime = localtime(&now); diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_priv.cpp b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_priv.cpp index 567445ea..76acd347 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_priv.cpp +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_priv.cpp @@ -33,7 +33,7 @@ #include #include -#ifdef __linux__ +#if __linux__ || __APPLE__ #include #include #include @@ -51,7 +51,7 @@ #include "ni_log.h" #include "ni_util.h" -uint32_t stop_process = 0; +uint32_t g_xcoder_stop_process = 0; /*!****************************************************************************** * \brief @@ -224,7 +224,7 @@ void ni_rsrc_get_lock_name(ni_device_type_t device_type, int32_t guid, char* p_n char type = device_type_chr[GET_XCODER_DEVICE_TYPE(device_type)]; if (NULL != p_name) { - snprintf(p_name, max_name_len, "%s/lck_%c%d", LOCK_DIR, type, guid); + snprintf(p_name, max_name_len, "%s/NI_lck_%c%d", LOCK_DIR, type, guid); } } @@ -241,7 +241,7 @@ void ni_rsrc_get_shm_name(ni_device_type_t device_type, int32_t guid, char* p_na /*! assume there is enough space allocated in name */ if (NULL != p_name) { - snprintf(p_name, max_name_len, "shm_%c%d", type, guid); + snprintf(p_name, max_name_len, "NI_shm_%c%d", type, guid); } } @@ -388,12 +388,12 @@ void ni_rsrc_get_one_device_info(ni_device_info_t* p_device_info) *******************************************************************************/ void ni_rsrc_update_record(ni_device_context_t* p_device_context, ni_session_context_t* p_session_context) { - int i = 0; + uint32_t i = 0; - if( (!p_device_context) || (!p_session_context) ) - { - return; - } + if ((!p_device_context) || (!p_session_context)) + { + return; + } p_device_context->p_device_info->load = p_session_context->load_query.current_load; p_device_context->p_device_info->active_num_inst = p_session_context->load_query.total_contexts; @@ -420,7 +420,7 @@ void ni_rsrc_update_record(ni_device_context_t* p_device_context, ni_session_con p_session_context->load_query.context_status[i].fps; } } -#elif __linux__ +#elif __linux__ || __APPLE__ /*!****************************************************************************** * \brief @@ -567,12 +567,12 @@ void ni_rsrc_get_one_device_info (ni_device_info_t * p_device_info) *******************************************************************************/ void ni_rsrc_update_record(ni_device_context_t *p_device_context, ni_session_context_t *p_session_context) { - int j; + uint32_t j; - if( (!p_device_context) || (!p_session_context) ) - { - return; - } + if ((!p_device_context) || (!p_session_context)) + { + return; + } p_device_context->p_device_info->load = p_session_context->load_query.current_load; p_device_context->p_device_info->active_num_inst = p_session_context->load_query.total_contexts; diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_priv.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_priv.h index 9b780b7b..0054f656 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_priv.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_priv.h @@ -35,29 +35,25 @@ extern "C" { #include "ni_device_api.h" #ifdef _ANDROID -#define LOCK_DIR "/dev/shm_netint" -#define CODERS_LCK_NAME "/dev/shm_netint/LCK_CODERS" -static const char *XCODERS_RETRY_LCK_NAME[] = { - "/dev/shm_netint/RETRY_LCK_DECODERS", "/dev/shm_netint/RETRY_LCK_ENCODERS", - "/dev/shm_netint/RETRY_LCK_SCALERS", "/dev/shm_netint/RETRY_LCK_AI"}; +#define LOCK_DIR "/dev/shm_netint" +#elif __APPLE__ +#define LOCK_DIR "/tmp" #else #define LOCK_DIR "/dev/shm" -#define CODERS_LCK_NAME "/dev/shm/LCK_CODERS" -static const char *XCODERS_RETRY_LCK_NAME[] = { - "/dev/shm/RETRY_LCK_DECODERS", "/dev/shm/RETRY_LCK_ENCODERS", - "/dev/shm/RETRY_LCK_SCALERS", "/dev/shm/RETRY_LCK_AI"}; #endif -#define CODERS_SHM_NAME "SHM_CODERS" +#define CODERS_LCK_NAME LOCK_DIR "/NI_LCK_CODERS" + +static const char *XCODERS_RETRY_LCK_NAME[] = { + LOCK_DIR "/NI_RETRY_LCK_DECODERS", LOCK_DIR "/NI_RETRY_LCK_ENCODERS", + LOCK_DIR "/NI_RETRY_LCK_SCALERS", LOCK_DIR "/NI_RETRY_LCK_AI"}; + +#define CODERS_SHM_NAME "NI_SHM_CODERS" #define MAX_LOCK_RETRY 6000 #define LOCK_WAIT 10000 // wait in us -#ifdef _MSC_VER -extern uint32_t stop_process; -#else -extern LIB_API uint32_t stop_process; -#endif +extern LIB_API uint32_t g_xcoder_stop_process; void ni_rsrc_get_lock_name(ni_device_type_t device_type, int32_t guid, char* p_name, size_t max_name_len); void ni_rsrc_get_shm_name(ni_device_type_t device_type, int32_t guid, char* p_name, size_t max_name_len); diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_update.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_update.c index 7b5610d2..69edc306 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_update.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_rsrc_update.c @@ -36,7 +36,7 @@ #include #include "ni_log.h" -#ifdef __linux__ +#if __linux__ || __APPLE__ #include #include #endif @@ -50,6 +50,8 @@ #define DEV_NAME_PREFIX "\\\\.\\Scsi" #elif __linux__ #define DEV_NAME_PREFIX "/dev/nvme" +#elif __APPLE__ +#define DEV_NAME_PREFIX "/dev/disk" #endif /*!****************************************************************************** @@ -109,7 +111,7 @@ int main(int argc, char *argv[]) char char_dev_name[64]; int should_match_rev = 1; int add_dev = 1; // default is to add(not delete) a resource - ni_log_level_t log_level; + ni_log_level_t log_level = NI_LOG_INFO; if (argc == 1) { display_help(); @@ -148,11 +150,12 @@ int main(int argc, char *argv[]) } break; case 'v': - printf("Ver: %s\n" - "Date: %s\n" - "ID: %s\n", - NI_XCODER_REVISION, NI_SW_RELEASE_TIME, - NI_SW_RELEASE_ID); + printf("Release ver: %s\n" + "API ver: %s\n" + "Date: %s\n" + "ID: %s\n", + NI_XCODER_REVISION, LIBXCODER_API_VERSION, + NI_SW_RELEASE_TIME, NI_SW_RELEASE_ID); return 0; case 'h': default: diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_util.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_util.c index baef844f..8800e06a 100755 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_util.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_util.c @@ -26,7 +26,7 @@ * *******************************************************************************/ -#ifdef __linux__ +#if __linux__ || __APPLE__ #include #include #include @@ -756,7 +756,6 @@ ni_queue_node_t *ni_buffer_pool_expand(ni_queue_buffer_pool_t *pool) for (i = 0; i < 200; i++) { - //TODO: What happens is ni_buffer_pool_allocate_buffer fails and returns a NULL pointer? if (NULL == ni_buffer_pool_allocate_buffer(pool)) { ni_log(NI_LOG_FATAL, @@ -939,6 +938,9 @@ ni_retcode_t ni_find_blk_name(const char *p_dev, char *p_out_buf, int out_buf_le "guess.\n"); snprintf(p_out_buf, out_buf_len, "%s", p_dev); return NI_RETCODE_SUCCESS; +#elif __APPLE__ + snprintf(p_out_buf, out_buf_len, "%s", p_dev); + return NI_RETCODE_SUCCESS; #else FILE *cmd_fp; char cmd_ret[16] = ""; @@ -1301,30 +1303,28 @@ ni_retcode_t ni_queue_push(ni_queue_buffer_pool_t *p_buffer_pool, { p_queue->p_first = p_queue->p_last = temp; p_queue->p_first->p_prev = NULL; + p_queue->count++; } else { p_queue->p_last->p_next = temp; temp->p_prev = p_queue->p_last; p_queue->p_last = temp; - } + p_queue->count++; - p_queue->count++; - - //ni_log(NI_LOG_TRACE, "%s exit: p_first=%"PRId64", p_last=%"PRId64", count=%d\n", __func__, p_queue->p_first, p_queue->p_last, p_queue->count); - - if (p_queue->count > XCODER_MAX_NUM_QUEUE_ENTRIES) - { - ni_log(NI_LOG_DEBUG, - "%s: queue overflow, remove oldest entry, count=%u\n", __func__, - p_queue->count); - abort(); - //Remove oldest one - temp = p_queue->p_first->p_next; - // free(p_queue->p_first); - ni_buffer_pool_return_buffer(p_queue->p_first, p_buffer_pool); - p_queue->p_first = temp; - p_queue->p_first->p_prev = NULL; - p_queue->count--; + // Assume the oldest one is useless when reaching this situation. + if (p_queue->count > XCODER_MAX_NUM_QUEUE_ENTRIES) + { + ni_log(NI_LOG_DEBUG, + "%s: queue overflow, remove oldest entry, count=%u\n", + __func__, p_queue->count); + //Remove oldest one + temp = p_queue->p_first->p_next; + // free(p_queue->p_first); + ni_buffer_pool_return_buffer(p_queue->p_first, p_buffer_pool); + p_queue->p_first = temp; + p_queue->p_first->p_prev = NULL; + p_queue->count--; + } } END: @@ -2039,182 +2039,6 @@ LIB_API int ni_remove_emulation_prevent_bytes(uint8_t *buf, int size) return remove_bytes; } -#ifdef MEASURE_LATENCY -/*!****************************************************************************** - * \brief Create a latency measurement queue object of a given capacity - * - * \param capacity maximum size of queue - * - * \return ni_lat_meas_q_t latency measurement queue structure - * - *******************************************************************************/ -ni_lat_meas_q_t *ni_lat_meas_q_create(unsigned capacity) -{ - ni_lat_meas_q_t *queue = (ni_lat_meas_q_t *)malloc(sizeof(ni_lat_meas_q_t)); - if (!queue) - { - ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for " - "lat_meas-queue queue", NI_ERRNO); - return NULL; - } - queue->capacity = capacity; - queue->front = queue->size = 0; - queue->rear = capacity - 1; - queue->array = (ni_lat_meas_q_entry_t *)malloc( - queue->capacity * sizeof(ni_lat_meas_q_entry_t)); - if (!queue->array) - { - ni_log(NI_LOG_ERROR, "ERROR %d: Failed to allocate memory for " - "lat_meas_queue queue->array", NI_ERRNO); - free(queue); - return NULL; - } - return queue; -} - -/*!****************************************************************************** - * \brief Push an item onto the queue - * - * \param queue pointer to latency queue - * \param item ni_lat_meas_q_entry_t item to push onto the queue - * - * \return void 1 if success, NULL if failed - * - *******************************************************************************/ -void *ni_lat_meas_q_enqueue(ni_lat_meas_q_t *queue, ni_lat_meas_q_entry_t item) -{ - if (queue->size == queue->capacity) - { - return NULL; - } - queue->rear = (queue->rear + 1) % queue->capacity; - queue->array[queue->rear] = item; - queue->size = queue->size + 1; - return (void *)1; -} - -/*!****************************************************************************** - * \brief Pop an item from the queue - * - * \param queue pointer to latency queue - * - * \return void pointer to popped item - * - *******************************************************************************/ -void *ni_lat_meas_q_dequeue(ni_lat_meas_q_t *queue) -{ - ni_lat_meas_q_entry_t *dequeue_item; - if (queue->size == 0) - { - return NULL; - } - dequeue_item = &queue->array[queue->front]; - queue->front = (queue->front + 1) % queue->capacity; - queue->size = queue->size - 1; - return dequeue_item; -} - -/*!****************************************************************************** - * \brief Get a pointer to rear of queue - * - * \param queue pointer to latency queue - * - * \return void pointer to rear of queue - * - *******************************************************************************/ -void *ni_lat_meas_q_rear(ni_lat_meas_q_t *queue) -{ - return queue->size == 0 ? NULL : &queue->array[queue->rear]; -} - -/*!****************************************************************************** - * \brief Get a pointer to front of queue - * - * \param queue pointer to latency queue - * - * \return void pointer to front of queue - * - *******************************************************************************/ -void *ni_lat_meas_q_front(ni_lat_meas_q_t *queue) -{ - return queue->size == 0 ? NULL : &queue->array[queue->front]; -} - -/*!****************************************************************************** - * \brief Add a new entry to latency queue - * - * \param dec_frame_time_q pointer to latency queue - * \param abs_time frame start time for latency comparison - * \param ts_time reference frame timestamp time - * - * \return void 1 if success, NULL if failed - * - *******************************************************************************/ -void *ni_lat_meas_q_add_entry(ni_lat_meas_q_t *dec_frame_time_q, - uint64_t abs_time, int64_t ts_time) -{ - // ni_log(NI_LOG_DEBUG, "ni_lat_meas_q_add_entry abs_time=%lu ts_time=" - // "%ld\n", abs_time, ts_time); - ni_lat_meas_q_entry_t entry = {.abs_timenano = abs_time, - .ts_time = ts_time}; - return ni_lat_meas_q_enqueue(dec_frame_time_q, entry); -} - -/*!****************************************************************************** - * \brief Check latency of a frame referenced by its timestamp - * - * \param dec_frame_time_q pointer to latency queue - * \param abs_time frame end time for latency comparison - * \param ts_time reference frame timestamp time - * - * \return uint64_t value of latency if suceeded, -1 if failed - * - *******************************************************************************/ -uint64_t ni_lat_meas_q_check_latency(ni_lat_meas_q_t *dec_frame_time_q, - uint64_t abs_time, int64_t ts_time) -{ - // ni_log(NI_LOG_DEBUG, "ni_lat_meas_q_check_latency abs_time=%lu ts_time=" - // "%ld\n", abs_time, ts_time); - uint32_t dequeue_count = 0; - ni_lat_meas_q_entry_t *entry = ni_lat_meas_q_front(dec_frame_time_q); - - if (entry == NULL) - { - return -1; - } - - if (entry->ts_time == ts_time) - { - ni_lat_meas_q_dequeue(dec_frame_time_q); - dequeue_count++; - } else - { // queue miss, perhaps frame was not decoded properly or TS was offset - while (entry->ts_time < ts_time) - { - entry = ni_lat_meas_q_dequeue(dec_frame_time_q); - dequeue_count++; - if (entry == NULL) - { - return -1; - } - } - } - ni_log(NI_LOG_DEBUG, "DQ_CNT:%u,QD:%d", dequeue_count, - dec_frame_time_q->size); - - if (entry == NULL) - { // queue overrun - return -1; - } else if (entry->ts_time > ts_time) - { // queue miss, perhaps frame was not enqueued properly or TS was offset - return -1; - } else if (entry->ts_time == ts_time) - { // queue item is perfectly matched, calculate latency - return (abs_time - entry->abs_timenano); - } -} -#endif - /****************************************************************************** * * Ai utils apis @@ -2433,9 +2257,6 @@ static void ni_ai_type_get_range(int32_t type, double *max_range, from = 0.0; to = (double)((1UL << bits) - 1); } - } else - { - // TODO: Add float } if (NULL != max_range) { @@ -3144,3 +2965,56 @@ void ni_copy_hw_descriptors(uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS], src_desc->ui16FrameIdx, src_desc->device_handle, dest_desc->ui16FrameIdx, dest_desc->device_handle); } + +/*!***************************************************************************** + * \brief Get libxcoder API version + * + * \return char pointer to libxcoder API version + ******************************************************************************/ +LIB_API char* ni_get_libxcoder_api_ver(void) +{ + static char* libxcoder_api_ver = LIBXCODER_API_VERSION; + return libxcoder_api_ver; +} + +/*!***************************************************************************** + * \brief Get FW API version libxcoder is compatible with + * + * \return char pointer to FW API version libxcoder is compatible with + ******************************************************************************/ +LIB_API char* ni_get_compat_fw_api_ver(void) +{ + static char compat_fw_api_ver_str[4] = ""; + // init static array one byte at a time to avoid compiler error C2099 + if (!compat_fw_api_ver_str[0]) + { + compat_fw_api_ver_str[0] = \ + NI_XCODER_REVISION[NI_XCODER_REVISION_API_MAJOR_VER_IDX]; + compat_fw_api_ver_str[1] = '.'; + compat_fw_api_ver_str[2] = \ + NI_XCODER_REVISION[NI_XCODER_REVISION_API_MINOR_VER_IDX]; + compat_fw_api_ver_str[3] = 0; + } + return &compat_fw_api_ver_str[0]; +} + +/*!***************************************************************************** + * \brief Get libxcoder SW release version + * + * \return char pointer to libxcoder SW release version + ******************************************************************************/ +LIB_API char* ni_get_libxcoder_release_ver(void) +{ + static char release_ver_str[6] = ""; + // init static array one byte at a time to avoid compiler error C2099 + if (!release_ver_str[0]) + { + release_ver_str[0] = NI_XCODER_REVISION[0]; + release_ver_str[1] = '.'; + release_ver_str[2] = NI_XCODER_REVISION[1]; + release_ver_str[3] = '.'; + release_ver_str[4] = NI_XCODER_REVISION[2]; + release_ver_str[5] = 0; + } + return &release_ver_str[0]; +} diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_util.h b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_util.h index 2a5bf481..549b36f2 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_util.h +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/ni_util.h @@ -36,6 +36,7 @@ #include "ni_device_api.h" #include "ni_log.h" +#include "ni_defs.h" #ifdef __cplusplus extern "C" @@ -213,18 +214,6 @@ LIB_API int ni_insert_emulation_prevent_bytes(uint8_t *buf, int size); ******************************************************************************/ LIB_API int ni_remove_emulation_prevent_bytes(uint8_t *buf, int size); -#ifdef MEASURE_LATENCY -// NI latency measurement queue operations -ni_lat_meas_q_t *ni_lat_meas_q_create(unsigned capacity); - -void *ni_lat_meas_q_add_entry(ni_lat_meas_q_t *dec_frame_time_q, - uint64_t abs_time, int64_t ts_time); - -uint64_t ni_lat_meas_q_check_latency(ni_lat_meas_q_t *dec_frame_time_q, - uint64_t abs_time, int64_t ts_time); - -#endif - /*!***************************************************************************** * \brief Get time for logs with microsecond timestamps * @@ -237,7 +226,6 @@ LIB_API int32_t ni_gettimeofday(struct timeval *p_tp, void *p_tzp); int32_t ni_posix_memalign(void **pp_memptr, size_t alignment, size_t size); uint32_t ni_round_up(uint32_t number_to_round, uint32_t multiple); -uint64_t ni_gettime_ns(void); #define ni_aligned_free(p_memptr) \ { \ @@ -245,7 +233,7 @@ uint64_t ni_gettime_ns(void); p_memptr = NULL; \ } -#ifdef __linux__ +#if __linux__ || __APPLE__ uint32_t ni_get_kernel_max_io_size(const char * p_dev); #endif @@ -283,6 +271,27 @@ LIB_API void ni_calculate_sha256(const uint8_t aui8Data[], LIB_API void ni_copy_hw_descriptors(uint8_t *p_dst[NI_MAX_NUM_DATA_POINTERS], uint8_t *p_src[NI_MAX_NUM_DATA_POINTERS]); +/*!***************************************************************************** + * \brief Get libxcoder API version + * + * \return char pointer to libxcoder API version + ******************************************************************************/ +LIB_API char* ni_get_libxcoder_api_ver(void); + +/*!***************************************************************************** + * \brief Get FW API version libxcoder is compatible with + * + * \return char pointer to FW API version libxcoder is compatible with + ******************************************************************************/ +LIB_API char* ni_get_compat_fw_api_ver(void); + +/*!***************************************************************************** + * \brief Get libxcoder SW release version + * + * \return char pointer to libxcoder SW release version + ******************************************************************************/ +LIB_API char* ni_get_libxcoder_release_ver(void); + /*!****************************************************************************** * \brief initialize a mutex * diff --git a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/test_rsrc_api.c b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/test_rsrc_api.c index afb0065b..0a0d5db6 100644 --- a/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/test_rsrc_api.c +++ b/xcoder/xcoder-quadra/xcoder-quadra-sys/vendor/libxcoder/source/test_rsrc_api.c @@ -210,7 +210,7 @@ void listModuleId(void) { ni_device_info_t *p_device_info = ni_rsrc_get_device_info(k, ptr->xcoders[k][i]); - printf("[%u]. %d (load: %d inst: %d %s.%d)\n", i, + printf("[%u]. %d (load: %d inst: %u %s.%d)\n", i, ptr->xcoders[k][i], p_device_info->load, p_device_info->active_num_inst, p_device_info->dev_name, p_device_info->hw_id); @@ -498,10 +498,12 @@ int main(void) change_log_level(); break; case 'V': - printf("Ver: %s\n" - "Date: %s\n" - "ID: %s\n", - NI_XCODER_REVISION, NI_SW_RELEASE_TIME, NI_SW_RELEASE_ID); + printf("Release ver: %s\n" + "API ver: %s\n" + "Date: %s\n" + "ID: %s\n", + NI_XCODER_REVISION, LIBXCODER_API_VERSION, NI_SW_RELEASE_TIME, + NI_SW_RELEASE_ID); break; case 'l': listOneTypeCoders();