整理代码

This commit is contained in:
蒲爽 2026-09-28 21:33:04 +08:00
commit c7b4e178ec
364 changed files with 59691 additions and 0 deletions

View file

@ -0,0 +1,136 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "AudioEncoder.h"
#include "ResourceManager.h"
#include "Util.h"
#include "util/Math.h"
#include <hi_mpi_audio.h>
extern "C"
{
#include "audio-adp/audio_aac_adp.h"
}
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
AudioEncoder::AudioEncoder(Core::CodecID codecID)
: MPPChannel((uint32_t)HI_ID_AENC, 0, ResourceManager::allocAENCChannelID()),
Core::AudioEncoder(Poco::format("MPP5::AENC#%u(%s)", channelID(), Core::codecIDToString(codecID)), codecID)
{
}
AudioEncoder::~AudioEncoder()
{
ResourceManager::freeAENCChannelID(channelID());
}
void AudioEncoder::initialize()
{
hi_aenc_chn_attr attr;
hi_aenc_attr_aac aac;
switch (getCodecID())
{
case Core::CodecID::AAC:
setFrameSize(1024);
setSampleFormat(Core::SampleFormat::S16P);
attr.value = &aac;
attr.type = HI_PT_AAC;
aac.aac_type = HI_AAC_TYPE_AACLC;
aac.band_width = 0;
aac.transport_type = HI_AAC_TRANSPORT_TYPE_ADTS;
aac.sample_rate = (hi_audio_sample_rate)getSampleRate();
aac.bit_rate = (hi_aac_bps)getBitrate();
aac.bit_width = Util::getBitWidth(getSampleFormat());
aac.snd_mode = Util::getSndMode(getChannelLayout());
break;
default:
throw Poco::BugcheckException(
Poco::format("%s: Not implemented codec-id: %s", name(), Core::codecIDToString(getCodecID())), -EINVAL);
}
attr.buf_size = 30;
attr.point_num_per_frame = getFrameSize();
auto rc = hi_mpi_aenc_create_chn(channelID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Create channel FAIL: %#x", name(), (uint32_t)rc), rc);
_fd = hi_mpi_aenc_get_fd(channelID());
_frame.bit_width = Util::getBitWidth(getSampleFormat());
_frame.snd_mode = Util::getSndMode(getChannelLayout());
}
void AudioEncoder::deinitialize()
{
hi_mpi_aenc_destroy_chn(channelID());
}
Core::Packet::Ptr AudioEncoder::encode()
{
auto pIn = readFrame();
_frame.virt_addr[0] = pIn->data[0].get();
_frame.virt_addr[1] = pIn->data[1].get();
_frame.time_stamp = pIn->timestamp;
_frame.len = pIn->length;
auto rc = hi_mpi_aenc_send_frame(channelID(), &_frame, nullptr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Write frame FAIL: %#x!", name(), (uint32_t)rc), rc);
struct timeval tm = {
.tv_sec = 1,
.tv_usec = 0,
};
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(_fd, &read_fds);
rc = select(_fd + 1, &read_fds, NULL, NULL, &tm);
if (rc < 0)
throw Poco::InvalidAccessException(Poco::format("%s: Read stream FAIL: %s", name(), std::string(strerror(rc))),
rc);
else if (0 == rc)
throw Poco::TimeoutException(Poco::format("%s: Read encoder stream timeout!", name()), rc);
hi_audio_stream stream;
rc = hi_mpi_aenc_get_stream(channelID(), &stream, 1000);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Get encoder stream FAIL: %#x", name(), (uint32_t)rc), rc);
uint8_t* pData = new uint8_t[stream.len];
memcpy(pData, stream.stream, stream.len);
Core::Packet::Ptr pPacket =
new Core::Packet(serialCodeManager().code(), 0, pData, stream.len, stream.time_stamp, stream.time_stamp);
hi_mpi_aenc_release_stream(channelID(), &stream);
return pPacket;
}
void AudioEncoder::onConfigChanged(ParameterNames& names)
{
Core::AudioEncoder::onConfigChanged(names);
}
void AudioEncoder::initModule()
{
hi_mpi_aenc_aac_init();
}
void AudioEncoder::deinitModule()
{
hi_mpi_aenc_aac_deinit();
}
}
}

View file

@ -0,0 +1,43 @@
#ifndef D8737294_8E5E_4514_9AD1_CFD956F0E262
#define D8737294_8E5E_4514_9AD1_CFD956F0E262
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "MPPChannel.h"
#include "../core/AudioEncoder.h"
#include <hi_common_aio.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class AudioEncoder: public MPPChannel, public Core::AudioEncoder
{
public:
AudioEncoder(Core::CodecID codecID);
~AudioEncoder();
protected:
void initialize() override;
void deinitialize() override;
Core::Packet::Ptr encode() override;
void onConfigChanged(ParameterNames& names) override;
private:
int _fd;
hi_audio_frame _frame;
public:
static void initModule();
static void deinitModule();
};
}
}
#endif

View file

@ -0,0 +1,125 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "AudioInput.h"
#include "Util.h"
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* LOCAL FUNCTIONS
*******************************************************************************
*/
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
AudioInput::AudioInput(uint32_t deviceID)
: Core::AbstractAudioInput(Poco::format("MPP5::AI#%u", deviceID)), MPPChannel((uint32_t)HI_ID_AI, deviceID, 0)
{
setSampleRate(48000);
setFrameSize(1024);
setSampleFormat(Core::SampleFormat::S16P);
}
AudioInput::~AudioInput()
{
}
void AudioInput::start()
{
hi_aio_attr attr;
attr.sample_rate = (hi_audio_sample_rate)getSampleRate();
attr.bit_width = Util::getBitWidth(getSampleFormat());
attr.work_mode = HI_AIO_MODE_I2S_SLAVE;
attr.i2s_type = HI_AIO_I2STYPE_EXTERN;
attr.snd_mode = HI_AUDIO_SOUND_MODE_STEREO;
attr.expand_flag = 0;
attr.frame_num = 8;
attr.point_num_per_frame = getFrameSize();
attr.chn_cnt = 2;
attr.clk_share = 0;
int32_t rc = hi_mpi_ai_set_pub_attr(deviceID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: set PUB-ATTR FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
rc = hi_mpi_ai_enable(deviceID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: enable FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_ai_enable_chn(deviceID(), channelID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: enable channel FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
hi_ai_chn_param param;
param.usr_frame_depth = 8;
hi_mpi_ai_set_chn_param(deviceID(), channelID(), &param);
run();
}
void AudioInput::stop()
{
cancel();
hi_mpi_ai_disable_chn(deviceID(), channelID());
hi_mpi_ai_disable(deviceID());
}
void AudioInput::onConfigChanged(ParameterNames& names)
{
if (!started())
return;
auto code = serialCodeManager().code();
if (names.exists(_SampleRate))
serialCodeManager().put(_SampleRate, getSampleRate());
if (names.exists(_FrameSize))
serialCodeManager().put(_FrameSize, getFrameSize());
if (code != serialCodeManager().code())
{
stop();
start();
}
AbstractAudioInput::onConfigChanged(names);
}
Core::Frame::Ptr AudioInput::readFrame()
{
hi_audio_frame frame;
hi_aec_frame aecFrame;
int rc = hi_mpi_ai_get_frame(deviceID(), 0, &frame, &aecFrame, 1000);
if (rc != HI_SUCCESS)
throw Poco::TimeoutException(Poco::format("%s: Get frame error: %u(%#x)!", name(), (uint32_t)rc, (uint32_t)rc));
Core::Frame::Ptr pFrame = nullptr;
if (frame.len > 0)
{
pFrame = new Core::Frame;
pFrame->data[0] = new uint8_t[frame.len];
memcpy(pFrame->data[0], frame.virt_addr[0], frame.len);
pFrame->data[1] = new uint8_t[frame.len];
memcpy(pFrame->data[1], frame.virt_addr[1], frame.len);
pFrame->length = frame.len;
pFrame->timestamp = frame.time_stamp;
}
hi_mpi_ai_release_frame(deviceID(), 0, &frame, &aecFrame);
_traffic++;
return pFrame;
}
}
}

View file

@ -0,0 +1,40 @@
#ifndef C7DEE8B3_9816_4937_B2A6_0591DEF0ED45
#define C7DEE8B3_9816_4937_B2A6_0591DEF0ED45
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "MPPChannel.h"
#include "../../core/AbstractAudioInput.h"
#include "util/Task.h"
#include <hi_common.h>
#include <hi_mpi_audio.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class AudioInput: public Core::AbstractAudioInput, public MPPChannel
{
public:
using Ptr = Poco::AutoPtr<AudioInput>;
public:
AudioInput(uint32_t deviceID);
~AudioInput();
protected:
void start() override;
void stop() override;
void onConfigChanged(ParameterNames& names) override;
Core::Frame::Ptr readFrame() override;
};
}
}
#endif

View file

@ -0,0 +1,122 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "HDMIAudioOutput.h"
#include "Util.h"
#include "util/Math.h"
/*
*******************************************************************************
* CONSTANTS
*******************************************************************************
*/
#define AO_DEV_ID 1
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
HDMIAudioOutput::HDMIAudioOutput(const std::string& arg)
: Core::AudioOutput("MPP5::AudioOutput(" + arg + ")"), MPPChannel((uint32_t)HI_ID_AO, AO_DEV_ID, 0)
{
setSampleRate(48000);
setSampleFormat(Core::SampleFormat::S16P);
setChannelLayout(Core::ChannelLayout::STEREO);
setFrameSize(1024);
}
HDMIAudioOutput::~HDMIAudioOutput()
{
}
void HDMIAudioOutput::initialize()
{
_bitWidth = Util::getBitWidth(getSampleFormat());
_sndMode = Util::getSndMode(getChannelLayout());
hi_aio_attr attr;
attr.sample_rate = (hi_audio_sample_rate)getSampleRate();
attr.bit_width = _bitWidth;
attr.work_mode = HI_AIO_MODE_I2S_MASTER;
attr.i2s_type = HI_AIO_I2STYPE_INNERHDMI;
attr.snd_mode = _sndMode;
attr.expand_flag = 0;
attr.frame_num = 8;
attr.point_num_per_frame = getFrameSize();
attr.chn_cnt = Core::channelLayoutChannels(getChannelLayout());
attr.clk_share = 0;
int rc = hi_mpi_ao_set_pub_attr(deviceID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Configure pub-attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_ao_enable(deviceID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Enable FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_ao_set_volume(deviceID(), getVolumeValue());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Configure volume FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
rc = hi_mpi_ao_enable_chn(deviceID(), channelID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Enable CHM#%u FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc), rc);
}
void HDMIAudioOutput::deinitialize()
{
hi_mpi_ao_disable_chn(deviceID(), channelID());
hi_mpi_ao_disable(deviceID());
}
void HDMIAudioOutput::onConfigChanged(ParameterNames& names)
{
if (!started())
return;
int rc = hi_mpi_ao_set_volume(deviceID(), getVolumeValue());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Configure volume FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
}
void HDMIAudioOutput::writeFrame(Core::Frame::Ptr pFrame)
{
hi_audio_frame frame = {};
frame.bit_width = HI_AUDIO_BIT_WIDTH_16;
frame.len = pFrame->length;
frame.time_stamp = pFrame->timestamp;
frame.snd_mode = HI_AUDIO_SOUND_MODE_MONO;
frame.virt_addr[0] = pFrame->data[0].get();
if (HI_AUDIO_SOUND_MODE_STEREO == _sndMode)
frame.virt_addr[1] = pFrame->data[1].get();
int rc = hi_mpi_ao_send_frame(deviceID(), channelID(), &frame, 100);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Send frame FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
}
int HDMIAudioOutput::getVolumeValue()
{
auto lineMapping = [](int inputMin, int inputMax, int outMin, int outMax, int input) -> int
{ return (input - inputMin) * (outMax - outMin) / (inputMax - inputMin) + outMin; };
int gain = ::Util::Math::clamp(getGain(), -100, 100);
if (gain < 0)
return lineMapping(-100, -1, -121, -1, gain);
return lineMapping(0, 100, 0, 6, gain);
}
}
}

View file

@ -0,0 +1,41 @@
#ifndef CCC7E17D_FF7C_44B5_8DCC_BFCE92AAFC87
#define CCC7E17D_FF7C_44B5_8DCC_BFCE92AAFC87
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "../core/AudioOutput.h"
#include "MPPChannel.h"
#include <hi_mpi_audio.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class HDMIAudioOutput: public Core::AudioOutput, public MPPChannel
{
public:
HDMIAudioOutput(const std::string& arg);
~HDMIAudioOutput();
protected:
void initialize() override;
void deinitialize() override;
void onConfigChanged(ParameterNames& names) override;
void writeFrame(Core::Frame::Ptr pFrame) override;
int getVolumeValue();
private:
hi_audio_bit_width _bitWidth;
hi_audio_snd_mode _sndMode;
};
}
}
#endif

View file

