p26001-store-acs-soc-fw-app/video/hisi/mpp5/VideoFrame.cpp
2026-09-28 21:33:04 +08:00

194 lines
5.9 KiB
C++

/*
*******************************************************************************
* 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);
}
}
}