From bad6cab2e4cd058260dbf34b6d2a0b87e3ca1311 Mon Sep 17 00:00:00 2001 From: oleg0421 Date: Sun, 9 Jun 2024 15:56:16 -0700 Subject: [PATCH] RDPECAM client: h264 interface changes --- include/freerdp/codec/h264.h | 17 ++++++++++++- libfreerdp/codec/h264.c | 43 ++++++++++++++++++++++++++++++++ libfreerdp/codec/h264.h | 1 + libfreerdp/codec/h264_openh264.c | 24 ++++++++++++++++-- 4 files changed, 82 insertions(+), 3 deletions(-) diff --git a/include/freerdp/codec/h264.h b/include/freerdp/codec/h264.h index 6ad96f91e..7f56c2fa0 100644 --- a/include/freerdp/codec/h264.h +++ b/include/freerdp/codec/h264.h @@ -41,12 +41,22 @@ extern "C" H264_RATECONTROL_CQP } H264_RATECONTROL_MODE; + typedef enum + { + H264_SCREEN_CONTENT_REAL_TIME = 0, + H264_SCREEN_CONTENT_NON_REAL_TIME, + H264_CAMERA_VIDEO_REAL_TIME, + H264_CAMERA_VIDEO_NON_REAL_TIME, + + } H264_USAGETYPE; + typedef enum { H264_CONTEXT_OPTION_RATECONTROL, H264_CONTEXT_OPTION_BITRATE, H264_CONTEXT_OPTION_FRAMERATE, - H264_CONTEXT_OPTION_QP + H264_CONTEXT_OPTION_QP, + H264_CONTEXT_OPTION_USAGETYPE, } H264_CONTEXT_OPTION; FREERDP_API void free_h264_metablock(RDPGFX_H264_METABLOCK* meta); @@ -60,6 +70,11 @@ extern "C" const RECTANGLE_16* regionRect, BYTE** ppDstData, UINT32* pDstSize, RDPGFX_H264_METABLOCK* meta); + /* API for user to fill YUV I420 buffer before encoding */ + FREERDP_API INT32 h264_get_yuv_buffer(H264_CONTEXT* h264, UINT32 nSrcStride, UINT32 nSrcWidth, + UINT32 nSrcHeight, BYTE* YUVData[3], UINT32 stride[3]); + FREERDP_API INT32 h264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize); + FREERDP_API INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nDstWidth, UINT32 nDstHeight, diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 718bd2ccf..27556131f 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -232,6 +232,44 @@ static BOOL detect_changes(BOOL firstFrameDone, const UINT32 QP, const RECTANGLE return TRUE; } +/** + * Function description + * + * @return + */ +INT32 h264_get_yuv_buffer(H264_CONTEXT* h264, UINT32 nSrcStride, UINT32 nSrcWidth, + UINT32 nSrcHeight, BYTE* YUVData[3], UINT32 stride[3]) +{ + if (!h264 || !h264->Compressor || !h264->subsystem || !h264->subsystem->Compress) + return -1; + + if (!avc420_ensure_buffer(h264, nSrcStride, nSrcWidth, nSrcHeight)) + return -1; + + for (size_t x = 0; x < 3; x++) + { + YUVData[x] = h264->pYUVData[x]; + stride[x] = h264->iStride[x]; + } + + return 0; +} + +/** + * Function description + * + * @return + */ +INT32 h264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize) +{ + if (!h264 || !h264->Compressor || !h264->subsystem || !h264->subsystem->Compress) + return -1; + + const BYTE* pcYUVData[3] = { h264->pYUVData[0], h264->pYUVData[1], h264->pYUVData[2] }; + + return h264->subsystem->Compress(h264, pcYUVData, h264->iStride, ppDstData, pDstSize); +} + INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep, UINT32 nSrcWidth, UINT32 nSrcHeight, const RECTANGLE_16* regionRect, BYTE** ppDstData, UINT32* pDstSize, RDPGFX_H264_METABLOCK* meta) @@ -749,6 +787,9 @@ BOOL h264_context_set_option(H264_CONTEXT* h264, H264_CONTEXT_OPTION option, UIN case H264_CONTEXT_OPTION_QP: h264->QP = value; return TRUE; + case H264_CONTEXT_OPTION_USAGETYPE: + h264->UsageType = value; + return TRUE; default: WLog_Print(h264->log, WLOG_WARN, "Unknown H264_CONTEXT_OPTION[0x%08" PRIx32 "]", option); @@ -769,6 +810,8 @@ UINT32 h264_context_get_option(H264_CONTEXT* h264, H264_CONTEXT_OPTION option) return h264->RateControlMode; case H264_CONTEXT_OPTION_QP: return h264->QP; + case H264_CONTEXT_OPTION_USAGETYPE: + return h264->UsageType; default: WLog_Print(h264->log, WLOG_WARN, "Unknown H264_CONTEXT_OPTION[0x%08" PRIx32 "]", option); diff --git a/libfreerdp/codec/h264.h b/libfreerdp/codec/h264.h index abd0aeb84..9c0463c7d 100644 --- a/libfreerdp/codec/h264.h +++ b/libfreerdp/codec/h264.h @@ -61,6 +61,7 @@ extern "C" UINT32 BitRate; UINT32 FrameRate; UINT32 QP; + UINT32 UsageType; UINT32 NumberOfThreads; UINT32 iStride[3]; diff --git a/libfreerdp/codec/h264_openh264.c b/libfreerdp/codec/h264_openh264.c index 92e4aaf1e..2823e55f9 100644 --- a/libfreerdp/codec/h264_openh264.c +++ b/libfreerdp/codec/h264_openh264.c @@ -228,14 +228,32 @@ static int openh264_compress(H264_CONTEXT* WINPR_RESTRICT h264, return status; } - sys->EncParamExt.iUsageType = SCREEN_CONTENT_REAL_TIME; + EUsageType usageType; + + switch (h264->UsageType) + { + case H264_CAMERA_VIDEO_NON_REAL_TIME: + usageType = CAMERA_VIDEO_NON_REAL_TIME; + break; + case H264_CAMERA_VIDEO_REAL_TIME: + usageType = CAMERA_VIDEO_REAL_TIME; + break; + case H264_SCREEN_CONTENT_NON_REAL_TIME: + usageType = SCREEN_CONTENT_NON_REAL_TIME; + break; + case H264_SCREEN_CONTENT_REAL_TIME: + default: + usageType = SCREEN_CONTENT_REAL_TIME; + break; + } + + sys->EncParamExt.iUsageType = usageType; sys->EncParamExt.iPicWidth = (int)h264->width; sys->EncParamExt.iPicHeight = (int)h264->height; sys->EncParamExt.fMaxFrameRate = (int)h264->FrameRate; sys->EncParamExt.iMaxBitrate = UNSPECIFIED_BIT_RATE; sys->EncParamExt.bEnableDenoise = 0; sys->EncParamExt.bEnableLongTermReference = 0; - sys->EncParamExt.bEnableFrameSkip = 0; sys->EncParamExt.iSpatialLayerNum = 1; sys->EncParamExt.iMultipleThreadIdc = (int)h264->NumberOfThreads; sys->EncParamExt.sSpatialLayers[0].fFrameRate = h264->FrameRate; @@ -250,11 +268,13 @@ static int openh264_compress(H264_CONTEXT* WINPR_RESTRICT h264, sys->EncParamExt.iTargetBitrate = (int)h264->BitRate; sys->EncParamExt.sSpatialLayers[0].iSpatialBitrate = sys->EncParamExt.iTargetBitrate; + sys->EncParamExt.bEnableFrameSkip = 1; break; case H264_RATECONTROL_CQP: sys->EncParamExt.iRCMode = RC_OFF_MODE; sys->EncParamExt.sSpatialLayers[0].iDLayerQp = (int)h264->QP; + sys->EncParamExt.bEnableFrameSkip = 0; break; }