@ -0,0 +1,403 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "HDMIVideoOutput.h"
#include "Logger.h"
#include "util/Math.h"
#include <array>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CONSTANTS
*******************************************************************************
*/
#define VO_DEVICE_ID 0
#define VIDEO_LAYER_ID 0
#define HDMI_ID HI_HDMI_ID_0
/*
*******************************************************************************
* TYPEDEFS
*******************************************************************************
*/
struct TimingDesc
{
std::string desc;
uint32_t width;
uint32_t height;
uint32_t frameRate;
hi_vo_intf_sync intf;
hi_hdmi_video_format format;
};
/*
*******************************************************************************
* LOCAL VARIABLES
*******************************************************************************
*/
static const std::array<TimingDesc, 27> timingDescTable = {{
{"3840x2160P30", 3840, 2160, 30, HI_VO_OUT_3840x2160_30, HI_HDMI_VIDEO_FORMAT_3840X2160P_30},
{"2560x1600P60", 2560, 1600, 60, HI_VO_OUT_2560x1600_60, HI_HDMI_VIDEO_FORMAT_2560x1600_60},
{"2560x1440P60", 2560, 1440, 60, HI_VO_OUT_2560x1440_60, HI_HDMI_VIDEO_FORMAT_2560x1440_60},
{"2560x1440P30", 2560, 1440, 30, HI_VO_OUT_2560x1440_30, HI_HDMI_VIDEO_FORMAT_2560x1440_30},
{"1920x1080P60", 1920, 1080, 60, HI_VO_OUT_1080P60, HI_HDMI_VIDEO_FORMAT_1080P_60},
{"1920x1080I60", 1920, 1080, 60, HI_VO_OUT_1080I60, HI_HDMI_VIDEO_FORMAT_1080i_60},
{"1920x1080P50", 1920, 1080, 50, HI_VO_OUT_1080P50, HI_HDMI_VIDEO_FORMAT_1080P_50},
{"1920x1080I50", 1920, 1080, 50, HI_VO_OUT_1080I50, HI_HDMI_VIDEO_FORMAT_1080i_50},
{"1920x1080P30", 1920, 1080, 30, HI_VO_OUT_1080P30, HI_HDMI_VIDEO_FORMAT_1080P_30},
{"1920x1080P25", 1920, 1080, 25, HI_VO_OUT_1080P25, HI_HDMI_VIDEO_FORMAT_1080P_25},
{"1920x1080P24", 1920, 1080, 24, HI_VO_OUT_1080P24, HI_HDMI_VIDEO_FORMAT_1080P_24},
{"1280x720P60", 1280, 720, 60, HI_VO_OUT_720P60, HI_HDMI_VIDEO_FORMAT_720P_60},
{"1280x720P50", 1280, 720, 50, HI_VO_OUT_720P50, HI_HDMI_VIDEO_FORMAT_720P_50},
{"720x576P50", 720, 576, 50, HI_VO_OUT_576P50, HI_HDMI_VIDEO_FORMAT_576P_50},
{"720x480P50", 720, 480, 60, HI_VO_OUT_480P60, HI_HDMI_VIDEO_FORMAT_480P_60},
{"1920x2160P30", 1920, 2160, 30, HI_VO_OUT_1920x2160_30, HI_HDMI_VIDEO_FORMAT_1920x2160_30},
{"1920x1200P60", 1920, 1200, 60, HI_VO_OUT_1920x1200_60, HI_HDMI_VIDEO_FORMAT_VESA_1920X1200_60},
{"1680x1050P60", 1680, 1050, 60, HI_VO_OUT_1680x1050_60, HI_HDMI_VIDEO_FORMAT_VESA_1680X1050_60},
{"1600x1200P60", 1600, 1200, 60, HI_VO_OUT_1600x1200_60, HI_HDMI_VIDEO_FORMAT_VESA_1600X1200_60},
{"1440x900P60", 1440, 900, 60, HI_VO_OUT_1440x900_60, HI_HDMI_VIDEO_FORMAT_VESA_1440X900_60},
{"1366x768P60", 1366, 768, 60, HI_VO_OUT_1366x768_60, HI_HDMI_VIDEO_FORMAT_VESA_1366X768_60},
{"1280x1024P60", 1280, 1024, 60, HI_VO_OUT_1280x1024_60, HI_HDMI_VIDEO_FORMAT_VESA_1280X1024_60},
{"1280x800P60", 1280, 800, 60, HI_VO_OUT_1280x800_60, HI_HDMI_VIDEO_FORMAT_VESA_1280X800_60},
{"1024x768P60", 1024, 768, 60, HI_VO_OUT_1024x768_60, HI_HDMI_VIDEO_FORMAT_VESA_1024X768_60},
{"800x600P60", 800, 600, 60, HI_VO_OUT_800x600_60, HI_HDMI_VIDEO_FORMAT_VESA_800X600_60},
}};
const TimingDesc& defaultTime = timingDescTable[4];
/*
*******************************************************************************
* LOCAL FUNCTIONS
*******************************************************************************
*/
static const TimingDesc& getTimingDesc(const std::string& desc)
{
for (const auto& t : timingDescTable)
{
if (t.desc == desc)
return t;
}
logger().warning("HDMIVideoOutput: Could NOT found '%s', using %s", desc, defaultTime.desc);
return defaultTime;
}
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
HDMIVideoOutput::HDMIVideoOutput(const std::string& name)
: Core::VideoOutput(name + "(MPP5::HDMI)"), MPPChannel((uint32_t)HI_ID_VO, VO_DEVICE_ID, 0)
{
hi_mpi_hdmi_init();
stopOutput();
}
HDMIVideoOutput::~HDMIVideoOutput()
{
stopOutput();
hi_mpi_hdmi_deinit();
}
void HDMIVideoOutput::start()
{
hi_mpi_hdmi_open(HDMI_ID);
onHotPlug();
}
void HDMIVideoOutput::stop()
{
onNoPlug();
hi_mpi_hdmi_close(HDMI_ID);
}
void HDMIVideoOutput::onConfigChanged(ParameterNames& names)
{
if (!getHDMIStarted())
return;
if (names.exists(_Timing))
{
try
{
stopOutput();
startOutput();
}
catch (Poco::Exception& e)
{
logger().error(e.displayText());
stopOutput();
}
}
if (names.exists(_Mode))
{
hi_mpi_hdmi_stop(HDMI_ID);
hi_hdmi_attr attr;
int rc = hi_mpi_hdmi_get_attr(HDMI_ID, &attr);
if (rc != HI_SUCCESS)
logger().error("%s: get HDMI attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc);
attr.hdmi_en = getUsingHDMIMode();
rc = hi_mpi_hdmi_set_attr(HDMI_ID, &attr);
if (rc != HI_SUCCESS)
logger().error("%s: set HDMI attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc);
rc = hi_mpi_hdmi_start(HDMI_ID);
if (rc != HI_SUCCESS)
logger().error("%s: start HDMI FAIL: %d(%#x)", name(), rc, (uint32_t)rc);
}
if (names.exists(_Luma) || names.exists(_Contrast) || names.exists(_Hue) || names.exists(_Saturation) ||
names.exists(_ColorType))
{
hi_vo_hdmi_param param;
if (names.exists(_ColorType))
hi_mpi_hdmi_stop(HDMI_ID);
hi_mpi_vo_get_hdmi_param(deviceID(), &param);
if (names.exists(_ColorType))
param.csc.csc_matrix = getCSCMatrix();
param.csc.luma = ::Util::Math::clamp(getLuma(), 0, 100);
param.csc.contrast = ::Util::Math::clamp(getContrast(), 0, 100);
param.csc.hue = ::Util::Math::clamp(getHue(), 0, 100);
param.csc.saturation = ::Util::Math::clamp(getSaturation(), 0, 100);
hi_mpi_vo_set_hdmi_param(deviceID(), &param);
if (names.exists(_ColorType))
hi_mpi_hdmi_start(HDMI_ID);
}
if (names.exists(_Mirror))
hi_mpi_vo_set_chn_mirror(VIDEO_LAYER_ID, channelID(), getMirror() ? HI_VO_MIRROR_HOR : HI_VO_MIRROR_NONE);
if (names.exists(_Rotation))
hi_mpi_vo_set_chn_rotation(VIDEO_LAYER_ID, channelID(), getRotationValue());
}
void HDMIVideoOutput::onLink(Core::Component::Ptr pPrevious)
{
MPPChannel::doLink(pPrevious);
}
void HDMIVideoOutput::onUnlink(Core::Component::Ptr pPrevious)
{
MPPChannel::doUnlink(pPrevious);
}
void HDMIVideoOutput::onHotPlug()
{
logger().debug("%s: HDMI HOTPLUG", name());
setPluged(true);
try
{
startOutput();
}
catch (Poco::Exception& e)
{
logger().error(e.displayText());
}
}
void HDMIVideoOutput::onNoPlug()
{
logger().debug("%s: HDMI NOPLUG", name());
setPluged(false);
stopOutput();
}
void HDMIVideoOutput::onEDIDFail()
{
logger().debug("EDID FAIL");
}
void HDMIVideoOutput::startOutput()
{
const TimingDesc& timing = getTimingDesc(getTiming());
hi_vo_pub_attr attr;
attr.bg_color = 0x000000;
attr.intf_type = HI_VO_INTF_HDMI;
attr.intf_sync = timing.intf;
int rc = hi_mpi_vo_set_pub_attr(deviceID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: set-pub FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_vo_enable(deviceID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: enable VO FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
{
hi_vo_video_layer_attr attr;
attr.display_rect.x = 0;
attr.display_rect.y = 0;
attr.display_rect.width = timing.width;
attr.display_rect.height = timing.height;
attr.img_size.width = timing.width;
attr.img_size.height = timing.height;
attr.display_frame_rate = timing.frameRate;
attr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422;
attr.double_frame_en = HI_FALSE;
attr.cluster_mode_en = HI_FALSE;
attr.dst_dynamic_range = HI_DYNAMIC_RANGE_SDR8;
attr.display_buf_len = 4;
attr.partition_mode = HI_VO_PARTITION_MODE_SINGLE;
attr.compress_mode = HI_COMPRESS_MODE_NONE;
rc = hi_mpi_vo_set_video_layer_attr(VIDEO_LAYER_ID, &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: set video layer attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_vo_enable_video_layer(VIDEO_LAYER_ID);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: enable video layer FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
}
{
hi_vo_chn_attr attr;
attr.priority = 0;
attr.rect.x = 0;
attr.rect.y = 0;
attr.rect.width = timing.width;
attr.rect.height = timing.height;
attr.deflicker_en = HI_FALSE;
rc = hi_mpi_vo_set_chn_attr(VIDEO_LAYER_ID, channelID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: set chn attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
rc = hi_mpi_vo_enable_chn(VIDEO_LAYER_ID, channelID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: enable FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
hi_mpi_vo_set_chn_mirror(VIDEO_LAYER_ID, channelID(), getMirror() ? HI_VO_MIRROR_HOR : HI_VO_MIRROR_NONE);
hi_mpi_vo_set_chn_rotation(VIDEO_LAYER_ID, channelID(), getRotationValue());
}
{
hi_hdmi_attr attr;
rc = hi_mpi_hdmi_get_attr(HDMI_ID, &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: get HDMI attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
attr.hdmi_en = getUsingHDMIMode();
attr.video_format = timing.format;
attr.deep_color_mode = HI_HDMI_DEEP_COLOR_24BIT;
attr.audio_en = attr.hdmi_en ? HI_TRUE : HI_FALSE;
attr.sample_rate = HI_HDMI_SAMPLE_RATE_48K;
attr.bit_depth = HI_HDMI_BIT_DEPTH_16;
attr.auth_mode_en = HI_TRUE;
attr.deep_color_adapt_en = HI_TRUE;
rc = hi_mpi_hdmi_set_attr(HDMI_ID, &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: set HDMI attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
hi_vo_hdmi_param param;
hi_mpi_vo_get_hdmi_param(deviceID(), &param);
param.csc.csc_matrix = getCSCMatrix();
param.csc.luma = ::Util::Math::clamp(getLuma(), 0, 100);
param.csc.contrast = ::Util::Math::clamp(getContrast(), 0, 100);
param.csc.hue = ::Util::Math::clamp(getHue(), 0, 100);
param.csc.saturation = ::Util::Math::clamp(getSaturation(), 0, 100);
hi_mpi_vo_set_hdmi_param(deviceID(), &param);
rc = hi_mpi_hdmi_start(HDMI_ID);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: start HDMI FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
}
setHDMIStarted(true);
}
void HDMIVideoOutput::stopOutput()
{
hi_mpi_hdmi_stop(HDMI_ID);
hi_mpi_vo_disable_chn(VIDEO_LAYER_ID, channelID());
hi_mpi_vo_disable_video_layer(VIDEO_LAYER_ID);
hi_mpi_vo_disable(VO_DEVICE_ID);
setHDMIStarted(false);
}
hi_bool HDMIVideoOutput::getUsingHDMIMode()
{
return getMode() == Core::VideoOutput::Mode::HDMI ? HI_TRUE : HI_FALSE;
}
hi_vo_csc_matrix HDMIVideoOutput::getCSCMatrix()
{
if (getMode() == Core::VideoOutput::Mode::DVI || getColorType() == Core::VideoOutput::ColorType::RGB)
return HI_VO_CSC_MATRIX_BT709LIMIT_TO_RGBFULL;
return HI_VO_CSC_MATRIX_BT709LIMIT_TO_BT709FULL;
}
hi_rotation HDMIVideoOutput::getRotationValue()
{
switch (getRotation())
{
default:
case 0:
return HI_ROTATION_0;
case 90:
return HI_ROTATION_90;
case 180:
return HI_ROTATION_180;
case 270:
return HI_ROTATION_270;
}
}
void HDMIVideoOutput::eventCallback(hi_hdmi_event_type event, td_void* p)
{
switch (event)
{
case HI_HDMI_EVENT_HOTPLUG:
static_cast<HDMIVideoOutput*>(p)->onHotPlug();
break;
case HI_HDMI_EVENT_NO_PLUG:
static_cast<HDMIVideoOutput*>(p)->onNoPlug();
break;
case HI_HDMI_EVENT_EDID_FAIL:
static_cast<HDMIVideoOutput*>(p)->onEDIDFail();
break;
default:
break;
}
}
}
}

View file

@ -0,0 +1,53 @@
#ifndef AB83CB54_F14E_4C1B_B2AE_6AF47090444C
#define AB83CB54_F14E_4C1B_B2AE_6AF47090444C
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "../../core/VideoOutput.h"
#include "MPPChannel.h"
#include <hi_mpi_hdmi.h>
#include <hi_mpi_vo.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class HDMIVideoOutput: public Core::VideoOutput, MPPChannel
{
public:
HDMIVideoOutput(const std::string& name);
~HDMIVideoOutput();
protected:
void start() override;
void stop() override;
void onConfigChanged(ParameterNames& names) override;
void onLink(Core::Component::Ptr pPrevious) override;
void onUnlink(Core::Component::Ptr pPrevious) override;
void onHotPlug();
void onNoPlug();
void onEDIDFail();
void startOutput();
void stopOutput();
hi_bool getUsingHDMIMode();
hi_vo_csc_matrix getCSCMatrix();
hi_rotation getRotationValue();
PROPERTY_DECLARE(Pluged, bool, false, protected, protected)
PROPERTY_DECLARE(HDMIStarted, bool, false, protected, protected)
static void eventCallback(hi_hdmi_event_type event, td_void* p);
};
}
}
#endif

498
video/hisi/mpp5/IVE.cpp Normal file
View file

@ -0,0 +1,498 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "IVE.h"
#include "Logger.h"
#include "util/Math.h"
#include <hi_mpi_sys.h>
#include <hi_mpi_vb.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CONSTANTS
*******************************************************************************
*/
#define HI__IVE_IMAGE_CHN_ONE 1
#define HI__IVE_IMAGE_CHN_TWO 2
#define HI__IVE_IMAGE_CHN_THREE 3
#define HI__IVE_IMAGE_CHN_FOUR 4
#define HI__IVE_MAX_CCL_REGION_NUM 254
#define HI__IVE_DIV_TWO 2
#define HI_SAMPLE_POINT_IDX_ZERO 0
#define HI_SAMPLE_POINT_IDX_ONE 1
#define HI_SAMPLE_POINT_IDX_TWO 2
#define HI_SAMPLE_POINT_IDX_THREE 3
#define HI_SAMPLE_RESIZE_MAX_TILE_METRIC_8BIT 2032
#define HI_SAMPLE_RESIZE_MAX_TILE_METRIC_16BIT 1016
#define HI_SAMPLE_RESIZE_TILE_ADJUST 2
#define HI_SAMPLE_RESIZE_ASSIST_UNIT_SIZE 48
#define HI_SAMPLE_RESIZE_CBCR_NUM_2 2
#define HI_SAMPLE_RESIZE_CBCR_NUM_3 3
#define HI_IVE_ALIGN 16
/*
*******************************************************************************
* MACROS
*******************************************************************************
*/
#define _convert_ptr_to_addr(type, addr) ((type)(hi_uintptr_t)(addr))
#define _convert_addr_to_ptr(type, addr) ((type*)(hi_uintptr_t)(addr))
/*
*******************************************************************************
* TYPEDEFS
*******************************************************************************
*/
struct _img_loop_info
{
uint32_t ele_size;
uint32_t loop_c;
uint32_t loop_h[HI_SVP_IMG_ADDR_NUM];
};
typedef struct _img_loop_info _img_loop_info_t;
/*
*******************************************************************************
* LOCAL FUNCTIONS
*******************************************************************************
*/
static void _ive_get_loop_info(const hi_svp_img* img, _img_loop_info_t* loop_info)
{
loop_info->ele_size = 1;
loop_info->loop_c = 1;
loop_info->loop_h[0] = img->height;
switch (img->type)
{
case HI_SVP_IMG_TYPE_U8C1:
case HI_SVP_IMG_TYPE_S8C1:
break;
case HI_SVP_IMG_TYPE_YUV420SP:
loop_info->ele_size = 1;
loop_info->loop_c = HI__IVE_IMAGE_CHN_TWO;
loop_info->loop_h[1] = img->height / HI__IVE_DIV_TWO;
break;
case HI_SVP_IMG_TYPE_YUV422SP:
loop_info->loop_c = HI__IVE_IMAGE_CHN_TWO;
loop_info->loop_h[1] = img->height;
break;
case HI_SVP_IMG_TYPE_U8C3_PACKAGE:
loop_info->ele_size = (uint32_t)(sizeof(uint8_t) + sizeof(uint16_t));
break;
case HI_SVP_IMG_TYPE_U8C3_PLANAR:
loop_info->loop_c = HI__IVE_IMAGE_CHN_THREE;
loop_info->loop_h[1] = img->height;
loop_info->loop_h[HI__IVE_IMAGE_CHN_TWO] = img->height;
break;
case HI_SVP_IMG_TYPE_S16C1:
case HI_SVP_IMG_TYPE_U16C1:
loop_info->ele_size = (uint32_t)sizeof(uint16_t);
break;
case HI_SVP_IMG_TYPE_U32C1:
case HI_SVP_IMG_TYPE_S32C1:
loop_info->ele_size = (uint32_t)sizeof(uint32_t);
break;
case HI_SVP_IMG_TYPE_S64C1:
case HI_SVP_IMG_TYPE_U64C1:
loop_info->ele_size = (uint32_t)sizeof(uint64_t);
break;
default:
break;
}
}
#define HI_SAMPLE_ADDR_IDX_ZERO 0
#define HI_SAMPLE_ADDR_IDX_ONE 1
#define HI_SAMPLE_ADDR_IDX_TWO 2
#define HI_MAX_LOOP_IMG_H 3
static int _ive_set_image_addr(hi_svp_img* img, const _img_loop_info_t* loop_info, hi_bool is_mmz_cached)
{
uint32_t c;
int size = 0;
int rc;
hi_void* virt_addr = HI_NULL;
for (c = 0; (c < loop_info->loop_c) && (c < HI_MAX_LOOP_IMG_H) && (c < HI_SVP_IMG_STRIDE_NUM); c++)
{
size += img->stride[0] * loop_info->loop_h[c] * loop_info->ele_size;
img->stride[c] = img->stride[0];
}
if (is_mmz_cached)
{
rc = hi_mpi_sys_mmz_alloc_cached((hi_phys_addr_t*)&img->phys_addr[0], (hi_void**)&virt_addr, HI_NULL, HI_NULL,
size);
}
else
{
rc = hi_mpi_sys_mmz_alloc((hi_phys_addr_t*)&img->phys_addr[0], (hi_void**)&virt_addr, HI_NULL, HI_NULL, size);
}
if (rc != HI_SUCCESS)
{
logger().error("IVE: mmz malloc FAIL: %d(%08X)", rc, (uint32_t)rc);
return rc;
}
img->virt_addr[HI_SAMPLE_ADDR_IDX_ZERO] = _convert_ptr_to_addr(uint64_t, virt_addr);
if (img->type != HI_SVP_IMG_TYPE_U8C3_PACKAGE)
{
for (c = 1; (c < loop_info->loop_c) && (c < HI_MAX_LOOP_IMG_H) && (c < HI_SVP_IMG_STRIDE_NUM); c++)
{
img->phys_addr[c] = img->phys_addr[c - 1] + img->stride[c - 1] * img->height;
img->virt_addr[c] = img->virt_addr[c - 1] + img->stride[c - 1] * img->height;
}
}
else
{
img->virt_addr[HI_SAMPLE_ADDR_IDX_ONE] = img->virt_addr[HI_SAMPLE_ADDR_IDX_ZERO] + 1;
img->virt_addr[HI_SAMPLE_ADDR_IDX_TWO] = img->virt_addr[HI_SAMPLE_ADDR_IDX_ONE] + 1;
img->phys_addr[HI_SAMPLE_ADDR_IDX_ONE] = img->phys_addr[HI_SAMPLE_ADDR_IDX_ZERO] + 1;
img->phys_addr[HI_SAMPLE_ADDR_IDX_TWO] = img->phys_addr[HI_SAMPLE_ADDR_IDX_ONE] + 1;
}
return size;
}
static int _ive_img_init(hi_svp_img* img, hi_svp_img_type type, uint32_t width, uint32_t height)
{
int rc = 0;
_img_loop_info_t loop_info;
img->type = type;
img->width = width;
img->height = height;
img->stride[0] = Util::Math::alignup(width, HI_IVE_ALIGN);
switch (type)
{
case HI_SVP_IMG_TYPE_U8C1:
case HI_SVP_IMG_TYPE_S8C1:
case HI_SVP_IMG_TYPE_YUV420SP:
case HI_SVP_IMG_TYPE_YUV422SP:
case HI_SVP_IMG_TYPE_S16C1:
case HI_SVP_IMG_TYPE_U16C1:
case HI_SVP_IMG_TYPE_U8C3_PACKAGE:
case HI_SVP_IMG_TYPE_S32C1:
case HI_SVP_IMG_TYPE_U32C1:
case HI_SVP_IMG_TYPE_S64C1:
case HI_SVP_IMG_TYPE_U64C1:
_ive_get_loop_info(img, &loop_info);
rc = _ive_set_image_addr(img, &loop_info, HI_FALSE);
break;
case HI_SVP_IMG_TYPE_YUV420P:
break;
case HI_SVP_IMG_TYPE_YUV422P:
break;
case HI_SVP_IMG_TYPE_S8C2_PACKAGE:
break;
case HI_SVP_IMG_TYPE_S8C2_PLANAR:
break;
case HI_SVP_IMG_TYPE_U8C3_PLANAR:
break;
default:
break;
}
return rc;
}
static uint32_t _ive_resize_get_tile_metric(uint32_t src_metric, uint32_t dst_metric, hi_svp_img_type img_type)
{
int tmp_metric = HI_SAMPLE_RESIZE_MAX_TILE_METRIC_8BIT;
uint32_t src_tile_num, scale, dst_tmp_tile, src_tmp_tile, tile_remainder;
switch (img_type)
{
case HI_SVP_IMG_TYPE_YUV420SP:
case HI_SVP_IMG_TYPE_YUV422SP:
case HI_SVP_IMG_TYPE_U8C3_PLANAR:
case HI_SVP_IMG_TYPE_U8C1:
case HI_SVP_IMG_TYPE_S8C1:
tmp_metric = HI_SAMPLE_RESIZE_MAX_TILE_METRIC_8BIT;
break;
case HI_SVP_IMG_TYPE_U16C1:
case HI_SVP_IMG_TYPE_S16C1:
tmp_metric = HI_SAMPLE_RESIZE_MAX_TILE_METRIC_16BIT;
break;
default:
break;
}
scale = (src_metric / dst_metric) + ((src_metric % dst_metric == 0) ? 0 : 1);
if (dst_metric < src_metric)
{
src_tile_num = (src_metric / tmp_metric) + ((src_metric % tmp_metric == 0) ? 0 : 1);
dst_tmp_tile = dst_metric / src_tile_num;
src_tmp_tile = src_metric / src_tile_num + ((src_metric % src_tile_num == 0) ? 0 : 1);
tile_remainder = (tmp_metric - src_tmp_tile) / scale;
tmp_metric = (dst_tmp_tile + tile_remainder) & ~0x1;
if (tile_remainder == 0)
{
tmp_metric -= HI_SAMPLE_RESIZE_TILE_ADJUST;
}
}
else if (dst_metric == src_metric || scale == 1)
{
tmp_metric -= HI_SAMPLE_RESIZE_TILE_ADJUST;
}
return (uint32_t)tmp_metric;
}
static uint32_t _ive_resize_get_tile_num(uint32_t width, uint32_t height, uint32_t tile_w, uint32_t tile_h)
{
uint32_t x_num, y_num;
if ((tile_w == 0) || (tile_h == 0))
return 0;
x_num = (width / tile_w) + ((width % tile_w) == 0 ? 0 : 1);
y_num = (height / tile_h) + ((height % tile_h) == 0 ? 0 : 1);
return (x_num * y_num);
}
#define HI_SAMPLE_RESIZE_CBCR_NUM_2 2
static uint32_t _ive_resize_get_yuv420sp_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t j, tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_YUV420SP);
for (j = 0; j < HI_SAMPLE_RESIZE_CBCR_NUM_2; j++)
{
tile_height = _ive_resize_get_tile_metric(src_height >> j, dst_height >> j, HI_SVP_IMG_TYPE_YUV420SP);
num += _ive_resize_get_tile_num(dst_width, dst_height >> j, tile_width, tile_height);
}
return num;
}
static uint32_t _ive_resize_get_yuv422sp_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t j, tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_YUV422SP);
tile_height = _ive_resize_get_tile_metric(src_height, dst_height, HI_SVP_IMG_TYPE_YUV422SP);
for (j = 0; j < HI_SAMPLE_RESIZE_CBCR_NUM_2; j++)
num += _ive_resize_get_tile_num(dst_width, dst_height, tile_width, tile_height);
return num;
}
static uint32_t _ive_resize_get_u8c3_planar_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t j, tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_U8C3_PLANAR);
tile_height = _ive_resize_get_tile_metric(src_height, dst_height, HI_SVP_IMG_TYPE_U8C3_PLANAR);
for (j = 0; j < HI_SAMPLE_RESIZE_CBCR_NUM_3; j++)
num += _ive_resize_get_tile_num(dst_width, dst_height, tile_width, tile_height);
return num;
}
static uint32_t _ive_resize_get_u8c1_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_U8C1);
tile_height = _ive_resize_get_tile_metric(src_height, dst_height, HI_SVP_IMG_TYPE_U8C1);
num = _ive_resize_get_tile_num(dst_width, dst_height, tile_width, tile_height);
return num;
}
static uint32_t _ive_resize_get_u16c1_tile_num(uint32_t src_width, uint32_t dst_width, uint32_t src_height,
uint32_t dst_height)
{
uint32_t tile_width, tile_height;
uint32_t num = 0;
tile_width = _ive_resize_get_tile_metric(src_width, dst_width, HI_SVP_IMG_TYPE_U16C1);
tile_height = _ive_resize_get_tile_metric(src_height, dst_height, HI_SVP_IMG_TYPE_U16C1);
num = _ive_resize_get_tile_num(dst_width, dst_height, tile_width, tile_height);
return num;
}
static int _ive_resize_get_assist_buf_size(const hi_svp_src_img src[], const hi_svp_dst_img dst[], int count)
{
int i;
int num = 0;
for (i = 0; i < count; i++)
{
switch (src[i].type)
{
case HI_SVP_IMG_TYPE_YUV420SP:
num += _ive_resize_get_yuv420sp_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
case HI_SVP_IMG_TYPE_YUV422SP:
num += _ive_resize_get_yuv422sp_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
case HI_SVP_IMG_TYPE_U8C3_PLANAR:
num += _ive_resize_get_u8c3_planar_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
case HI_SVP_IMG_TYPE_U8C1:
case HI_SVP_IMG_TYPE_S8C1:
num += _ive_resize_get_u8c1_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
case HI_SVP_IMG_TYPE_U16C1:
case HI_SVP_IMG_TYPE_S16C1:
num += _ive_resize_get_u16c1_tile_num(src[i].width, dst[i].width, src[i].height, dst[i].height);
break;
default:
break;
}
}
return num * HI_SAMPLE_RESIZE_ASSIST_UNIT_SIZE;
}
static int _ive_mem_info_init(hi_svp_mem_info* mem_info, hi_u32 size)
{
int rc = HI_ERR_IVE_NULL_PTR;
hi_void* virt_addr = HI_NULL;
mem_info->size = size;
rc = hi_mpi_sys_mmz_alloc((hi_phys_addr_t*)&mem_info->phys_addr, (hi_void**)&virt_addr, HI_NULL, HI_NULL, size);
if (rc != HI_SUCCESS)
return rc;
mem_info->virt_addr = _convert_ptr_to_addr(uint64_t, virt_addr);
return rc;
}
static int _ive_img_load(hi_svp_img* img, uint8_t* pData)
{
uint8_t* ptr_tmp = HI_NULL;
uint16_t c, h;
int rc = 0;
_img_loop_info_t loop_info = {0};
int index = 0;
_ive_get_loop_info(img, &loop_info);
for (c = 0; (c < loop_info.loop_c) && (c < HI_SVP_IMG_STRIDE_NUM) && (c < HI_SVP_IMG_ADDR_NUM); c++)
{
ptr_tmp = _convert_addr_to_ptr(uint8_t, img->virt_addr[c]);
if (!ptr_tmp)
{
rc = HI_ERR_IVE_BAD_ADDR;
goto exit;
}
for (h = 0; h < loop_info.loop_h[c]; h++)
{
int bytes = img->width * loop_info.ele_size;
memcpy(ptr_tmp, &pData[index], bytes);
index += bytes;
ptr_tmp += img->stride[c] * loop_info.ele_size;
}
}
exit:
return rc;
}
static int _ive_img_store(hi_svp_img* img, uint8_t* pBuffer)
{
uint16_t c, h;
uint8_t* ptr_tmp = HI_NULL;
int rc = 0;
_img_loop_info_t loop_info = {0};
int index = 0;
if (img->phys_addr == 0 || img->virt_addr == 0)
return HI_ERR_BAD_ADDR;
_ive_get_loop_info(img, &loop_info);
for (c = 0; (c < loop_info.loop_c) && (c < HI_SVP_IMG_STRIDE_NUM) && (c < HI_SVP_IMG_ADDR_NUM); c++)
{
ptr_tmp = _convert_addr_to_ptr(uint8_t, img->virt_addr[c]);
if (!ptr_tmp)
{
rc = HI_ERR_IVE_BAD_ADDR;
goto exit;
}
for (h = 0; h < loop_info.loop_h[c]; h++)
{
int bytes = img->width * loop_info.ele_size;
memcpy(&pBuffer[index], ptr_tmp, bytes);
index += bytes;
ptr_tmp += img->stride[c] * loop_info.ele_size;
}
}
exit:
return rc;
}
#define _mmz_free(phys, virt) \
do \
{ \
if (((phys) != 0) && ((virt) != 0)) \
{ \
hi_mpi_sys_mmz_free((hi_phys_addr_t)(phys), (hi_void*)(hi_uintptr_t)(virt)); \
(phys) = 0; \
(virt) = 0; \
} \
} while (0)
static void _ive_img_free(hi_svp_img* img)
{
_mmz_free(img->phys_addr[0], img->virt_addr[0]);
}
static void _ive_mem_info_free(hi_svp_mem_info* info)
{
_mmz_free(info->phys_addr, info->virt_addr);
}
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
VideoFrame::Ptr MPP5::IVE::resize(VideoFrame::Ptr from, uint32_t width, uint32_t height)
{
return VideoFrame::Ptr();
}
}
}

