/* ******************************************************************************* * INCLUDE ******************************************************************************* */ #include "VideoFrame.h" #include "util/Math.h" #include #include #include #include #include #include /* ******************************************************************************* * 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 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); } } }