27
video/hisi/mpp5/IVE.h Normal file
View file

@ -0,0 +1,27 @@
#ifndef F479D816_531D_4084_A289_1B5C5A2A6CE7
#define F479D816_531D_4084_A289_1B5C5A2A6CE7
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "VideoFrame.h"
#include <hi_mpi_ive.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class IVE
{
public:
VideoFrame::Ptr resize(VideoFrame::Ptr from, uint32_t width, uint32_t height);
};
}
}
#endif

View file

@ -0,0 +1,135 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "MPPChannel.h"
#include "Logger.h"
#include <hi_common.h>
#include <hi_mpi_sys.h>
#include <Poco/Format.h>
/*
*******************************************************************************
* MACROS
*******************************************************************************
*/
#define HI_MPP_CHN_DECLARE(name, ref) \
hi_mpp_chn name \
{ \
(hi_mod_id)(ref).moduleID(), (hi_s32)(ref).deviceID(), (hi_s32)(ref).channelID(), \
}
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
static const char* moduleNames[] = {
"CMPI", "VB", "SYS",
"RGN", "CHNL", "VDEC",
"AVS", "VPSS", "VENC",
"SVP", "H264E", "JPEGE",
"UNKNOWN", "H265E", "JPEGD",
"VO", "VI", "DIS",
"VALG", "RC", "AIO",
"AI", "AO", "AENC",
"ADEC", "VPU", "PCIV",
"PCIVFMW", "ISP", "IVE",
"USER", "UNKNOWN", "UNKNOWN",
"PROC", "LOG", "VFMW",
"UNKNOWN", "GDC", "PHOTO",
"FB", "HDMI", "VOIE",
"TDE", "HDR", "PRORES",
"VGS", "UNKNOWN", "FD",
"OD", "UNKNOWN", "LPR",
"SVP_NNIE", "SVP_DSP", "DPU_RECT",
"DPU_MATCH", "MOTIONSENSOR", "MOTIONFUSION",
"GYRODIS", "PM", "SVP_ALG",
"IVP", "MCF", "SVP_MAU",
"VDA", "VPP", "KCF",
"PQP", "NPUDEV", "AICPU",
"NPUDFX", "TSFW", "CIPHER",
"KLAD", "KEYSLOT", "OTP",
"VDEC_ADAPT", "DCC", "VDEC_SERVER",
"VFMW_MDC", "VB_LOG", "MCF_CALIBRATION",
"SVP_NPU", "HNR", "SNAP",
"LOG_MDC", "UVC", "FISHEYE_CALIBRATION",
};
MPPChannel::MPPChannel(uint32_t moduleID, uint32_t deviceID, uint32_t channelID)
: _moduleID(moduleID), _deviceID(deviceID), _channelID(channelID)
{
}
std::string MPPChannel::toString() const
{
const char* name = "UNKNOWN";
if (moduleID() < HI_ID_FISHEYE_CALIBRATION)
name = moduleNames[moduleID()];
return Poco::format("%s(%u:%u)", std::string(name), deviceID(), channelID());
}
void MPPChannel::bind(const MPPChannel& next)
{
HI_MPP_CHN_DECLARE(from, *this);
HI_MPP_CHN_DECLARE(to, next);
int rc = hi_mpi_sys_bind(&from, &to);
if (rc < 0)
logger().error("Bind: %s -> %s: %#x", this->toString(), next.toString(), (uint32_t)rc);
else
logger().debug("Bind: %s -> %s SUCCESS", this->toString(), next.toString());
}
void MPPChannel::unbind(const MPPChannel& next)
{
HI_MPP_CHN_DECLARE(from, *this);
HI_MPP_CHN_DECLARE(to, next);
int rc = hi_mpi_sys_unbind(&from, &to);
if (rc < 0)
logger().error("Unbind: %s -> %s: %#x", this->toString(), next.toString(), (uint32_t)rc);
else
logger().debug("Unbind: %s -> %s SUCCESS", this->toString(), next.toString());
}
void MPPChannel::doLink(Core::Component::Ptr pPrevious)
{
auto pFrom = dynamic_cast<MPPChannel*>(pPrevious.get());
if (pFrom)
{
pFrom->bind(*this);
return;
}
logger().error("MPPChannel: dolink FAIL: %s is not 'MPPChannel'", pPrevious->name());
}
void MPPChannel::doUnlink(Core::Component::Ptr pPrevious)
{
auto pFrom = dynamic_cast<MPPChannel*>(pPrevious.get());
if (pFrom)
{
pFrom->unbind(*this);
return;
}
logger().error("MPPChannel: doUnlink FAIL: %s is not 'MPPChannel'", pPrevious->name());
}
hi_mpp_chn MPPChannel::raw()
{
return hi_mpp_chn{
(hi_mod_id)moduleID(),
(hi_s32)deviceID(),
(hi_s32)channelID(),
};
}
}
}

View file

@ -0,0 +1,70 @@
#ifndef EEDA2366_7E77_49AC_8716_526A3A63113F
#define EEDA2366_7E77_49AC_8716_526A3A63113F
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include <string>
#include "../core/Component.h"
#include <hi_mpi_sys.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class MPPChannel
{
public:
MPPChannel(uint32_t moduleID, uint32_t deviceID, uint32_t channelID);
public:
bool operator<(const MPPChannel& other) const;
uint32_t moduleID() const;
uint32_t deviceID() const;
uint32_t channelID() const;
std::string toString() const;
virtual void bind(const MPPChannel& next);
virtual void unbind(const MPPChannel& next);
void doLink(Core::Component::Ptr pPrevious);
void doUnlink(Core::Component::Ptr pPrevious);
hi_mpp_chn raw();
private:
uint32_t _moduleID;
uint32_t _deviceID;
uint32_t _channelID;
};
inline bool MPPChannel::operator<(const MPPChannel& other) const
{
return moduleID() < other.moduleID() || deviceID() < other.deviceID() || channelID() < other.channelID();
}
inline uint32_t MPPChannel::moduleID() const
{
return _moduleID;
}
inline uint32_t MPPChannel::deviceID() const
{
return _deviceID;
}
inline uint32_t MPPChannel::channelID() const
{
return _channelID;
}
}
}
#endif

View file

@ -0,0 +1,18 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "Notifications.h"
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
}
}

View file

@ -0,0 +1,24 @@
#ifndef DF1404E9_430D_4F31_989F_4C5EB4BE26D4
#define DF1404E9_430D_4F31_989F_4C5EB4BE26D4
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "../../core/Component.h"
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class VideoDecoderResetNotification: public Core::Component::Notification
{
};
}
}
#endif

View file

@ -0,0 +1,75 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "ResourceManager.h"
#include <hi_mpi_vpss.h>
#include <hi_mpi_venc.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
Util::HandlesManager<uint32_t> ResourceManager::_vpssGroupIDManager(HI_VPSS_MAX_GRP_NUM);
Util::HandlesManager<uint32_t> ResourceManager::_vencChannelIDManager(HI_VENC_MAX_CHN_NUM);
Util::HandlesManager<uint32_t> ResourceManager::_vdecChannelIDManager(HI_VDEC_MAX_CHN_NUM);
Util::HandlesManager<uint32_t> ResourceManager::_aencChannelIDManager(HI_AENC_MAX_CHN_NUM);
Util::HandlesManager<uint32_t> ResourceManager::_rgnHandleManager(HI_RGN_HANDLE_MAX);
uint32_t ResourceManager::allocVPSSGroupID()
{
return _vpssGroupIDManager.allocHandle();
}
void ResourceManager::freeVPSSGroupID(uint32_t id)
{
_vpssGroupIDManager.freeHandle(id);
}
uint32_t ResourceManager::allocVENCChannelID()
{
return _vencChannelIDManager.allocHandle();
}
void ResourceManager::freeVENCChannelID(uint32_t id)
{
_vencChannelIDManager.freeHandle(id);
}
uint32_t ResourceManager::allocVDECChannelID()
{
return _vdecChannelIDManager.allocHandle();
}
void ResourceManager::freeVDECChannelID(uint32_t id)
{
_vdecChannelIDManager.freeHandle(id);
}
uint32_t ResourceManager::allocAENCChannelID()
{
return _aencChannelIDManager.allocHandle();
}
void ResourceManager::freeAENCChannelID(uint32_t id)
{
_aencChannelIDManager.freeHandle(id);
}
uint32_t ResourceManager::allocRGNHandle()
{
return _rgnHandleManager.allocHandle();
}
void ResourceManager::freeRGNHandle(uint32_t handle)
{
_rgnHandleManager.freeHandle(handle);
}
}
}

View file

@ -0,0 +1,60 @@
#ifndef CAE4D712_1E71_4191_9693_2F31854D9087
#define CAE4D712_1E71_4191_9693_2F31854D9087
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "util/HandlesManager.h"
/*
*******************************************************************************
* CONSTANTS
*******************************************************************************
*/
#define NO_SIGNAL_YUV_PATH "/customer/no-signal-1080.yvu422sp"
#define NO_SIGNAL_YUV_FORMAT HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422
#define NO_SIGNAL_YUV_WIDTH 1920
#define NO_SIGNAL_YUV_HEIGHT 1080
#define NO_SIGNAL_JPEG_PATH "/customer/no-signal-1080.jpg"
#define NO_SIGNAL_JPEG_WIDTH 1920
#define NO_SIGNAL_JPEG_HEIGHT 1080
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class ResourceManager
{
public:
static uint32_t allocVPSSGroupID();
static void freeVPSSGroupID(uint32_t id);
static uint32_t allocVENCChannelID();
static void freeVENCChannelID(uint32_t id);
static uint32_t allocVDECChannelID();
static void freeVDECChannelID(uint32_t id);
static uint32_t allocAENCChannelID();
static void freeAENCChannelID(uint32_t id);
static uint32_t allocRGNHandle();
static void freeRGNHandle(uint32_t handle);
private:
static Util::HandlesManager<uint32_t> _vpssGroupIDManager;
static Util::HandlesManager<uint32_t> _vencChannelIDManager;
static Util::HandlesManager<uint32_t> _vdecChannelIDManager;
static Util::HandlesManager<uint32_t> _aencChannelIDManager;
static Util::HandlesManager<uint32_t> _rgnHandleManager;
};
}
}
#endif

110
video/hisi/mpp5/System.cpp Normal file
View file

@ -0,0 +1,110 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "System.h"
#include "Logger.h"
#include <hi_buffer.h>
#include <hi_common.h>
#include <hi_mpi_tde.h>
#include <hi_mpi_sys.h>
#include <hi_mpi_vb.h>
/*
*******************************************************************************
* CONSTANTS
*******************************************************************************
*/
#ifndef INPUT_IMAGE_WIDTH_MAX
#define INPUT_IMAGE_WIDTH_MAX 3840
#endif
#ifndef INPUT_IMAGE_HEIGHT_MAX
#define INPUT_IMAGE_HEIGHT_MAX 2160
#endif
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
System::System()
{
hi_mpi_sys_exit();
hi_mpi_vb_exit();
hi_vb_cfg vbcfg;
memset(&vbcfg, 0, sizeof(vbcfg));
vbcfg.max_pool_cnt = 16;
hi_pic_buf_attr attr;
attr.width = INPUT_IMAGE_WIDTH_MAX;
attr.height = INPUT_IMAGE_HEIGHT_MAX;
attr.align = HI_DEFAULT_ALIGN;
attr.bit_width = OT_DATA_BIT_WIDTH_8;
attr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422;
attr.compress_mode = HI_COMPRESS_MODE_FRAME;
uint32_t size = hi_common_get_pic_buf_size(&attr);
sprintf(vbcfg.common_pool[0].mmz_name, "%s", "anonymous");
vbcfg.common_pool[0].remap_mode = OT_VB_REMAP_MODE_NONE;
vbcfg.common_pool[0].blk_cnt = 32;
vbcfg.common_pool[0].blk_size = size;
attr.width = 1920;
attr.height = 1080;
attr.align = HI_DEFAULT_ALIGN;
attr.bit_width = OT_DATA_BIT_WIDTH_8;
attr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422;
attr.compress_mode = HI_COMPRESS_MODE_FRAME;
size = hi_common_get_pic_buf_size(&attr);
sprintf(vbcfg.common_pool[1].mmz_name, "%s", "anonymous");
vbcfg.common_pool[1].remap_mode = OT_VB_REMAP_MODE_NONE;
vbcfg.common_pool[1].blk_cnt = 32;
vbcfg.common_pool[1].blk_size = size;
int rc = hi_mpi_vb_set_cfg(&vbcfg);
if (rc != HI_SUCCESS)
{
logger().error("VB Set config FAIL: %#x", (uint32_t)rc);
return;
}
rc = hi_mpi_vb_init();
if (rc != HI_SUCCESS)
{
logger().error("VB Initialize FAIL: %#x", (uint32_t)rc);
return;
}
rc = hi_mpi_sys_init();
if (rc != HI_SUCCESS)
{
logger().error("SYS Initialize FAIL: %#x", (uint32_t)rc);
return;
}
hi_mpi_sys_init_pts_base(0);
hi_tde_open();
}
System::~System()
{
hi_tde_close();
hi_mpi_sys_exit();
hi_mpi_vb_exit();
}
uint64_t System::getTimestamp()
{
hi_u64 now;
hi_mpi_sys_get_cur_pts(&now);
return now;
}
}
}

31
video/hisi/mpp5/System.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef D30EB83D_9A50_4F5F_8549_B0B9F16AE7AD
#define D30EB83D_9A50_4F5F_8549_B0B9F16AE7AD
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "../../core/System.h"
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class System: public Core::System
{
public:
System();
~System();
protected:
uint64_t getTimestamp() override;
};
}
}
#endif

100
video/hisi/mpp5/Util.cpp Normal file
View file

@ -0,0 +1,100 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "Util.h"
#include <Poco/Exception.h>
#include <Poco/Format.h>
#include <array>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* TYPEDEFS
*******************************************************************************
*/
struct CodecIDMapItem
{
Core::CodecID id;
hi_payload_type pt;
};
/*
*******************************************************************************
* LOCAL VARIABLES
*******************************************************************************
*/
static const std::array<CodecIDMapItem, 7> codecMap = {{
{Core::CodecID::H264, HI_PT_H264},
{Core::CodecID::H265, HI_PT_H265},
{Core::CodecID::MJPEG, HI_PT_MJPEG},
{Core::CodecID::MP3, HI_PT_MP3},
{Core::CodecID::AAC, HI_PT_AAC},
{Core::CodecID::G711A, HI_PT_G711A},
{Core::CodecID::G711U, HI_PT_G711U},
}};
/*
*******************************************************************************
* FUNCTIONS
*******************************************************************************
*/
static hi_payload_type findPayloadType(Core::CodecID id)
{
for (const auto& m : codecMap)
{
if (id == m.id)
return m.pt;
}
throw Poco::NotFoundException(Poco::format("Video::MPP5: Can't find %s in codec-map", Core::codecIDToString(id)));
}
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
hi_audio_bit_width Util::getBitWidth(Core::SampleFormat format)
{
if (16 == Core::sampleFormatBitWidth(format))
return HI_AUDIO_BIT_WIDTH_16;
throw Poco::InvalidArgumentException("MPP5: Only support 16 bit-width", -EINVAL);
}
hi_audio_snd_mode Util::getSndMode(Core::ChannelLayout layout)
{
if (Core::ChannelLayout::STEREO == layout)
return HI_AUDIO_SOUND_MODE_STEREO;
return HI_AUDIO_SOUND_MODE_MONO;
}
hi_payload_type Util::getPayloadType(Core::CodecID id)
{
return findPayloadType(id);
}
uint32_t Util::getChannelId(const std::string& name)
{
if (name.find("NET0") != std::string::npos)
return 2;
else if (name.find("NET1") != std::string::npos)
return 3;
else if (name.find("NET2") != std::string::npos)
return 4;
else if (name.find("NET3") != std::string::npos)
return 5;
else if (name.find("USB") != std::string::npos)
return 6;
else if (name.find("File") != std::string::npos)
return 7;
}
}
}

32
video/hisi/mpp5/Util.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef CFE2FF99_0E17_46AD_B839_023CAED87EE5
#define CFE2FF99_0E17_46AD_B839_023CAED87EE5
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "../../core/SampleFormat.h"
#include "../../core/CodecID.h"
#include <hi_common_aio.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class Util
{
public:
static hi_audio_bit_width getBitWidth(Core::SampleFormat format);
static hi_audio_snd_mode getSndMode(Core::ChannelLayout layout);
static hi_payload_type getPayloadType(Core::CodecID id);
static uint32_t getChannelId(const std::string& name);
};
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,123 @@
#ifndef CF63EDDC_B464_4F43_9D68_4B200F07DD82
#define CF63EDDC_B464_4F43_9D68_4B200F07DD82
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "MPPChannel.h"
#include "VideoFrame.h"
#include "../../core/VideoDecoder.h"
#include "../../core/CodecCapabilityManager.h"
#include "../../core/FrameSynchronizer.h"
#include <functional>
#include "util/Broadcast.h"
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class VideoDecoder: public MPPChannel,
public Core::VideoDecoder
{
private:
class Pipe: public MPPChannel
{
public:
Pipe(const std::string& name, uint32_t id);
~Pipe();
public:
void start(uint32_t width, uint32_t height);
void stop();
void write(VideoFrame& frame, uint64_t pts, uint32_t timeref, bool isFrozen, hi_video_frame_info& frameX);
uint32_t groupID() const;
const std::string& name() const;
const uint32_t width();
const uint32_t height();
private:
const std::string _name;
uint32_t _width;
uint32_t _height;
};
enum class PostTaskControl
{
RUNNING,
EXIT,
INSTANT_EXIT,
};
public:
VideoDecoder(const std::string& name);
~VideoDecoder();
void reset() override;
protected:
void start() override;
void stop() override;
void initialize() override;
void deinitialize() override;
void onConfigChanged(ParameterNames& names) override;
Core::Frame::Ptr decode() override;
void bind(const MPPChannel& next) override;
void unbind(const MPPChannel& next) override;
void sendUserFrame(VideoFrame::Ptr pFrame, uint64_t duration, uint32_t& timeref);
void runSendUserFrame(VideoFrame::Ptr pFrame, std::function<bool(void)> condition);
void runSignalLost(std::atomic<bool>& isCancelled);
void runFault(std::atomic<bool>& isCancelled);
Core::Packet::Ptr runExceptionProcedure(std::atomic<bool>& isCancelled);
bool handleSerialCode(const Core::SerialCode& code);
void handlePreviousChanged();
void decodePacket(Core::Packet::Ptr pPacket, std::atomic<bool>& isCancelled);
void createDecoder(uint32_t width, uint32_t height, uint32_t frameRate, Core::CodecID codecID);
void releaseDecoder(bool instant = false);
Core::Packet::Ptr tryReadPacket(uint32_t timeout, bool shuldLog);
void releaseCapabilityHandle();
void frameCopy(hi_video_frame_info& from, hi_video_frame_info& to);
void frameRelease(hi_video_frame_info& frame);
bool saveSingleFrame(hi_video_frame_info& frame, const std::string& dir_path);
bool loadVideoFrame(const std::string& dir_path, hi_video_frame_info& frame);
private:
Core::CodecCapabilityManager::Handle _handle;
Pipe _pipe;
::Util::Task _postTask;
std::atomic<PostTaskControl> _postTaskControl;
uint32_t _frameTimeRef = 2;
Core::FrameSynchronizer _synchronizer;
const uint32_t _channelId;
hi_video_frame_info _frameX;
bool _frozenPlay;
bool _firstPic;
bool _buttonPressed;
bool _lastStatus;
bool _catchUpEnabled;
bool _isCatchingUp;
void updateCatchUpState();
PROPERTY_DECLARE(UsingCapability, Core::CodecID, Core::CodecID::NB, private, private)
public:
static void initModule();
static void deinitModule();
private:
static Core::CodecCapabilityManager _vdhCapabilityManager;
static Core::CodecCapabilityManager _jpgdCapabilityManager;
};
}
}
#endif

View file

@ -0,0 +1,682 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "VideoEncoder.h"
#include "ResourceManager.h"
#include "Logger.h"
#include "util/Math.h"
#include <errno.h>
using namespace Util;
/*
*******************************************************************************
* CONSTANTS
*******************************************************************************
*/
#define MIN_ALIGN 2
/*
*******************************************************************************
* MACROS
*******************************************************************************
*/
#define __set_basic(attr, gop, sfr, dfr) \
attr.gop = (gop); \
attr.src_frame_rate = (sfr); \
attr.dst_frame_rate = (dfr);
#define __set_cbr(attr, gop, st, sfr, dfr, br) \
__set_basic(attr, gop, sfr, dfr) attr.stats_time = (st); \
attr.bit_rate = (br);
#define __set_vbr(attr, gop, st, sfr, dfr, br) \
__set_basic(attr, gop, sfr, dfr) attr.stats_time = (st); \
attr.max_bit_rate = (br);
#define __set_avbr __set_vbr
#define __set_qvbr(attr, gop, st, sfr, dfr, br) \
__set_basic(attr, gop, sfr, dfr) attr.stats_time = (st); \
attr.target_bit_rate = (br);
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
VideoEncoder::Preprocessor::Preprocessor(const std::string& name, uint32_t id)
: MPPChannel((uint32_t)HI_ID_VPSS, id, 0), _name(Poco::format("%s(VPSS#%u)", name, id))
{
}
VideoEncoder::Preprocessor::~Preprocessor()
{
}
void VideoEncoder::Preprocessor::start(uint32_t iwidth, uint32_t iheight, uint32_t owidth, uint32_t oheight)
{
hi_vpss_grp_attr attr = {};
attr.nr_en = HI_FALSE;
attr.ie_en = HI_FALSE;
attr.dci_en = HI_FALSE;
attr.buf_share_en = HI_FALSE;
attr.buf_share_chn = 0;
attr.mcf_en = HI_FALSE;
attr.max_width = iwidth;
attr.max_height = iheight;
attr.max_dei_width = iwidth;
attr.max_dei_height = iheight;
attr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
attr.dynamic_range = HI_DYNAMIC_RANGE_SDR8;
attr.frame_rate.src_frame_rate = -1;
attr.frame_rate.dst_frame_rate = -1;
attr.dei_mode = HI_VPSS_DEI_MODE_OFF;
int rc = hi_mpi_vpss_create_grp(groupID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Create group FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
hi_mpi_vpss_reset_grp(groupID());
rc = hi_mpi_vpss_start_grp(groupID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Start group FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
hi_vpss_chn_attr chnAttr = {};
chnAttr.chn_mode = HI_VPSS_CHN_MODE_USER;
chnAttr.width = owidth;
chnAttr.height = oheight;
chnAttr.video_format = HI_VIDEO_FORMAT_LINEAR;
chnAttr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
chnAttr.dynamic_range = HI_DYNAMIC_RANGE_SDR8;
chnAttr.compress_mode = HI_COMPRESS_MODE_NONE;
chnAttr.frame_rate.src_frame_rate = -1;
chnAttr.frame_rate.dst_frame_rate = -1;
chnAttr.mirror_en = HI_FALSE;
chnAttr.flip_en = HI_FALSE;
chnAttr.depth = 0;
chnAttr.aspect_ratio.mode = HI_ASPECT_RATIO_NONE;
rc = hi_mpi_vpss_set_chn_attr(groupID(), channelID(), &chnAttr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Set channel#%u attr FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc), rc);
rc = hi_mpi_vpss_enable_chn(groupID(), channelID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Enable channel#%u FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc), rc);
}
void VideoEncoder::Preprocessor::stop()
{
int rc = hi_mpi_vpss_disable_chn(groupID(), channelID());
if (rc != HI_SUCCESS)
logger().error("%s: Disable channel#%u FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc);
rc = hi_mpi_vpss_stop_grp(groupID());
if (rc != HI_SUCCESS)
logger().error("%s: Stop group FAIL: %d(%#x)", name(), rc, (uint32_t)rc);
rc = hi_mpi_vpss_destroy_grp(groupID());
if (rc != HI_SUCCESS)
logger().error("%s: Destroy group FAIL: %d(%#x)", name(), rc, (uint32_t)rc);
}
uint32_t VideoEncoder::Preprocessor::groupID() const
{
return deviceID();
}
const std::string& VideoEncoder::Preprocessor::name() const
{
return _name;
}
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
Core::CodecCapabilityManager VideoEncoder::_capabilityManager(1920 * 1080 * 30 * 4 + 720 * 480 * 30 * 4);
VideoEncoder::VideoEncoder(Core::CodecID codecID)
: MPPChannel((uint32_t)HI_ID_VENC, 0, ResourceManager::allocVENCChannelID()),
Core::VideoEncoder(Poco::format("MPP5::VENC#%u(%s)", channelID(), Core::codecIDToString(codecID)), codecID),
_handle(Core::CodecCapabilityManager::INVALID_HANDLE), _preprocessor(name(), ResourceManager::allocVPSSGroupID())
{
registerNotificationHandle<Core::ParameterChangedNotification>(*this,
&VideoEncoder::handlePreviousParameterChanged);
}
VideoEncoder::~VideoEncoder()
{
ResourceManager::freeVPSSGroupID(_preprocessor.groupID());
ResourceManager::freeVENCChannelID(channelID());
releaseCapabilityHandle();
}
void VideoEncoder::start()
{
if (previousComponents().size() == 0)
throw Poco::BugcheckException(Poco::format("%s: No previous component", name()));
auto pPrevious = previousComponents().first().cast<VideoComponent>();
if (!pPrevious)
throw Poco::BugcheckException(Poco::format("%s: First previous component '%s' convert to 'VideoComponent' FAIL",
name(), previousComponents().first()->name()));
uint32_t width;
uint32_t height;
getEncodeResolution(pPrevious, width, height);
_preprocessor.start(pPrevious->getWidth(), pPrevious->getHeight(), width, height);
hi_venc_chn_attr attr = {};
attr.venc_attr.max_pic_width = width;
attr.venc_attr.max_pic_height = height;
attr.venc_attr.pic_width = width;
attr.venc_attr.pic_height = height;
attr.venc_attr.buf_size =
Util::Math::alignup(attr.venc_attr.max_pic_width * attr.venc_attr.max_pic_height * 3 / 2, 64);
attr.venc_attr.is_by_frame = HI_TRUE;
switch (getCodecID())
{
default:
case Core::CodecID::H264:
attr.venc_attr.type = HI_PT_H264;
switch (getCodecProfile())
{
case Core::CodecProfile::H264_BASELINE:
attr.venc_attr.profile = 0;
break;
default:
case Core::CodecProfile::H264_MAIN:
attr.venc_attr.profile = 1;
break;
case Core::CodecProfile::H264_HIGH:
attr.venc_attr.profile = 2;
break;
case Core::CodecProfile::H264_SVC_T:
attr.venc_attr.profile = 3;
break;
}
attr.venc_attr.h264_attr.rcn_ref_share_buf_en = HI_FALSE;
attr.venc_attr.h264_attr.frame_buf_ratio = 100;
break;
case Core::CodecID::H265:
attr.venc_attr.type = HI_PT_H265;
switch (getCodecProfile())
{
default:
case Core::CodecProfile::H265_MAIN:
attr.venc_attr.profile = 0;
break;
case Core::CodecProfile::H265_MAIN_10:
attr.venc_attr.profile = 1;
break;
}
attr.venc_attr.h265_attr.rcn_ref_share_buf_en = HI_FALSE;
attr.venc_attr.h265_attr.frame_buf_ratio = 100;
}
setChnAttrRateControl(attr, getCodecID(), getBitrateControl(), getSuitableGOP(), getSuitableSFR(), getSuitableDFR(),
getSuitableBitrate());
setChnAttrGOPMode(attr, getGOPMode(), getSuitableGOP());
int rc = hi_mpi_venc_create_chn(channelID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Create channel FAIL: %#x", name(), (uint32_t)rc), rc);
rc = hi_mpi_venc_reset_chn(channelID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Reset channel recv FAIL: %#x", name(), (uint32_t)rc), rc);
hi_venc_start_param param;
param.recv_pic_num = -1;
rc = hi_mpi_venc_start_chn(channelID(), &param);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Start channel recv FAIL: %#x", name(), (uint32_t)rc), rc);
task().run(
[this](std::atomic<bool>& isCancelled) -> void
{
while (!isCancelled)
{
try
{
postToNextComponents(sharedFromThis(), readPacket(1000), Core::MediaType::VIDEO);
}
catch (Poco::Exception& e)
{
logger().error("%s: %s", name(), e.displayText());
Poco::Thread::sleep(1000);
}
}
});
}
void VideoEncoder::stop()
{
task().cancel();
hi_mpi_venc_stop_chn(channelID());
hi_mpi_venc_reset_chn(channelID());
hi_mpi_venc_destroy_chn(channelID());
_preprocessor.stop();
}
void VideoEncoder::initialize()
{
uint32_t width;
uint32_t height;
getEncodeResolution(getPrevious(), width, height);
setWidth(width);
setHeight(height);
}
void VideoEncoder::deinitialize()
{
releaseCapabilityHandle();
}
void VideoEncoder::onConfigChanged(ParameterNames& names)
{
if (!started())
return;
if (names.exists(_CodecProfile) || names.exists(_Width) || names.exists(_Height) || names.exists(_FrameRate))
{
serialCodeManager().put(_Width, getWidth());
serialCodeManager().put(_Height, getHeight());
stop();
deinitialize();
initialize();
start();
return;
}
hi_venc_chn_attr attr;
hi_mpi_venc_get_chn_attr(channelID(), &attr);
if (names.exists(_GOPMode) || names.exists(_GOP) || names.exists(_BitrateControl) || names.exists(_Bitrate))
{
setChnAttrGOPMode(attr, getGOPMode(), getGOP());
setChnAttrRateControl(attr, getCodecID(), getBitrateControl(), getSuitableGOP(), getSuitableSFR(),
getSuitableDFR(), getSuitableBitrate());
}
hi_mpi_venc_set_chn_attr(channelID(), &attr);
}
void VideoEncoder::onLink(Core::Component::Ptr pPrevious)
{
_preprocessor.doLink(pPrevious);
_preprocessor.bind(*this);
}
void VideoEncoder::onUnlink(Core::Component::Ptr pPrevious)
{
_preprocessor.doUnlink(pPrevious);
_preprocessor.unbind(*this);
}
void VideoEncoder::handlePreviousParameterChanged(const Poco::AutoPtr<Core::ParameterChangedNotification>& pNotication)
{
if (!started())
return;
const auto& parameters = pNotication->parameters();
auto pPrevious = getPrevious();
if (parameters.exists(_Width) || parameters.exists(_Height))
{
uint32_t width;
uint32_t height;
getEncodeResolution(pPrevious, width, height);
if (getWidth() == width && getHeight() == height)
{
_preprocessor.stop();
_preprocessor.start(pPrevious->getWidth(), pPrevious->getHeight(), width, height);
}
else
{
setWidth(width);
setHeight(height);
commit();
}
}
if (parameters.exists(_FrameRate))
{
hi_venc_chn_attr attr;
hi_mpi_venc_get_chn_attr(channelID(), &attr);
setChnAttrRateControl(attr, getCodecID(), getBitrateControl(), getSuitableGOP(), getSuitableSFR(),
getSuitableDFR(), getSuitableBitrate());
hi_mpi_venc_set_chn_attr(channelID(), &attr);
}
}
Core::VideoComponent::Ptr VideoEncoder::getPrevious()
{
auto pPrevious = previousComponents().first().cast<VideoComponent>();
if (!pPrevious)
throw Poco::BugcheckException(Poco::format("%s: First previous component '%s' convert to 'VideoComponent' FAIL",
name(), previousComponents().first()->name()));
return pPrevious;
}
int VideoEncoder::getSuitableGOP()
{
return Math::clamp(getGOP(), 1, 65535);
}
int VideoEncoder::getSuitableSFR()
{
return Math::clamp(getPrevious()->getFrameRate(), HI_VENC_MIN_INPUT_FRAME_RATE, HI_VENC_MAX_INPUT_FRAME_RATE);
}
int VideoEncoder::getSuitableDFR()
{
return Math::clamp(Math::min(getFrameRate(), getSuitableSFR()), HI_VENC_MIN_INPUT_FRAME_RATE,
HI_VENC_MAX_INPUT_FRAME_RATE);
;
}
uint32_t VideoEncoder::getSuitableBitrate()
{
return Math::clamp(getBitrate() / 1000, (int64_t)HI_VENC_MIN_BITRATE, (int64_t)HI_VENC_MAX_BITRATE);
}
void VideoEncoder::getEncodeResolution(Core::VideoComponent::Ptr pPrevious, uint32_t& width, uint32_t& height)
{
if (getAdaptable() && !pPrevious.isNull())
{
width = pPrevious->getWidth();
height = pPrevious->getHeight();
}
else
{
width = getWidth();
height = getHeight();
}
width = Math::alignup(Math::clamp(width, (uint32_t)HI_VENC_H264_MIN_WIDTH, (uint32_t)HI_VENC_H264_MAX_WIDTH),
MIN_ALIGN);
height = Math::alignup(Math::clamp(height, (uint32_t)HI_VENC_H264_MIN_HEIGHT, (uint32_t)HI_VENC_H264_MAX_HEIGHT),
MIN_ALIGN);
if (width == 0 || height == 0)
{
width = 1920;
height = 1080;
}
}
Core::Packet::Ptr VideoEncoder::readPacket(uint32_t timeout)
{
static const int PACKET_DATA_SIZE_MAX = (1024 * 1024 * 2);
Core::Packet::Ptr pPacket = nullptr;
const long tvsec = timeout / 1000;
const long tvusec = 0;
int fd = hi_mpi_venc_get_fd(channelID());
while (true)
{
struct timeval tm = {
.tv_sec = tvsec,
.tv_usec = tvusec,
};
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(fd, &read_fds);
int rc = select(fd + 1, &read_fds, NULL, NULL, &tm);
if (rc < 0)
throw Poco::InvalidAccessException(
Poco::format("%s: Read stream FAIL: %s", name(), std::string(strerror(rc))), rc);
else if (0 == rc)
throw Poco::TimeoutException(Poco::format("%s: Read encoder stream timeout!", name()), rc);
if (!FD_ISSET(fd, &read_fds))
continue;
hi_venc_chn_status status;
hi_mpi_venc_query_status(channelID(), &status);
hi_venc_stream stream;
stream.pack = (hi_venc_pack*)malloc(sizeof(hi_venc_pack) * status.cur_packs);
if (!stream.pack)
continue;
stream.pack_cnt = status.cur_packs;
rc = hi_mpi_venc_get_stream(channelID(), &stream, timeout);
if (rc != HI_SUCCESS)
{
free(stream.pack);
throw Poco::InvalidAccessException(Poco::format("%s: Get encoder stream FAIL: %#x", name(), (uint32_t)rc),
rc);
}
bool done = false;
uint8_t* pBuffer = new uint8_t[PACKET_DATA_SIZE_MAX];
if (!pBuffer)
{
free(stream.pack);
throw Poco::OutOfMemoryException(Poco::format("%s: Alloc memory for encoded data: FAIL", name()), 0);
}
uint32_t length = 0;
uint32_t flags = Core::Packet::FLAG_IS_VIDEO;
for (uint32_t i = 0; i < stream.pack_cnt; i++)
{
hi_venc_pack* pack = &stream.pack[i];
uint32_t chucksize = pack->len - pack->offset;
if (chucksize < PACKET_DATA_SIZE_MAX - length)
{
memcpy(&pBuffer[length], pack->addr + pack->offset, chucksize);
length += chucksize;
}
else
logger().error("%s: Buffer size(%d) is insufficient to hold the encoded data!", PACKET_DATA_SIZE_MAX);
if (pack->is_frame_end)
{
switch (getCodecID())
{
default:
case Core::CodecID::H264:
if (stream.h264_info.ref_type == HI_VENC_BASE_IDR_SLICE)
flags |= Core::Packet::FLAG_IS_KEY;
break;
case Core::CodecID::H265:
if (stream.h265_info.ref_type == HI_VENC_BASE_IDR_SLICE)
flags |= Core::Packet::FLAG_IS_KEY;
break;
}
pPacket = new Core::Packet(serialCodeManager().code(), flags, pBuffer, length, pack->pts, pack->pts);
done = true;
break;
}
}
rc = hi_mpi_venc_release_stream(channelID(), &stream);
free(stream.pack);
stream.pack = NULL;
if (done)
break;
}
return pPacket;
}
void VideoEncoder::setChnAttrGOPMode(hi_venc_chn_attr& attr, const Core::GOPMode mode, int gop)
{
switch (mode)
{
case Core::GOPMode::NORMAL_P:
attr.gop_attr.gop_mode = HI_VENC_GOP_MODE_NORMAL_P;
attr.gop_attr.normal_p.ip_qp_delta = 2;
break;
case Core::GOPMode::SMART_P:
attr.gop_attr.gop_mode = HI_VENC_GOP_MODE_SMART_P;
attr.gop_attr.smart_p.bg_interval = gop;
attr.gop_attr.smart_p.bg_qp_delta = 4;
attr.gop_attr.smart_p.vi_qp_delta = 2;
break;
default:
throw Poco::InvalidArgumentException(
Poco::format("%s: Invalid gop-mode: %s", name(), Core::gopModeToString(getGOPMode())), -1);
}
}
void VideoEncoder::setChnAttrRateControl(hi_venc_chn_attr& attr, Core::CodecID codec, Core::BitrateControl bc, int gop,
int sfr, int dfr, uint32_t bitrate)
{
logger().debug("%s: confiure: %s, %s, GOP:%d, sfr:%d, dfr:%d, %uKbps", name(), Core::codecIDToString(codec),
Core::bitrateControlToString(bc), gop, sfr, dfr, bitrate);
if (Core::CodecID::H264 == codec)
{
switch (bc)
{
case Core::BitrateControl::CBR:
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H264_CBR;
__set_cbr(attr.rc_attr.h264_cbr, gop, 1, sfr, dfr, bitrate);
break;
case Core::BitrateControl::VBR:
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H264_VBR;
__set_vbr(attr.rc_attr.h264_vbr, gop, 1, sfr, dfr, bitrate);
break;
case Core::BitrateControl::AVBR:
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H264_AVBR;
__set_avbr(attr.rc_attr.h264_avbr, gop, 1, sfr, dfr, bitrate);
break;
case Core::BitrateControl::QVBR:
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H264_QVBR;
__set_qvbr(attr.rc_attr.h264_qvbr, gop, 1, sfr, dfr, bitrate);
break;
case Core::BitrateControl::CVBR:
case Core::BitrateControl::FIXQP:
case Core::BitrateControl::QPMAP:
default:
throw Poco::NotImplementedException(Poco::format("%s: Not implemented H.264 bitrate-control: %s", name(),
Core::bitrateControlToString(getBitrateControl())),
-1);
}
}
else if (Core::CodecID::H265 == codec)
{
switch (bc)
{
case Core::BitrateControl::CBR:
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H265_CBR;
__set_cbr(attr.rc_attr.h265_cbr, gop, 1, sfr, dfr, bitrate);
break;
case Core::BitrateControl::VBR:
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H265_VBR;
__set_vbr(attr.rc_attr.h265_vbr, gop, 1, sfr, dfr, bitrate);
break;
case Core::BitrateControl::AVBR:
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H265_AVBR;
__set_avbr(attr.rc_attr.h265_avbr, gop, 1, sfr, dfr, bitrate);
break;
case Core::BitrateControl::QVBR:
attr.rc_attr.rc_mode = HI_VENC_RC_MODE_H265_QVBR;
__set_qvbr(attr.rc_attr.h265_qvbr, gop, 1, sfr, dfr, bitrate);
break;
case Core::BitrateControl::CVBR:
case Core::BitrateControl::FIXQP:
case Core::BitrateControl::QPMAP:
default:
throw Poco::NotImplementedException(Poco::format("%s: Not implemented H.265 bitrate-control: %s", name(),
Core::bitrateControlToString(getBitrateControl())),
-1);
}
}
}
void VideoEncoder::releaseCapabilityHandle()
{
}
void VideoEncoder::initModule()
{
hi_venc_mod_param param = {};
param.mod_type = HI_VENC_MOD_H264;
param.h264_mod_param.one_stream_buf = 0;
param.h264_mod_param.mini_buf_mode = 0;
param.h264_mod_param.low_power_mode = 0;
param.h264_mod_param.vb_src = HI_VB_SRC_PRIVATE;
param.h264_mod_param.qp_hist_en = HI_FALSE;
param.h264_mod_param.max_user_data_len = 1024;
int rc = hi_mpi_venc_set_mod_param(&param);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("MPP5::VENC: Set module H264 param FAIL: %u(%#x)", (uint32_t)rc, (uint32_t)rc));
param.mod_type = HI_VENC_MOD_H265;
param.h265_mod_param.one_stream_buf = 0;
param.h265_mod_param.mini_buf_mode = 0;
param.h265_mod_param.low_power_mode = 0;
param.h265_mod_param.vb_src = HI_VB_SRC_PRIVATE;
param.h265_mod_param.qp_hist_en = HI_FALSE;
param.h265_mod_param.max_user_data_len = 32768;
rc = hi_mpi_venc_set_mod_param(&param);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("MPP5::VENC: Set module H265 param FAIL: %u(%#x)", (uint32_t)rc, (uint32_t)rc));
}
void VideoEncoder::deinitModule()
{
}
}
}

View file

@ -0,0 +1,91 @@
#ifndef F3099295_0B78_4FE9_A07D_1748943D2805
#define F3099295_0B78_4FE9_A07D_1748943D2805
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "MPPChannel.h"
#include "../core/VideoEncoder.h"
#include "../core/CodecCapabilityManager.h"
#include "../../core/Notifications.h"
#include "util/HandlesManager.h"
#include <hi_mpi_venc.h>
#include <hi_mpi_vpss.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class VideoEncoder: public MPPChannel, public Core::VideoEncoder
{
private:
class Preprocessor: public MPPChannel
{
public:
using Ptr = Poco::SharedPtr<Preprocessor>;
public:
Preprocessor(const std::string& name, uint32_t id);
~Preprocessor();
public:
void start(uint32_t iwidth, uint32_t iheight, uint32_t owidth, uint32_t oheight);
void stop();
uint32_t groupID() const;
const std::string& name() const;
private:
const std::string _name;
};
public:
VideoEncoder(Core::CodecID codecID);
~VideoEncoder();
protected:
void start() override;
void stop() override;
void initialize() override;
void deinitialize() override;
void onConfigChanged(ParameterNames& names) override;
void onLink(Core::Component::Ptr pPrevious) override;
void onUnlink(Core::Component::Ptr pPrevious) override;
void handlePreviousParameterChanged(const Poco::AutoPtr<Core::ParameterChangedNotification>& pNotication);
Core::VideoComponent::Ptr getPrevious();
int getSuitableGOP();
int getSuitableSFR();
int getSuitableDFR();
uint32_t getSuitableBitrate();
void getEncodeResolution(Core::VideoComponent::Ptr pPrevious, uint32_t& width, uint32_t& height);
void setChnAttrGOPMode(hi_venc_chn_attr& attr, Core::GOPMode mode, int gop);
void setChnAttrRateControl(hi_venc_chn_attr& attr, Core::CodecID codec, Core::BitrateControl bc, int gop, int sfr,
int dfr, uint32_t bitrate);
Core::Packet::Ptr readPacket(uint32_t timeout);
void releaseCapabilityHandle();
private:
Core::CodecCapabilityManager::Handle _handle;
Preprocessor _preprocessor;
public:
static void initModule();
static void deinitModule();
private:
static Core::CodecCapabilityManager _capabilityManager;
};
}
}
#endif

View file

@ -0,0 +1,194 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "VideoFrame.h"
#include "util/Math.h"
#include <hi_mpi_sys.h>
#include <hi_mpi_vdec.h>
#include <Poco/Format.h>
#include <Poco/FileStream.h>
#include <string.h>
#include <iostream>
/*
*******************************************************************************
* CONSTANTS
*******************************************************************************
*/
#define POOL_ID 0
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
VideoFrame::VideoFrame(hi_video_frame_info* pInfo, uint32_t size, uint8_t* pVirAddr, uint32_t phyAddr, uint32_t handle,
uint32_t chn)
: _pInfo(pInfo), _size(size), _pVirAddr(pVirAddr), _phyAddr(phyAddr), _handle(handle), _chn(chn)
{
}
VideoFrame::~VideoFrame()
{
if (!_pInfo)
return;
switch (_pInfo->mod_id)
{
case HI_ID_USER:
if (_pVirAddr)
{
hi_mpi_sys_munmap(_pVirAddr, _size);
hi_mpi_vb_release_blk(_handle);
}
break;
case HI_ID_VDEC:
hi_mpi_vdec_release_frame(_chn, _pInfo);
break;
default:
std::cout << Poco::format("error: VideoFrame: Unsupported mod id: %d", (int)_pInfo->mod_id) << std::endl;
break;
}
free(_pInfo);
}
VideoFrame::Ptr VideoFrame::create(hi_pixel_format format, uint32_t width, uint32_t height, const uint8_t* pData)
{
uint32_t stride = Util::Math::alignup(width, 16);
uint32_t imagesz, lumasz, chromasz;
switch (format)
{
case HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420:
case HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420:
imagesz = stride * Util::Math::alignup(height, 16) * 3 / 2;
lumasz = stride * height;
chromasz = lumasz >> 1;
break;
case HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422:
case HI_PIXEL_FORMAT_YUV_SEMIPLANAR_422:
imagesz = stride * Util::Math::alignup(height, 16) * 2;
lumasz = stride * height;
chromasz = lumasz;
break;
default:
throw Poco::NotImplementedException("Unsupported pixel format");
}
hi_vb_blk handle = hi_mpi_vb_get_blk(POOL_ID, imagesz, "anonymous");
if (HI_VB_INVALID_HANDLE == handle)
throw Poco::RuntimeException(
Poco::format("VideoFrame: Failed to get VB block: %u bytes @POOL#%d", imagesz, (int)POOL_ID));
hi_phys_addr_t phyAddr = hi_mpi_vb_handle_to_phys_addr(handle);
if (!phyAddr)
throw Poco::RuntimeException("VideoFrame: Failed to get VB block phys-addr");
uint8_t* pVirAddr = (uint8_t*)hi_mpi_sys_mmap(phyAddr, imagesz);
if (!pVirAddr)
throw Poco::RuntimeException("VideoFrame: Failed to map VB block");
hi_video_frame_info* pInfo = (hi_video_frame_info*)malloc(sizeof(hi_video_frame_info));
if (!pInfo)
throw Poco::OutOfMemoryException("VideoFrame: Failed to allocate frame info");
memset(pInfo, 0, sizeof(*pInfo));
pInfo->mod_id = HI_ID_USER;
pInfo->pool_id = POOL_ID;
hi_video_frame* pVideoFrame = &pInfo->video_frame;
pVideoFrame->width = width;
pVideoFrame->height = height;
pVideoFrame->field = HI_VIDEO_FIELD_FRAME;
pVideoFrame->pixel_format = (hi_pixel_format)format;
pVideoFrame->video_format = HI_VIDEO_FORMAT_LINEAR;
pVideoFrame->compress_mode = HI_COMPRESS_MODE_NONE;
pVideoFrame->dynamic_range = HI_DYNAMIC_RANGE_SDR8;
pVideoFrame->color_gamut = HI_COLOR_GAMUT_BT601;
switch (format)
{
case HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420:
case HI_PIXEL_FORMAT_YUV_SEMIPLANAR_420:
pVideoFrame->stride[0] = stride;
pVideoFrame->stride[1] = stride;
pVideoFrame->phys_addr[0] = phyAddr;
pVideoFrame->phys_addr[1] = (phyAddr + lumasz);
pVideoFrame->virt_addr[0] = (hi_void*)pVirAddr;
pVideoFrame->virt_addr[1] = (hi_void*)(pVirAddr + lumasz);
pVideoFrame->time_ref = 0;
pVideoFrame->pts = 0;
pVideoFrame->frame_flag = 0;
memcpy(pVideoFrame->virt_addr[0], pData, lumasz);
memcpy(pVideoFrame->virt_addr[1], pData + lumasz, chromasz);
break;
case HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422:
case HI_PIXEL_FORMAT_YUV_SEMIPLANAR_422:
pVideoFrame->stride[0] = stride;
pVideoFrame->stride[1] = stride;
pVideoFrame->phys_addr[0] = phyAddr;
pVideoFrame->phys_addr[1] = (phyAddr + lumasz);
pVideoFrame->virt_addr[0] = (hi_void*)pVirAddr;
pVideoFrame->virt_addr[1] = (hi_void*)(pVirAddr + lumasz);
pVideoFrame->time_ref = 0;
pVideoFrame->pts = 0;
pVideoFrame->frame_flag = 0;
memcpy(pVideoFrame->virt_addr[0], pData, lumasz);
memcpy(pVideoFrame->virt_addr[1], pData + lumasz, chromasz);
break;
default:
throw Poco::NotImplementedException("VideoFrame: Unsupported pixel format");
}
return new VideoFrame(pInfo, imagesz, pVirAddr, phyAddr, handle, 0);
}
VideoFrame::Ptr VideoFrame::create(hi_pixel_format format, uint32_t width, uint32_t height, const std::string& path)
{
uint32_t size;
Poco::SharedPtr<uint8_t> pData;
try
{
Poco::FileInputStream fist(path);
fist.seekg(0, fist.end);
size = fist.tellg();
fist.seekg(0, fist.beg);
pData = new uint8_t[size];
fist.read((char*)pData.get(), size);
fist.close();
}
catch (Poco::Exception& e)
{
size = width * height * 3;
pData = new uint8_t[size];
}
return create(format, width, height, pData);
}
}
}

View file

@ -0,0 +1,73 @@
#ifndef B9B55BBA_D4EA_459D_AB14_BEB06E1FB74A
#define B9B55BBA_D4EA_459D_AB14_BEB06E1FB74A
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include <hi_mpi_ive.h>
#include <hi_mpi_vb.h>
#include <Poco/SharedPtr.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class VideoFrame
{
public:
using Ptr = Poco::SharedPtr<VideoFrame>;
private:
VideoFrame(hi_video_frame_info* pInfo, uint32_t size, uint8_t* pVirAddr, uint32_t phyAddr, uint32_t handle,
uint32_t chn);
public:
~VideoFrame();
public:
const hi_video_frame_info* info() const;
const uint32_t width() const;
const uint32_t height() const;
const hi_pixel_format pixelFormat() const;
private:
hi_video_frame_info* _pInfo;
uint32_t _size;
uint8_t* _pVirAddr;
uint32_t _phyAddr;
uint32_t _handle;
uint32_t _chn;
public:
static Ptr create(hi_pixel_format format, uint32_t width, uint32_t height, const uint8_t* pData);
static Ptr create(hi_pixel_format format, uint32_t width, uint32_t height, const std::string& path);
};
inline const hi_video_frame_info* VideoFrame::info() const
{
return _pInfo;
}
inline const uint32_t VideoFrame::width() const
{
return _pInfo->video_frame.width;
}
inline const uint32_t VideoFrame::height() const
{
return _pInfo->video_frame.height;
}
inline const hi_pixel_format VideoFrame::pixelFormat() const
{
return _pInfo->video_frame.pixel_format;
}
}
}
#endif

View file

@ -0,0 +1,202 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "VideoInput.h"
#include "IVE.h"
#include "ResourceManager.h"
#include "../../core/Notifications.h"
#include "Application.h"
#include "Logger.h"
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
VideoFrame::Ptr VideoInput::_pUserVideoFrame = nullptr;
VideoInput::VideoInput(uint32_t deviceID, uint32_t channelID, bool dataReverseEnable)
: Core::VideoComponent(Poco::format("MPP5::VI#%u", deviceID)), MPPChannel((uint32_t)HI_ID_VI, deviceID, channelID),
_dataReverseEnable(dataReverseEnable), _channelId(deviceID == 2 ? 0 : 1)
{
setWidth(1920);
setHeight(1080);
setFrameRate(30);
setVideoScanMode(Core::VideoScanMode::PROGRESSIVE);
}
VideoInput::~VideoInput()
{
}
void VideoInput::start()
{
uint32_t width = getWidth();
uint32_t height = getHeight();
hi_vi_dev_attr devAttr;
devAttr.intf_mode = HI_VI_MODE_BT1120_STANDARD;
devAttr.work_mode = HI_VI_WORK_MODE_MULTIPLEX_1;
devAttr.component_mask[0] = 0x00000ff0;
devAttr.component_mask[1] = 0x000ff000;
devAttr.clk_edge = HI_VI_CLK_EDGE_SINGLE_UP;
devAttr.data_seq = HI_VI_IN_DATA_VUVU;
devAttr.sync_cfg.vsync = HI_VI_VSYNC_PULSE;
devAttr.sync_cfg.vsync_neg = HI_VI_VSYNC_NEG_LOW;
devAttr.sync_cfg.hsync = HI_VI_HSYNC_VALID_SIG;
devAttr.sync_cfg.hsync_neg = HI_VI_HSYNC_NEG_HIGH;
devAttr.sync_cfg.vsync_valid = HI_VI_VSYNC_VALID_SIG;
devAttr.sync_cfg.vsync_valid_neg = HI_VI_VSYNC_VALID_NEG_HIGH;
devAttr.sync_cfg.timing_blank.hsync_hfb = 0;
devAttr.sync_cfg.timing_blank.hsync_act = width;
devAttr.sync_cfg.timing_blank.hsync_hbb = 0;
devAttr.sync_cfg.timing_blank.vsync_vfb = 0;
devAttr.sync_cfg.timing_blank.vsync_vact = height;
devAttr.sync_cfg.timing_blank.vsync_vbb = 0;
devAttr.sync_cfg.timing_blank.vsync_vbfb = 0;
devAttr.sync_cfg.timing_blank.vsync_vbact = 0;
devAttr.sync_cfg.timing_blank.vsync_vbbb = 0;
devAttr.data_reverse_en = (hi_bool)_dataReverseEnable;
devAttr.mixed_capture_en = HI_FALSE;
auto rc = hi_mpi_vi_set_dev_attr(deviceID(), &devAttr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Set attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_vi_enable_dev(deviceID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Enable FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
hi_vi_chn_attr chnAttr;
chnAttr.capture_rect.x = 0;
chnAttr.capture_rect.y = 0;
chnAttr.capture_rect.width = width;
chnAttr.capture_rect.height = height;
chnAttr.dst_size.width = width;
chnAttr.dst_size.height = height;
chnAttr.capture_select = HI_VI_CAPTURE_SELECT_BOTH;
chnAttr.scan_mode = getVIScanMode();
chnAttr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422;
chnAttr.mirror_en = HI_FALSE;
chnAttr.flip_en = HI_FALSE;
chnAttr.compress_mode = HI_COMPRESS_MODE_NONE;
chnAttr.src_frame_rate = -1;
chnAttr.dst_frame_rate = -1;
auto channel = channelID();
rc = hi_mpi_vi_set_chn_attr(channel, &chnAttr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Configure channel FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_vi_set_frame_depth(channel, 4);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Configure frame depth FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_vi_enable_chn(channel);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Enable channel FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
enableUserPic(getSignalLost());
}
void VideoInput::stop()
{
enableUserPic(false);
hi_mpi_vi_disable_chn(channelID());
hi_mpi_vi_disable_dev(deviceID());
}
void VideoInput::onConfigChanged(ParameterNames& names)
{
if (!started())
return;
notifyNextComponents(sharedFromThis(), new Core::ParameterChangedNotification(names));
if (names.exists(_Width) || names.exists(_Height))
{
stop();
start();
return;
}
if (names.exists(_VideoScanMode))
{
hi_vi_chn_attr attr;
hi_mpi_vi_get_chn_attr(channelID(), &attr);
attr.scan_mode = getVIScanMode();
int rc = hi_mpi_vi_set_chn_attr(channelID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Configure channel FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
}
if (names.exists(_SignalLost))
enableUserPic(getSignalLost());
}
uint32_t VideoInput::traffic()
{
hi_vi_chn_status s;
return hi_mpi_vi_query(channelID(), &s) == HI_SUCCESS ? s.interrupt_cnt : 0;
}
void VideoInput::enableUserPic(bool enable)
{
if (enable)
hi_mpi_vi_enable_user_pic(channelID());
else
hi_mpi_vi_disable_user_pic(channelID());
}
hi_vi_scan_mode VideoInput::getVIScanMode()
{
return getVideoScanMode() == Core::VideoScanMode::PROGRESSIVE ? HI_VI_SCAN_PROGRESSIVE : HI_VI_SCAN_INTERLACED;
}
void VideoInput::initModule()
{
hi_vi_mod_param param;
hi_mpi_vi_get_mod_param(&param);
param.yc_reverse = 0;
hi_mpi_vi_set_mod_param(&param);
if (!_pUserVideoFrame)
_pUserVideoFrame =
VideoFrame::create(NO_SIGNAL_YUV_FORMAT, NO_SIGNAL_YUV_WIDTH, NO_SIGNAL_YUV_HEIGHT, NO_SIGNAL_YUV_PATH);
hi_vi_user_pic_attr attr = {};
attr.pub_en = HI_TRUE;
attr.user_pic_mode = HI_VI_USER_PIC_MODE_PIC;
attr.user_pic_info.user_pic_frame_info.mod_id = HI_ID_VI;
attr.user_pic_info.user_pic_frame_info.pool_id = 0;
attr.user_pic_info.user_pic_frame_info = *_pUserVideoFrame->info();
int rc = hi_mpi_vi_set_user_pic(0, &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("MPP::VI: Set user pic FAIL: %d(%#x)", rc, (uint32_t)rc), rc);
}
void VideoInput::deinitModule()
{
_pUserVideoFrame.reset();
}
void VideoInput::reset()
{
}
}
}

View file

@ -0,0 +1,55 @@
#ifndef FA05C272_A837_4EE6_A95D_55486BEA1F99
#define FA05C272_A837_4EE6_A95D_55486BEA1F99
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "../../core/VideoComponent.h"
#include "MPPChannel.h"
#include "VideoFrame.h"
#include <hi_mpi_vi.h>
#include "util/Broadcast.h"
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class VideoInput: public Core::VideoComponent, public MPPChannel
{
public:
using Ptr = Poco::AutoPtr<VideoInput>;
public:
VideoInput(uint32_t deviceID, uint32_t channelID, bool dataReverseEnable);
~VideoInput();
void reset() override;
protected:
void start() override;
void stop() override;
void onConfigChanged(ParameterNames& names) override;
uint32_t traffic() override;
void enableUserPic(bool enable);
hi_vi_scan_mode getVIScanMode();
private:
bool _dataReverseEnable;
const uint32_t _channelId;
public:
static void initModule();
static void deinitModule();
private:
static VideoFrame::Ptr _pUserVideoFrame;
};
}
}
#endif

View file

@ -0,0 +1,295 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "VideoMixer.h"
#include "util/Math.h"
#include <hi_mpi_vo.h>
#include <cmath>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CONSTANTS
*******************************************************************************
*/
#define WIDTH 1920
#define HEIGHT 1080
#define FRAMTE_RATE 60
#define VO_DEVICE_ID 1
#define VIDEO_LAYER_ID 1
#define VO_WBC_ID 0
#define VO_MAX_CHN_NUM (HI_VO_MAX_CHN_NUM - 1)
#define VO_CHN_PLACEHOLDER_ID (VO_MAX_CHN_NUM - 1)
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
VideoMixer::Channel::Channel(VideoMixer::Ptr pMixer, uint32_t id)
: MPPChannel((uint32_t)HI_ID_VO, VIDEO_LAYER_ID, id), Core::VideoMixer::Channel("MPP5::VHD1", pMixer, id)
{
}
VideoMixer::Channel::~Channel()
{
}
void VideoMixer::Channel::start()
{
if (mixer().cast<VideoMixer>()->started())
activate();
}
void VideoMixer::Channel::stop()
{
if (getActivated())
deactivate();
}
void VideoMixer::Channel::onConfigChanged(ParameterNames& names)
{
Core::VideoMixer::Channel::onConfigChanged(names);
if (!started())
return;
if (names.exists(_Attach))
{
if (!getAttach())
deactivate();
else if (mixer().cast<VideoMixer>()->started())
activate();
}
if ((names.exists(_Region) || names.exists(_ZOrder)) && getActivated())
configureChannel();
}
void VideoMixer::Channel::onLink(Core::Component::Ptr pPrevious)
{
MPPChannel::doLink(pPrevious);
}
void VideoMixer::Channel::onUnlink(Core::Component::Ptr pPrevious)
{
MPPChannel::doUnlink(pPrevious);
}
void VideoMixer::Channel::activate()
{
configureChannel();
int rc = hi_mpi_vo_enable_chn(VIDEO_LAYER_ID, channelID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: enable FAIL: %d(%#x)", mixer()->name() + "/" + name(), rc, (uint32_t)rc), rc);
setActivated(true);
}
void VideoMixer::Channel::deactivate()
{
hi_mpi_vo_disable_chn(VIDEO_LAYER_ID, channelID());
setActivated(false);
}
void VideoMixer::Channel::configureChannel()
{
const auto region = getRegion();
hi_vo_chn_attr attr;
attr.priority = ::Util::Math::clamp(getZOrder(), 0, VO_MAX_CHN_NUM - 2) + 1;
attr.rect.x =
::Util::Math::aligndown(::Util::Math::clamp(static_cast<int>(std::round(region.x * WIDTH)), 0, WIDTH - 32), 2);
attr.rect.y = ::Util::Math::aligndown(
::Util::Math::clamp(static_cast<int>(std::round(region.y * HEIGHT)), 0, HEIGHT - 32), 2);
attr.rect.width = ::Util::Math::aligndown(
::Util::Math::clamp(static_cast<int>(std::round(region.width * WIDTH)), 32, WIDTH - attr.rect.x), 2);
attr.rect.height = ::Util::Math::aligndown(
::Util::Math::clamp(static_cast<int>(std::round(region.height * HEIGHT)), 32, HEIGHT - attr.rect.y), 2);
;
attr.deflicker_en = HI_FALSE;
int rc = hi_mpi_vo_set_chn_attr(VIDEO_LAYER_ID, channelID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: set chn attr FAIL: %d(%#x)", mixer()->name() + "/" + name(), rc, (uint32_t)rc), rc);
}
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
VideoMixer::VideoMixer(const std::string& name)
: MPPChannel((uint32_t)HI_ID_VO, VO_DEVICE_ID, 0), Core::VideoMixer(Poco::format("%s(MPP5::VO::DHD1)", name))
{
setWidth(WIDTH);
setHeight(HEIGHT);
setFrameRate(FRAMTE_RATE);
setSignalLost(false);
}
VideoMixer::~VideoMixer()
{
}
void VideoMixer::start()
{
int rc = hi_mpi_vo_enable(deviceID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: enable VO FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
{
hi_vo_video_layer_attr attr;
attr.display_rect.x = 0;
attr.display_rect.y = 0;
attr.display_rect.width = WIDTH;
attr.display_rect.height = HEIGHT;
attr.img_size.width = WIDTH;
attr.img_size.height = HEIGHT;
attr.display_frame_rate = FRAMTE_RATE;
attr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422;
attr.double_frame_en = HI_FALSE;
attr.cluster_mode_en = HI_FALSE;
attr.dst_dynamic_range = HI_DYNAMIC_RANGE_SDR8;
attr.display_buf_len = 4;
attr.partition_mode = HI_VO_PARTITION_MODE_SINGLE;
attr.compress_mode = HI_COMPRESS_MODE_NONE;
rc = hi_mpi_vo_set_video_layer_attr(VIDEO_LAYER_ID, &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: set video layer attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_vo_enable_video_layer(VIDEO_LAYER_ID);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: enable video layer FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
}
{
hi_vo_wbc_src src;
src.src_type = HI_VO_WBC_SRC_VIDEO;
src.src_id = VIDEO_LAYER_ID;
rc = hi_mpi_vo_set_wbc_src(VO_WBC_ID, &src);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: set WBC src FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
rc = hi_mpi_vo_set_wbc_mode(VO_WBC_ID, HI_VO_WBC_MODE_NORM);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: set WBC mode FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
hi_vo_wbc_attr attr;
attr.target_size.width = WIDTH;
attr.target_size.height = HEIGHT;
attr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422;
attr.frame_rate = -1;
attr.dynamic_range = HI_DYNAMIC_RANGE_SDR8;
attr.compress_mode = HI_COMPRESS_MODE_NONE;
rc = hi_mpi_vo_set_wbc_attr(VO_WBC_ID, &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: set WBC attr FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
rc = hi_mpi_vo_enable_wbc(VO_WBC_ID);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: enable WBC FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
}
foreachChannel<Channel>(
[](Channel::Ptr pChannel) -> void
{
if (pChannel->getAttach())
pChannel->activate();
});
{
hi_vo_chn_attr attr;
attr.priority = 0;
attr.rect.x = 0;
attr.rect.y = 0;
attr.rect.width = 32;
attr.rect.height = 32;
attr.deflicker_en = HI_FALSE;
hi_mpi_vo_set_chn_attr(VIDEO_LAYER_ID, VO_CHN_PLACEHOLDER_ID, &attr);
hi_mpi_vo_enable_chn(VIDEO_LAYER_ID, VO_CHN_PLACEHOLDER_ID);
}
Core::VideoMixer::start();
}
void VideoMixer::stop()
{
hi_mpi_vo_disable_chn(VIDEO_LAYER_ID, VO_CHN_PLACEHOLDER_ID);
foreachChannel<Channel>(
[this](Channel::Ptr pChannel) -> void
{
if (pChannel->getActivated())
pChannel->deactivate();
});
Core::VideoMixer::stop();
int rc = hi_mpi_vo_disable_wbc(VO_WBC_ID);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: disable WBC FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_vo_disable_video_layer(VIDEO_LAYER_ID);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: disable video layer FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
rc = hi_mpi_vo_disable(VO_DEVICE_ID);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: disable VO FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
}
void VideoMixer::initialize()
{
hi_vo_pub_attr attr;
attr.bg_color = 0x000000;
attr.intf_type = HI_VO_INTF_BT1120;
attr.intf_sync = HI_VO_OUT_1080P60;
int rc = hi_mpi_vo_set_pub_attr(deviceID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: set-pub FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
}
void VideoMixer::deinitialize()
{
}
void VideoMixer::onConfigChanged(ParameterNames& names)
{
}
Core::VideoMixer::Channel::Ptr VideoMixer::createChannel(uint32_t id)
{
if (id >= VO_CHN_PLACEHOLDER_ID)
throw Poco::InvalidArgumentException(
Poco::format("%s: channel id %u overrage: [0,%u]", name(), id, (uint32_t)(VO_CHN_PLACEHOLDER_ID - 1)),
-EINVAL);
return new Channel(Ptr(this, true), id);
}
}
}

View file

@ -0,0 +1,68 @@
#ifndef B351F133_EBBC_42F5_9C48_5BA22D16BB53
#define B351F133_EBBC_42F5_9C48_5BA22D16BB53
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "MPPChannel.h"
#include "../../core/VideoMixer.h"
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class VideoMixer: public MPPChannel, public Core::VideoMixer
{
public:
class Channel: public MPPChannel, public Core::VideoMixer::Channel
{
public:
using Ptr = Poco::AutoPtr<Channel>;
protected:
Channel(VideoMixer::Ptr, uint32_t id);
public:
~Channel();
protected:
virtual void start() override;
virtual void stop() override;
void onConfigChanged(ParameterNames& names) override;
void onLink(Core::Component::Ptr pPrevious) override;
void onUnlink(Core::Component::Ptr pPrevious) override;
void activate();
void deactivate();
PROPERTY_DECLARE(Activated, bool, false, protected, protected)
void configureChannel();
friend class VideoMixer;
};
public:
VideoMixer(const std::string& name);
~VideoMixer();
protected:
void start() override;
void stop() override;
void initialize() override;
void deinitialize() override;
void onConfigChanged(ParameterNames& names) override;
Core::VideoMixer::Channel::Ptr createChannel(uint32_t id) override;
friend class Channel;
};
}
}
#endif

View file

@ -0,0 +1,317 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "VideoOverlay.h"
#include "MPPChannel.h"
#include "ResourceManager.h"
#include "util/Math.h"
#include "Logger.h"
#include <hi_mpi_tde.h>
#include <hi_mpi_sys.h>
#include <hi_mpi_vb.h>
#include <Poco/Exception.h>
#include <cstring>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
VideoOverlay::VideoOverlay(Core::VideoOverlayType type, const std::string& name, const Core::Rect& region)
: Core::VideoOverlay(type, name, region), _handle(ResourceManager::allocRGNHandle()), _imagePhyAddr(0),
_pImageVirAddr(nullptr)
{
hi_rgn_attr attr = {};
switch (type)
{
case Core::VideoOverlayType::CANVAS:
attr.type = HI_RGN_OVERLAY;
attr.attr.overlay.pixel_format = HI_PIXEL_FORMAT_ARGB_8888;
_bytesPerPixel = 4;
attr.attr.overlay.size.width = ::Util::Math::alignup(region.width, 2);
attr.attr.overlay.size.height = ::Util::Math::alignup(region.height, 2);
attr.attr.overlay.bg_color = 0;
attr.attr.overlay.canvas_num = 2;
break;
case Core::VideoOverlayType::MOSAIC:
attr.type = HI_RGN_MOSAIC;
break;
default:
throw Poco::LogicException(name + ": Unimplemented type: " + std::to_string((int)type));
}
int rc = hi_mpi_rgn_create(_handle, &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidArgumentException(Poco::format("%s: Create FAIL: %#x", name, (uint32_t)rc), rc);
}
VideoOverlay::~VideoOverlay()
{
_timer.cancel(true);
if (_pImageVirAddr != nullptr && _imagePhyAddr != 0)
hi_mpi_sys_mmz_free(_imagePhyAddr, _pImageVirAddr);
Core::VideoComponent::Ptr o = target();
auto chn = dynamic_cast<MPPChannel*>(o.get())->raw();
hi_mpi_rgn_detach_from_chn(_handle, &chn);
hi_mpi_rgn_destroy(_handle);
ResourceManager::freeRGNHandle(_handle);
}
void VideoOverlay::render(Core::Image::Ptr pImage)
{
hi_rgn_canvas_info info;
hi_mpi_rgn_get_canvas_info(_handle, &info);
uint32_t height = ::Util::Math::min((uint32_t)pImage->height(), (uint32_t)region().height);
for (uint32_t y = 0; y < height; y++)
{
int i = 0;
Core::Color color;
uint8_t* pLine = (uint8_t*)info.virt_addr + y * info.stride;
cimg_forX(*pImage, x)
{
if (x >= region().width)
continue;
pImage->getPixel(x, y, color);
color.toARGB8888Pixel(&pLine[i]);
i += _bytesPerPixel;
}
}
hi_mpi_rgn_update_canvas(_handle);
}
void VideoOverlay::scrollRender(Core::Image::Ptr pImage, int hscroll)
{
const int W = (int)region().width;
const int H = (int)::Util::Math::min((uint32_t)pImage->height(), (uint32_t)region().height);
const int textWidth = (int)pImage->width();
const int winW = (int)::Util::Math::min((uint32_t)W, 4096u);
const int period = 2 * W + textWidth;
const uint32_t stride = ::Util::Math::alignup((uint32_t)winW * _bytesPerPixel, 8);
int rc = hi_mpi_sys_mmz_alloc(&_imagePhyAddr, (void**)&_pImageVirAddr, nullptr, nullptr, (uint32_t)H * stride);
if (rc != HI_SUCCESS)
throw Poco::OutOfMemoryException(Poco::format("%s: Alloc MMZ FAIL: %#x", name(), (uint32_t)rc), rc);
_pTextImage = pImage;
_textWidth = textWidth;
_winW = winW;
_winH = H;
_stride = stride;
_period = period;
if (hscroll > 0)
_progressX = 0;
else
_progressX = period - W;
const int movePixels = hscroll;
const long interval = 30;
_timer.schedule(Poco::Util::Timer::func(
[this, W, movePixels]()
{
const int H = _winH;
const int winW = _winW;
const int textW = _textWidth;
const uint32_t stride = _stride;
const int period = _period;
::memset(_pImageVirAddr, 0, (uint32_t)H * stride);
int startStrip = (_progressX > W) ? _progressX : W;
int endStrip = ((_progressX + winW) < (W + textW)) ? (_progressX + winW) : (W + textW);
if (startStrip < endStrip)
{
int textStart = startStrip - W;
int winStart = startStrip - _progressX;
int count = endStrip - startStrip;
for (int y = 0; y < H; y++)
{
uint8_t* pWin =
_pImageVirAddr + (uint32_t)y * stride + (uint32_t)winStart * _bytesPerPixel;
Core::Color color;
for (int x = 0; x < count; x++)
{
_pTextImage->getPixel(textStart + x, y, color);
color.toARGB8888Pixel(&pWin[x * (int)_bytesPerPixel]);
}
}
}
hi_tde_surface srcSurface = {};
srcSurface.phys_addr = _imagePhyAddr;
srcSurface.color_format = HI_TDE_COLOR_FORMAT_ARGB8888;
srcSurface.height = (uint32_t)H;
srcSurface.width = (uint32_t)winW;
srcSurface.stride = stride;
srcSurface.is_ycbcr_clut = HI_FALSE;
srcSurface.alpha_max_is_255 = HI_TRUE;
srcSurface.support_alpha_ex_1555 = HI_FALSE;
srcSurface.alpha0 = 0XFF;
srcSurface.alpha1 = 0XFF;
hi_rgn_canvas_info info;
hi_mpi_rgn_get_canvas_info(_handle, &info);
const uint32_t dstW = ::Util::Math::min((uint32_t)region().width, 4096u);
const uint32_t dstH = ::Util::Math::min((uint32_t)region().height, 4096u);
hi_tde_surface dstSurface = {};
dstSurface.phys_addr = info.phys_addr;
dstSurface.color_format = HI_TDE_COLOR_FORMAT_ARGB8888;
dstSurface.height = dstH;
dstSurface.width = dstW;
dstSurface.stride = info.stride;
dstSurface.is_ycbcr_clut = HI_FALSE;
dstSurface.support_alpha_ex_1555 = HI_FALSE;
dstSurface.alpha_max_is_255 = HI_TRUE;
dstSurface.alpha0 = 0XFF;
dstSurface.alpha1 = 0XFF;
hi_tde_rect srcRect;
srcRect.pos_x = 0;
srcRect.pos_y = 0;
srcRect.width = (uint32_t)winW;
srcRect.height = (uint32_t)H;
hi_tde_rect dstRect;
dstRect.pos_x = 0;
dstRect.pos_y = 0;
dstRect.width = (uint32_t)winW;
dstRect.height = (uint32_t)H;
hi_s32 handle = hi_tde_begin_job();
hi_tde_single_src src;
src.src_surface = (hi_tde_surface*)&srcSurface;
src.dst_surface = (hi_tde_surface*)&dstSurface;
src.src_rect = (hi_tde_rect*)&srcRect;
src.dst_rect = (hi_tde_rect*)&dstRect;
int rc = hi_tde_quick_copy(handle, &src);
if (rc != HI_SUCCESS)
{
logger().error("%s: TDE quick copy FAIL: %#x", name(), (uint32_t)rc);
_timer.cancel(false);
return;
}
hi_tde_end_job(handle, HI_FALSE, HI_TRUE, 10);
hi_mpi_rgn_update_canvas(_handle);
_progressX += movePixels;
if (movePixels > 0)
{
if (_progressX >= period - W)
_progressX = 0;
}
else
{
if (_progressX <= 0)
_progressX = period - W;
}
}),
interval, interval);
}
void VideoOverlay::attach(Core::VideoComponent::Ptr pVideoComponent)
{
Core::VideoOverlay::attach(pVideoComponent);
hi_rgn_chn_attr attr = {};
attr.is_show = HI_TRUE;
switch (type())
{
case Core::VideoOverlayType::CANVAS:
attr.type = HI_RGN_OVERLAY;
attr.attr.overlay_chn.point.x = ::Util::Math::alignup(region().x, 2);
attr.attr.overlay_chn.point.y = ::Util::Math::alignup(region().y, 2);
attr.attr.overlay_chn.fg_alpha = 0;
attr.attr.overlay_chn.bg_alpha = 0;
attr.attr.overlay_chn.layer = getLayer();
attr.attr.overlay_chn.qp_info.enable = HI_FALSE;
attr.attr.overlay_chn.qp_info.is_abs_qp = HI_FALSE;
attr.attr.overlay_chn.qp_info.qp_val = 0;
attr.attr.overlay_chn.dst = HI_RGN_ATTACH_JPEG_MAIN;
break;
case Core::VideoOverlayType::MOSAIC:
attr.type = HI_RGN_MOSAIC;
attr.attr.mosaic_chn.rect.x = ::Util::Math::alignup(region().x, 4);
;
attr.attr.mosaic_chn.rect.y = ::Util::Math::alignup(region().y, 2);
attr.attr.mosaic_chn.rect.width = ::Util::Math::alignup(region().width, 4);
attr.attr.mosaic_chn.rect.height = ::Util::Math::alignup(region().height, 2);
attr.attr.mosaic_chn.blk_size = getBlockSize();
attr.attr.mosaic_chn.layer = getLayer();
break;
default:
throw Poco::LogicException(name() + ": Unimplemented type: " + std::to_string((int)type()));
}
auto t = target();
auto pChannel = dynamic_cast<MPPChannel*>(t.get());
if (!pChannel)
throw Poco::LogicException(name() + ": Unsupported target: " + target()->name());
auto chn = pChannel->raw();
int rc = hi_mpi_rgn_attach_to_chn(_handle, &chn, &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidArgumentException(Poco::format("%s: Attach FAIL: %#x", name(), (uint32_t)rc), rc);
}
void VideoOverlay::onConfigChanged(ParameterNames& names)
{
if (names.exists(_ZOrder))
{
auto t = target();
auto pChannel = dynamic_cast<MPPChannel*>(t.get());
auto chn = pChannel->raw();
hi_rgn_chn_attr attr;
hi_mpi_rgn_get_display_attr(_handle, &chn, &attr);
switch (attr.type)
{
case HI_RGN_OVERLAY:
attr.attr.overlay_chn.layer = getZOrder();
break;
default:
break;
}
hi_mpi_rgn_set_display_attr(_handle, &chn, &attr);
}
}
hi_mosaic_blk_size VideoOverlay::getBlockSize()
{
switch (getBlock())
{
default:
case 8:
return HI_MOSAIC_BLK_SIZE_8;
case 16:
return HI_MOSAIC_BLK_SIZE_16;
case 32:
return HI_MOSAIC_BLK_SIZE_32;
}
}
hi_u32 VideoOverlay::getLayer()
{
return ::Util::Math::clamp(getZOrder(), 0, 4);
}
}
}

View file

@ -0,0 +1,53 @@
#ifndef ECE73282_2093_4767_B1C9_C38188A584FF
#define ECE73282_2093_4767_B1C9_C38188A584FF
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "../../core/VideoOverlay.h"
#include <hi_mpi_region.h>
#include <Poco/Util/Timer.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class VideoOverlay: public Core::VideoOverlay
{
public:
VideoOverlay(Core::VideoOverlayType type, const std::string& name, const Core::Rect& region);
~VideoOverlay();
void render(Core::Image::Ptr pImage) override;
void scrollRender(Core::Image::Ptr pImage, int hscroll) override;
void attach(Core::VideoComponent::Ptr pVideoComponent) override;
protected:
void onConfigChanged(ParameterNames& names) override;
hi_mosaic_blk_size getBlockSize();
hi_u32 getLayer();
private:
hi_rgn_handle _handle;
unsigned _bytesPerPixel;
uint32_t _imagePhyAddr;
uint8_t* _pImageVirAddr;
Poco::Util::Timer _timer;
int _progressX;
Core::Image::Ptr _pTextImage;
int _textWidth;
int _winW;
int _winH;
uint32_t _stride;
int _period;
};
}
}
#endif

View file

@ -0,0 +1,289 @@
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "VideoProcessor.h"
#include "Logger.h"
#include "ResourceManager.h"
#include "VideoInput.h"
#include "util/Math.h"
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DEFINE
*******************************************************************************
*/
VideoProcessor::VideoProcessor()
: MPPChannel((uint32_t)HI_ID_VPSS, ResourceManager::allocVPSSGroupID(), 0),
Core::VideoProcessor(Poco::format("VideoProcessor(VPSS#%u)", deviceID()))
{
registerNotificationHandle<Core::ParameterChangedNotification>(*this,
&VideoProcessor::handlePreviousParameterChanged);
}
VideoProcessor::~VideoProcessor()
{
ResourceManager::freeVPSSGroupID(deviceID());
}
void VideoProcessor::start()
{
auto pPrevious = previousComponents().first().cast<VideoComponent>();
if (!pPrevious)
throw Poco::BugcheckException(Poco::format("%s: First previous component '%s' convert to 'VideoComponent' FAIL",
name(), previousComponents().first()->name()));
setWidth(pPrevious->getWidth());
setHeight(pPrevious->getHeight());
setVideoScanMode(pPrevious->getVideoScanMode());
uint32_t width = getWidth();
uint32_t height = getHeight();
hi_vpss_grp_attr attr = {};
attr.nr_en = HI_FALSE;
attr.ie_en = HI_FALSE;
attr.dci_en = HI_FALSE;
attr.buf_share_en = HI_FALSE;
attr.buf_share_chn = 0;
attr.mcf_en = HI_FALSE;
attr.max_width = width;
attr.max_height = height;
attr.max_dei_width = width;
attr.max_dei_height = height;
attr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_422;
attr.dynamic_range = HI_DYNAMIC_RANGE_SDR8;
attr.frame_rate.src_frame_rate = -1;
attr.frame_rate.dst_frame_rate = -1;
if (!pPrevious.cast<VideoInput>().isNull() && getVideoScanMode() == Core::VideoScanMode::INTERLACED)
{
attr.dei_mode = HI_VPSS_DEI_MODE_AUTO;
setFrameRate(pPrevious->getFrameRate() / 2);
}
else
{
attr.dei_mode = HI_VPSS_DEI_MODE_OFF;
setFrameRate(pPrevious->getFrameRate());
}
int rc = hi_mpi_vpss_create_grp(groupID(), &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Create group FAIL: %d(%#x)", name(), rc, (uint32_t)rc),
rc);
hi_mpi_vpss_reset_grp(groupID());
rc = hi_mpi_vpss_start_grp(groupID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(Poco::format("%s: Start group FAIL: %d(%#x)", name(), rc, (uint32_t)rc), rc);
bool isPreviousMJPEG = false;
uint32_t direction = 0;
hi_vpss_chn_attr chnAttr = {};
chnAttr.chn_mode = HI_VPSS_CHN_MODE_USER;
chnAttr.width = width;
chnAttr.height = height;
chnAttr.video_format = HI_VIDEO_FORMAT_LINEAR;
chnAttr.pixel_format = HI_PIXEL_FORMAT_YVU_SEMIPLANAR_420;
chnAttr.dynamic_range = HI_DYNAMIC_RANGE_SDR8;
chnAttr.compress_mode = HI_COMPRESS_MODE_NONE;
chnAttr.frame_rate.src_frame_rate = -1;
chnAttr.frame_rate.dst_frame_rate = -1;
chnAttr.mirror_en = (hi_bool)getMirror();
chnAttr.flip_en = (hi_bool)getFlip();
chnAttr.depth = 0;
setVPSSVideoDirection(isPreviousMJPEG && direction, &chnAttr);
rc = hi_mpi_vpss_set_chn_attr(groupID(), channelID(), &chnAttr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Set channel#%u attr FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc), rc);
setVPSSChannelRotation(getRotation(), channelID());
setVPSSGroupCrop(getCrop());
rc = hi_mpi_vpss_enable_chn(groupID(), channelID());
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Enable channel#%u FAIL: %d(%#x)", name(), channelID(), rc, (uint32_t)rc), rc);
}
void VideoProcessor::stop()
{
hi_mpi_vpss_disable_chn(groupID(), channelID());
hi_mpi_vpss_stop_grp(groupID());
hi_mpi_vpss_destroy_grp(groupID());
}
void VideoProcessor::onConfigChanged(ParameterNames& names)
{
if (!started())
return;
if (names.exists(_Width) || names.exists(_Height))
{
stop();
start();
publishEvent(Core::Component::Event::IMAGE_SIZE_CHANGED);
return;
}
if (names.exists(_Rotation))
setVPSSChannelRotation(getRotation(), channelID());
if (names.exists(_Crop))
setVPSSGroupCrop(getCrop());
if (names.exists(_Mirror) || names.exists(_Flip))
{
hi_vpss_chn_attr attr;
hi_mpi_vpss_get_chn_attr(groupID(), channelID(), &attr);
attr.mirror_en = (hi_bool)getMirror();
attr.flip_en = (hi_bool)getFlip();
hi_mpi_vpss_set_chn_attr(groupID(), channelID(), &attr);
}
if (names.exists(_VideoDirection))
{
hi_vpss_chn_attr attr;
hi_mpi_vpss_get_chn_attr(groupID(), channelID(), &attr);
setVPSSVideoDirection(attr.aspect_ratio.mode == HI_ASPECT_RATIO_NONE, &attr);
hi_mpi_vpss_set_chn_attr(groupID(), channelID(), &attr);
}
}
void VideoProcessor::onLink(Core::Component::Ptr pPrevious)
{
MPPChannel::doLink(pPrevious);
}
void VideoProcessor::onUnlink(Core::Component::Ptr pPrevious)
{
MPPChannel::doUnlink(pPrevious);
}
void VideoProcessor::handlePreviousParameterChanged(
const Poco::AutoPtr<Core::ParameterChangedNotification>& pNotication)
{
auto pPrevious = previousComponents().first().cast<VideoComponent>();
if (!pPrevious)
throw Poco::BugcheckException(Poco::format("%s: First previous component '%s' convert to 'VideoComponent' FAIL",
name(), previousComponents().first()->name()));
auto parameters = pNotication->parameters();
if (parameters.exists(_Width))
setWidth(pPrevious->getWidth());
if (parameters.exists(_Height))
setHeight(pPrevious->getHeight());
if (parameters.exists(_FrameRate))
setFrameRate(pPrevious->getFrameRate());
if (parameters.exists(_VideoScanMode))
{
setVideoScanMode(pPrevious->getVideoScanMode());
if (started())
{
hi_vpss_grp_attr attr;
hi_mpi_vpss_get_grp_attr(groupID(), &attr);
if (!pPrevious.cast<VideoInput>().isNull() && getVideoScanMode() == Core::VideoScanMode::INTERLACED)
{
attr.dei_mode = HI_VPSS_DEI_MODE_AUTO;
setFrameRate(pPrevious->getFrameRate() / 2);
}
else
{
attr.dei_mode = HI_VPSS_DEI_MODE_OFF;
setFrameRate(pPrevious->getFrameRate());
}
hi_mpi_vpss_set_grp_attr(groupID(), &attr);
}
parameters.insert(_FrameRate);
}
commit();
notifyNextComponents(sharedFromThis(), new Core::ParameterChangedNotification(parameters));
}
void VideoProcessor::setVPSSGroupCrop(const Core::Rect& rect)
{
int x = Util::Math::clamp(rect.x, 0, HI_VPSS_MAX_IMG_WIDTH - 1);
int y = Util::Math::clamp(rect.y, 0, HI_VPSS_MAX_IMG_HEIGHT - 1);
int width = Util::Math::clamp(rect.width, HI_VPSS_MIN_IMG_WIDTH,
Util::Math::max(HI_VPSS_MIN_IMG_WIDTH, HI_VPSS_MAX_IMG_WIDTH - rect.x));
int height = Util::Math::clamp(rect.height, HI_VPSS_MIN_IMG_HEIGHT,
Util::Math::max(HI_VPSS_MIN_IMG_HEIGHT, HI_VPSS_MAX_IMG_HEIGHT - rect.y));
hi_vpss_crop_info crop = {};
crop.enable = (hi_bool) !(rect.x == 0 && rect.y == 0 && rect.width == 0 && rect.height == 0);
crop.crop_mode = HI_COORD_ABS;
crop.crop_rect.x = x;
crop.crop_rect.y = y;
crop.crop_rect.width = width;
crop.crop_rect.height = height;
hi_mpi_vpss_set_grp_crop(groupID(), &crop);
}
void VideoProcessor::setVPSSChannelRotation(int rotation, uint32_t channelID)
{
hi_rotation_attr attr;
attr.enable = HI_TRUE;
attr.rotation_type = HI_ROTATION_ANG_FIXED;
switch (rotation)
{
default:
case 0:
attr.enable = HI_FALSE;
attr.rotation_fixed = HI_ROTATION_0;
break;
case 90:
attr.rotation_fixed = HI_ROTATION_90;
break;
case 180:
attr.rotation_fixed = HI_ROTATION_180;
break;
case 270:
attr.rotation_fixed = HI_ROTATION_270;
break;
}
int rc = hi_mpi_vpss_set_chn_rotation(groupID(), channelID, &attr);
if (rc != HI_SUCCESS)
throw Poco::InvalidAccessException(
Poco::format("%s: Set channel#%u rotation FAIL: %d(%#x)", name(), channelID, rc, (uint32_t)rc), rc);
}
void VideoProcessor::setVPSSVideoDirection(int direction, hi_vpss_chn_attr* attr)
{
if (!attr)
return;
if (direction)
{
uint32_t width = getWidth();
uint32_t height = getHeight();
attr->aspect_ratio.mode = HI_ASPECT_RATIO_MANUAL;
attr->aspect_ratio.bg_color = 0x000000;
attr->aspect_ratio.video_rect.width = height * height / width;
attr->aspect_ratio.video_rect.height = height;
attr->aspect_ratio.video_rect.x = (width - attr->aspect_ratio.video_rect.width) / 2;
attr->aspect_ratio.video_rect.y = 0;
}
else
attr->aspect_ratio.mode = HI_ASPECT_RATIO_NONE;
}
}
}

View file

@ -0,0 +1,49 @@
#ifndef FD7AD900_2C3C_41D7_A5C2_6B4F2B79CE9E
#define FD7AD900_2C3C_41D7_A5C2_6B4F2B79CE9E
/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "MPPChannel.h"
#include "../core/VideoProcessor.h"
#include "../../core/Notifications.h"
#include <hi_mpi_vpss.h>
namespace Video
{
namespace MPP5
{
/*
*******************************************************************************
* CLASS DECLARE
*******************************************************************************
*/
class VideoProcessor: public MPPChannel, public Core::VideoProcessor
{
public:
VideoProcessor();
~VideoProcessor();
protected:
void start() override;
void stop() override;
void onConfigChanged(ParameterNames& names) override;
void onLink(Core::Component::Ptr pPrevious) override;
void onUnlink(Core::Component::Ptr pPrevious) override;
void handlePreviousParameterChanged(const Poco::AutoPtr<Core::ParameterChangedNotification>& pNotication);
uint32_t groupID();
void setVPSSGroupCrop(const Core::Rect& rect);
void setVPSSChannelRotation(int rotation, uint32_t channelID);
void setVPSSVideoDirection(int direction, hi_vpss_chn_attr* attr);
};
inline uint32_t VideoProcessor::groupID()
{
return deviceID();
}
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,107 @@
/*
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
*/
#ifndef AUDIO_AAC_ADP_H
#define AUDIO_AAC_ADP_H
#include <stdio.h>
#include "hi_mpi_audio.h"
#include "hi_common_aenc.h"
#include "hi_common_adec.h"
#include "hi_common_aio.h"
#include "hi_aacdec.h"
#include "hi_aacenc.h"
/* samples per frame for AACLC and aacPlus */
#define AACLD_SAMPLES_PER_FRAME 512
#define AACLC_SAMPLES_PER_FRAME 1024
#define AACPLUS_SAMPLES_PER_FRAME 2048
/* max length of AAC stream by bytes */
#define MAX_AAC_MAINBUF_SIZE (768 * 2)
typedef enum {
HI_AAC_TYPE_AACLC = 0, /* AAC LC */
HI_AAC_TYPE_EAAC = 1, /* EAAC(HEAAC or AAC+ or aac_plus_v1) */
HI_AAC_TYPE_EAACPLUS = 2, /* EAAC+(AAC++ or aac_plus_v2) */
HI_AAC_TYPE_AACLD = 3,
HI_AAC_TYPE_AACELD = 4,
HI_AAC_TYPE_BUTT,
} hi_aac_type;
typedef enum {
HI_AAC_BPS_8K = 8000,
HI_AAC_BPS_16K = 16000,
HI_AAC_BPS_22K = 22000,
HI_AAC_BPS_24K = 24000,
HI_AAC_BPS_32K = 32000,
HI_AAC_BPS_48K = 48000,
HI_AAC_BPS_64K = 64000,
HI_AAC_BPS_96K = 96000,
HI_AAC_BPS_128K = 128000,
HI_AAC_BPS_256K = 256000,
HI_AAC_BPS_320K = 320000,
HI_AAC_BPS_BUTT
} hi_aac_bps;
typedef enum {
HI_AAC_TRANSPORT_TYPE_ADTS = 0,
HI_AAC_TRANSPORT_TYPE_LOAS = 1,
HI_AAC_TRANSPORT_TYPE_LATM_MCP1 = 2,
HI_AAC_TRANSPORT_TYPE_BUTT
} hi_aac_transport_type;
typedef struct {
hi_s32 sample_rate; /* sample rate */
hi_s32 bit_rate; /* bitrate */
hi_s32 profile; /* profile */
hi_s32 tns_used; /* TNS tools */
hi_s32 pns_used; /* PNS tools */
hi_s32 chn_num; /* channel num */
} aacdec_frame_info;
/*
* AAC commendatory parameter:
* sampling rate(HZ) LC bit_rate(kbit/s) EAAC bit_rate (kbit/s) EAAC+ bit_rate (kbit/s)
* 48000 128 48 32,24
* 44100 128 48 32,24
* 32000 96 22 16
* 24000 64
* 22050 64
* 16000 48
*/
typedef struct {
hi_aac_type aac_type; /* AAC profile type */
hi_aac_bps bit_rate; /* AAC bitrate(LC:16~320, EAAC:24~128, EAAC+:16~64, AACLD:16~320, AACELD:32~320) */
hi_audio_sample_rate sample_rate; /* AAC sample rate(LC:8~48, EAAC:16~48, EAAC+:16~48, AACLD:8~48, AACELD:8~48) */
hi_audio_bit_width bit_width; /* AAC bit width (only support 16bit) */
hi_audio_snd_mode snd_mode; /* sound mode of inferent audio frame */
hi_aac_transport_type transport_type;
hi_s16 band_width; /* targeted audio bandwidth in hz (0 or 1000~smp_rate/2), the default is 0 */
} hi_aenc_attr_aac;
typedef struct {
hi_aac_encoder *aac_state;
hi_aenc_attr_aac aac_attr;
} aenc_aac_encoder;
typedef struct {
hi_aac_transport_type transport_type;
} hi_adec_attr_aac;
typedef struct {
hi_aac_decoder aac_state;
hi_adec_attr_aac aac_attr;
} adec_aac_decoder;
hi_s32 hi_mpi_aenc_aac_init(hi_void);
hi_s32 hi_mpi_aenc_aac_deinit(hi_void);
hi_s32 hi_mpi_adec_aac_init(hi_void);
hi_s32 hi_mpi_adec_aac_deinit(hi_void);
#endif

View file

@ -0,0 +1,88 @@
/*
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
*/
#include "audio_dl_adp.h"
#include <stdio.h>
#ifndef __LITEOS__
#include <dlfcn.h>
#else
#include <los_ld_elflib.h>
#endif
hi_s32 audio_dlpath(hi_char *lib_path)
{
#ifndef __LITEOS__
(hi_void)lib_path;
#else
if (LOS_PathAdd(lib_path) != HI_SUCCESS) {
printf("add path %s failed!\n", lib_path);
return HI_FAILURE;
}
#endif
return HI_SUCCESS;
}
hi_s32 audio_dlopen(hi_void **lib_handle, hi_char *lib_name)
{
if ((lib_handle == HI_NULL) || (lib_name == HI_NULL)) {
return HI_FAILURE;
}
*lib_handle = HI_NULL;
#ifndef __LITEOS__
*lib_handle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);
#else
*lib_handle = LOS_SoLoad(lib_name);
#endif
if (*lib_handle == HI_NULL) {
printf("dlopen %s failed!\n", lib_name);
return HI_FAILURE;
}
return HI_SUCCESS;
}
hi_s32 audio_dlsym(hi_void **func_handle, hi_void *lib_handle, hi_char *func_name)
{
if (lib_handle == HI_NULL) {
printf("LibHandle is empty!");
return HI_FAILURE;
}
*func_handle = HI_NULL;
#ifndef __LITEOS__
*func_handle = dlsym(lib_handle, func_name);
#else
*func_handle = LOS_FindSymByName(lib_handle, func_name);
#endif
if (*func_handle == HI_NULL) {
#ifndef __LITEOS__
printf("dlsym %s fail, error msg is %s!\n", func_name, dlerror());
#else
printf("dlsym %s fail!\n", func_name);
#endif
return HI_FAILURE;
}
return HI_SUCCESS;
}
hi_s32 audio_dlclose(hi_void *lib_handle)
{
if (lib_handle == HI_NULL) {
printf("LibHandle is empty!");
return HI_FAILURE;
}
#ifndef __LITEOS__
dlclose(lib_handle);
#else
LOS_ModuleUnload(lib_handle);
#endif
return HI_SUCCESS;
}

View file

@ -0,0 +1,18 @@
/*
Copyright (c), 2001-2022, Shenshu Tech. Co., Ltd.
*/
#ifndef __AUDIO_DL_ADP_H__
#define __AUDIO_DL_ADP_H__
#include "hi_type.h"
hi_s32 audio_dlpath(hi_char *lib_path);
hi_s32 audio_dlopen(hi_void **lib_handle, hi_char *lib_name);
hi_s32 audio_dlsym(hi_void **func_handle, hi_void *lib_handle, hi_char *func_name);
hi_s32 audio_dlclose(hi_void *lib_handle);
#endif