Refactored encoder functions to return changed areas
This commit is contained in:
parent
50acf72615
commit
f346793970
@ -123,10 +123,7 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, RDPGFX_H2
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
error_out:
|
||||
free(meta->regionRects);
|
||||
meta->regionRects = NULL;
|
||||
free(meta->quantQualityVals);
|
||||
meta->quantQualityVals = NULL;
|
||||
free_h264_metablock(meta);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -169,8 +166,7 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
|
||||
WLog_ERR(TAG, "context->SurfaceCommand failed with error %" PRIu32 "", error);
|
||||
}
|
||||
|
||||
free(h264.meta.regionRects);
|
||||
free(h264.meta.quantQualityVals);
|
||||
free_h264_metablock(&h264.meta);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -259,10 +255,8 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
|
||||
|
||||
fail:
|
||||
Stream_Free(s, FALSE);
|
||||
free(h264.bitstream[0].meta.regionRects);
|
||||
free(h264.bitstream[0].meta.quantQualityVals);
|
||||
free(h264.bitstream[1].meta.regionRects);
|
||||
free(h264.bitstream[1].meta.quantQualityVals);
|
||||
free_h264_metablock(&h264.bitstream[0].meta);
|
||||
free_h264_metablock(&h264.bitstream[1].meta);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -51,10 +51,12 @@ struct _H264_CONTEXT
|
||||
UINT32 NumberOfThreads;
|
||||
|
||||
UINT32 iStride[3];
|
||||
BYTE* pOldYUVData[3];
|
||||
BYTE* pYUVData[3];
|
||||
|
||||
UINT32 iYUV444Size[3];
|
||||
UINT32 iYUV444Stride[3];
|
||||
BYTE* pOldYUV444Data[3];
|
||||
BYTE* pYUV444Data[3];
|
||||
|
||||
UINT32 numSystemData;
|
||||
@ -62,6 +64,10 @@ struct _H264_CONTEXT
|
||||
H264_CONTEXT_SUBSYSTEM* subsystem;
|
||||
YUV_CONTEXT* yuv;
|
||||
|
||||
BOOL encodingBuffer;
|
||||
BOOL firstLumaFrameDone;
|
||||
BOOL firstChromaFrameDone;
|
||||
|
||||
void* lumaData;
|
||||
wLog* log;
|
||||
};
|
||||
@ -70,9 +76,20 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
static INLINE void free_h264_metablock(RDPGFX_H264_METABLOCK* meta)
|
||||
{
|
||||
RDPGFX_H264_METABLOCK m = { 0 };
|
||||
if (!meta)
|
||||
return;
|
||||
free(meta->quantQualityVals);
|
||||
free(meta->regionRects);
|
||||
*meta = m;
|
||||
}
|
||||
|
||||
FREERDP_API INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat,
|
||||
UINT32 nSrcStep, UINT32 nSrcWidth, UINT32 nSrcHeight,
|
||||
BYTE** ppDstData, UINT32* pDstSize);
|
||||
const RECTANGLE_16* regionRect, BYTE** ppDstData,
|
||||
UINT32* pDstSize, RDPGFX_H264_METABLOCK* meta);
|
||||
|
||||
FREERDP_API INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE* pDstData, DWORD DstFormat, UINT32 nDstStep,
|
||||
@ -81,8 +98,10 @@ extern "C"
|
||||
|
||||
FREERDP_API INT32 avc444_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat,
|
||||
UINT32 nSrcStep, UINT32 nSrcWidth, UINT32 nSrcHeight,
|
||||
BYTE version, BYTE* op, BYTE** pDstData, UINT32* pDstSize,
|
||||
BYTE** pAuxDstData, UINT32* pAuxDstSize);
|
||||
BYTE version, const RECTANGLE_16* regionRect, BYTE* op,
|
||||
BYTE** pDstData, UINT32* pDstSize, BYTE** pAuxDstData,
|
||||
UINT32* pAuxDstSize, RDPGFX_H264_METABLOCK* meta,
|
||||
RDPGFX_H264_METABLOCK* auxMeta);
|
||||
|
||||
FREERDP_API INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op,
|
||||
const RECTANGLE_16* regionRects, UINT32 numRegionRect,
|
||||
|
@ -41,6 +41,9 @@ static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, DWORD nDstHeight);
|
||||
|
||||
BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT32 height)
|
||||
{
|
||||
size_t x;
|
||||
BOOL isNull = FALSE;
|
||||
|
||||
if (!h264)
|
||||
return FALSE;
|
||||
|
||||
@ -53,24 +56,34 @@ BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT3
|
||||
if (height % 16 != 0)
|
||||
height += 16 - height % 16;
|
||||
|
||||
if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2] || (width != h264->width) ||
|
||||
(height != h264->height) || (stride != h264->iStride[0]))
|
||||
for (x = 0; x < 3; x++)
|
||||
{
|
||||
if (!h264->pYUVData[x] || !h264->pOldYUVData[x])
|
||||
isNull = TRUE;
|
||||
}
|
||||
|
||||
if (isNull || (width != h264->width) || (height != h264->height) ||
|
||||
(stride != h264->iStride[0]))
|
||||
{
|
||||
|
||||
h264->iStride[0] = stride;
|
||||
h264->iStride[1] = (stride + 1) / 2;
|
||||
h264->iStride[2] = (stride + 1) / 2;
|
||||
h264->width = width;
|
||||
h264->height = height;
|
||||
_aligned_free(h264->pYUVData[0]);
|
||||
_aligned_free(h264->pYUVData[1]);
|
||||
_aligned_free(h264->pYUVData[2]);
|
||||
h264->pYUVData[0] = _aligned_malloc(h264->iStride[0] * height * 1ULL, 16);
|
||||
h264->pYUVData[1] = _aligned_malloc(h264->iStride[1] * height * 1ULL, 16);
|
||||
h264->pYUVData[2] = _aligned_malloc(h264->iStride[2] * height * 1ULL, 16);
|
||||
|
||||
if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2])
|
||||
for (x = 0; x < 3; x++)
|
||||
{
|
||||
BYTE* tmp1 = _aligned_recalloc(h264->pYUVData[x], h264->iStride[x], height, 16);
|
||||
BYTE* tmp2 = _aligned_recalloc(h264->pOldYUVData[x], h264->iStride[x], height, 16);
|
||||
if (tmp1)
|
||||
h264->pYUVData[x] = tmp1;
|
||||
if (tmp2)
|
||||
h264->pOldYUVData[x] = tmp2;
|
||||
if (!tmp1 || !tmp2)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -82,7 +95,7 @@ INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize
|
||||
int status;
|
||||
const BYTE* pYUVData[3];
|
||||
|
||||
if (!h264)
|
||||
if (!h264 || h264->Compressor)
|
||||
return -1001;
|
||||
|
||||
status = h264->subsystem->Decompress(h264, pSrcData, SrcSize);
|
||||
@ -103,13 +116,117 @@ INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize
|
||||
return 1;
|
||||
}
|
||||
|
||||
INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
|
||||
UINT32 nSrcWidth, UINT32 nSrcHeight, BYTE** ppDstData, UINT32* pDstSize)
|
||||
static BOOL allocate_h264_metablock(UINT32 QP, RECTANGLE_16* rectangles,
|
||||
RDPGFX_H264_METABLOCK* meta, size_t count)
|
||||
{
|
||||
size_t x;
|
||||
if (!meta)
|
||||
return FALSE;
|
||||
|
||||
meta->regionRects = rectangles;
|
||||
if (count == 0)
|
||||
return TRUE;
|
||||
|
||||
meta->quantQualityVals = calloc(count, sizeof(RDPGFX_H264_QUANT_QUALITY));
|
||||
|
||||
if (!meta->quantQualityVals || !meta->regionRects)
|
||||
return FALSE;
|
||||
meta->numRegionRects = count;
|
||||
for (x = 0; x < count; x++)
|
||||
{
|
||||
RDPGFX_H264_QUANT_QUALITY* cur = &meta->quantQualityVals[x];
|
||||
cur->qp = QP;
|
||||
cur->qualityVal = 100 - QP;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INLINE BOOL diff_tile(const RECTANGLE_16* regionRect, BYTE* pYUVData[3],
|
||||
BYTE* pOldYUVData[3], UINT32 const iStride[3])
|
||||
{
|
||||
size_t size, y;
|
||||
if (!regionRect || !pYUVData || !pOldYUVData || !iStride)
|
||||
return FALSE;
|
||||
size = regionRect->right - regionRect->left;
|
||||
if (regionRect->right > iStride[0])
|
||||
return FALSE;
|
||||
if (regionRect->right / 2 > iStride[1])
|
||||
return FALSE;
|
||||
if (regionRect->right / 2 > iStride[2])
|
||||
return FALSE;
|
||||
|
||||
for (y = regionRect->top; y < regionRect->bottom; y++)
|
||||
{
|
||||
const BYTE* cur0 = &pYUVData[0][y * iStride[0]];
|
||||
const BYTE* cur1 = &pYUVData[1][y * iStride[1]];
|
||||
const BYTE* cur2 = &pYUVData[2][y * iStride[2]];
|
||||
const BYTE* old0 = &pOldYUVData[0][y * iStride[0]];
|
||||
const BYTE* old1 = &pOldYUVData[1][y * iStride[1]];
|
||||
const BYTE* old2 = &pOldYUVData[2][y * iStride[2]];
|
||||
|
||||
if (memcmp(&cur0[regionRect->left], &old0[regionRect->left], size) != 0)
|
||||
return TRUE;
|
||||
if (memcmp(&cur1[regionRect->left / 2], &old1[regionRect->left / 2], size / 2) != 0)
|
||||
return TRUE;
|
||||
if (memcmp(&cur2[regionRect->left / 2], &old2[regionRect->left / 2], size / 2) != 0)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL detect_changes(BOOL firstFrameDone, const UINT32 QP, const RECTANGLE_16* regionRect,
|
||||
BYTE* pYUVData[3], BYTE* pOldYUVData[3], UINT32 const iStride[3],
|
||||
RDPGFX_H264_METABLOCK* meta)
|
||||
{
|
||||
size_t count = 0, wc, hc;
|
||||
RECTANGLE_16* rectangles;
|
||||
|
||||
if (!regionRect || !pYUVData || !pOldYUVData || !iStride || !meta)
|
||||
return FALSE;
|
||||
|
||||
wc = (regionRect->right - regionRect->left) / 64 + 1;
|
||||
hc = (regionRect->bottom - regionRect->top) / 64 + 1;
|
||||
rectangles = calloc(wc * hc, sizeof(RECTANGLE_16));
|
||||
if (!rectangles)
|
||||
return FALSE;
|
||||
if (!firstFrameDone)
|
||||
{
|
||||
rectangles[0] = *regionRect;
|
||||
count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t x, y;
|
||||
for (y = regionRect->top; y < regionRect->bottom; y += 64)
|
||||
{
|
||||
for (x = regionRect->left; x < regionRect->right; x += 64)
|
||||
{
|
||||
RECTANGLE_16 rect;
|
||||
const BYTE* pYUVData[3];
|
||||
rect.left = regionRect->left + x;
|
||||
rect.top = regionRect->top + y;
|
||||
rect.right = MIN(regionRect->left + x + 64, regionRect->right);
|
||||
rect.bottom = MIN(regionRect->top + y + 64, regionRect->bottom);
|
||||
if (diff_tile(&rect, pYUVData, pOldYUVData, iStride))
|
||||
rectangles[count++] = rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!allocate_h264_metablock(QP, rectangles, meta, count))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!h264)
|
||||
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)
|
||||
{
|
||||
size_t x;
|
||||
INT32 rc;
|
||||
BYTE* pYUVData[3];
|
||||
const BYTE* pcYUVData[3];
|
||||
BYTE* pOldYUVData[3];
|
||||
|
||||
if (!h264 || !regionRect || !meta || !h264->Compressor)
|
||||
return -1;
|
||||
|
||||
if (!h264->subsystem->Compress)
|
||||
@ -118,30 +235,58 @@ INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat,
|
||||
if (!avc420_ensure_buffer(h264, nSrcStep, nSrcWidth, nSrcHeight))
|
||||
return -1;
|
||||
|
||||
rect.left = 0;
|
||||
rect.top = 0;
|
||||
rect.right = nSrcWidth;
|
||||
rect.bottom = nSrcHeight;
|
||||
if (h264->encodingBuffer)
|
||||
{
|
||||
for (x = 0; x < 3; x++)
|
||||
{
|
||||
pYUVData[x] = h264->pYUVData[x];
|
||||
pOldYUVData[x] = h264->pOldYUVData[x];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (x = 0; x < 3; x++)
|
||||
{
|
||||
pYUVData[x] = h264->pOldYUVData[x];
|
||||
pOldYUVData[x] = h264->pYUVData[x];
|
||||
}
|
||||
}
|
||||
h264->encodingBuffer = !h264->encodingBuffer;
|
||||
|
||||
if (!yuv420_context_encode(h264->yuv, pSrcData, nSrcStep, SrcFormat, h264->iStride,
|
||||
h264->pYUVData, &rect, 1))
|
||||
if (!yuv420_context_encode(h264->yuv, pSrcData, nSrcStep, SrcFormat, h264->iStride, pYUVData,
|
||||
regionRect, 1))
|
||||
return -1;
|
||||
|
||||
pYUVData[0] = h264->pYUVData[0];
|
||||
pYUVData[1] = h264->pYUVData[1];
|
||||
pYUVData[2] = h264->pYUVData[2];
|
||||
return h264->subsystem->Compress(h264, pYUVData, h264->iStride, ppDstData, pDstSize);
|
||||
if (!detect_changes(h264->firstLumaFrameDone, h264->QP, regionRect, pYUVData, pOldYUVData,
|
||||
h264->iStride, meta))
|
||||
return -1;
|
||||
|
||||
if (meta->numRegionRects == 0)
|
||||
return 0;
|
||||
|
||||
for (x = 0; x < 3; x++)
|
||||
pcYUVData[x] = pYUVData[x];
|
||||
|
||||
rc = h264->subsystem->Compress(h264, pcYUVData, h264->iStride, ppDstData, pDstSize);
|
||||
if (rc >= 0)
|
||||
h264->firstLumaFrameDone = TRUE;
|
||||
return rc;
|
||||
}
|
||||
|
||||
INT32 avc444_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
|
||||
UINT32 nSrcWidth, UINT32 nSrcHeight, BYTE version, BYTE* op, BYTE** ppDstData,
|
||||
UINT32* pDstSize, BYTE** ppAuxDstData, UINT32* pAuxDstSize)
|
||||
UINT32 nSrcWidth, UINT32 nSrcHeight, BYTE version, const RECTANGLE_16* region,
|
||||
BYTE* op, BYTE** ppDstData, UINT32* pDstSize, BYTE** ppAuxDstData,
|
||||
UINT32* pAuxDstSize, RDPGFX_H264_METABLOCK* meta,
|
||||
RDPGFX_H264_METABLOCK* auxMeta)
|
||||
{
|
||||
RECTANGLE_16 rect = { 0 };
|
||||
BYTE* coded;
|
||||
UINT32 codedSize;
|
||||
BYTE** pYUV444Data;
|
||||
BYTE** pOldYUV444Data;
|
||||
BYTE** pYUVData;
|
||||
BYTE** pOldYUVData;
|
||||
|
||||
if (!h264)
|
||||
if (!h264 || !h264->Compressor)
|
||||
return -1;
|
||||
|
||||
if (!h264->subsystem->Compress)
|
||||
@ -153,34 +298,75 @@ INT32 avc444_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat,
|
||||
if (!avc444_ensure_buffer(h264, nSrcHeight))
|
||||
return -1;
|
||||
|
||||
rect.right = nSrcWidth;
|
||||
rect.bottom = nSrcHeight;
|
||||
if (h264->encodingBuffer)
|
||||
{
|
||||
pYUV444Data = h264->pOldYUV444Data;
|
||||
pOldYUV444Data = h264->pYUV444Data;
|
||||
pYUVData = h264->pOldYUVData;
|
||||
pOldYUVData = h264->pYUVData;
|
||||
}
|
||||
else
|
||||
{
|
||||
pYUV444Data = h264->pYUV444Data;
|
||||
pOldYUV444Data = h264->pOldYUV444Data;
|
||||
pYUVData = h264->pYUVData;
|
||||
pOldYUVData = h264->pOldYUVData;
|
||||
}
|
||||
h264->encodingBuffer = !h264->encodingBuffer;
|
||||
|
||||
if (!yuv444_context_encode(h264->yuv, version, pSrcData, nSrcStep, SrcFormat, h264->iStride,
|
||||
h264->pYUV444Data, h264->pYUVData, &rect, 1))
|
||||
pYUV444Data, pYUVData, region, 1))
|
||||
return -1;
|
||||
|
||||
if (!detect_changes(h264->firstLumaFrameDone, h264->QP, region, pYUV444Data, pOldYUV444Data,
|
||||
h264->iStride, meta))
|
||||
return -1;
|
||||
if (!detect_changes(h264->firstChromaFrameDone, h264->QP, region, pYUVData, pOldYUVData,
|
||||
h264->iStride, auxMeta))
|
||||
return -1;
|
||||
|
||||
/* [MS-RDPEGFX] 2.2.4.5 RFX_AVC444_BITMAP_STREAM
|
||||
* LC:
|
||||
* 0 ... Luma & Chroma
|
||||
* 1 ... Luma
|
||||
* 2 ... Chroma
|
||||
*/
|
||||
if ((meta->numRegionRects > 0) && (auxMeta->numRegionRects > 0))
|
||||
*op = 0;
|
||||
else if (meta->numRegionRects > 0)
|
||||
*op = 1;
|
||||
else if (auxMeta->numRegionRects > 0)
|
||||
*op = 2;
|
||||
else
|
||||
{
|
||||
const BYTE* pYUV444Data[3] = { h264->pYUV444Data[0], h264->pYUV444Data[1],
|
||||
h264->pYUV444Data[2] };
|
||||
|
||||
if (h264->subsystem->Compress(h264, pYUV444Data, h264->iStride, &coded, &codedSize) < 0)
|
||||
return -1;
|
||||
WLog_INFO(TAG, "no changes detected for luma or chroma frame");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((*op == 0) || (*op == 1))
|
||||
{
|
||||
const BYTE* pcYUV444Data[3] = { pYUV444Data[0], pYUV444Data[1], pYUV444Data[2] };
|
||||
|
||||
if (h264->subsystem->Compress(h264, pcYUV444Data, h264->iStride, &coded, &codedSize) < 0)
|
||||
return -1;
|
||||
h264->firstLumaFrameDone = TRUE;
|
||||
memcpy(h264->lumaData, coded, codedSize);
|
||||
*ppDstData = h264->lumaData;
|
||||
*pDstSize = codedSize;
|
||||
{
|
||||
const BYTE* pYUVData[3] = { h264->pYUVData[0], h264->pYUVData[1], h264->pYUVData[2] };
|
||||
|
||||
if (h264->subsystem->Compress(h264, pYUVData, h264->iStride, &coded, &codedSize) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((*op == 0) || (*op == 2))
|
||||
{
|
||||
const BYTE* pcYUVData[3] = { pYUVData[0], pYUVData[1], pYUVData[2] };
|
||||
|
||||
if (h264->subsystem->Compress(h264, pcYUVData, h264->iStride, &coded, &codedSize) < 0)
|
||||
return -1;
|
||||
h264->firstChromaFrameDone = TRUE;
|
||||
*ppAuxDstData = coded;
|
||||
*pAuxDstSize = codedSize;
|
||||
*op = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, DWORD nDstHeight)
|
||||
@ -190,6 +376,7 @@ static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, DWORD nDstHeight)
|
||||
UINT32* piDstSize = h264->iYUV444Size;
|
||||
UINT32* piDstStride = h264->iYUV444Stride;
|
||||
BYTE** ppYUVDstData = h264->pYUV444Data;
|
||||
BYTE** ppOldYUVDstData = h264->pOldYUV444Data;
|
||||
const UINT32 pad = nDstHeight % 16;
|
||||
UINT32 padDstHeight = nDstHeight; /* Need alignment to 16x16 blocks */
|
||||
|
||||
@ -200,24 +387,31 @@ static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, DWORD nDstHeight)
|
||||
{
|
||||
for (x = 0; x < 3; x++)
|
||||
{
|
||||
BYTE* tmp1;
|
||||
BYTE* tmp2;
|
||||
piDstStride[x] = piMainStride[0];
|
||||
piDstSize[x] = piDstStride[x] * padDstHeight;
|
||||
_aligned_free(ppYUVDstData[x]);
|
||||
ppYUVDstData[x] = _aligned_malloc(piDstSize[x], 16);
|
||||
|
||||
if (!ppYUVDstData[x])
|
||||
tmp1 = _aligned_recalloc(ppYUVDstData[x], piDstSize[x], 1, 16);
|
||||
if (tmp1)
|
||||
ppYUVDstData[x] = tmp1;
|
||||
tmp2 = _aligned_recalloc(ppOldYUVDstData[x], piDstSize[x], 1, 16);
|
||||
if (tmp2)
|
||||
ppOldYUVDstData[x] = tmp2;
|
||||
if (!tmp1 || !tmp2)
|
||||
goto fail;
|
||||
|
||||
memset(ppYUVDstData[x], 0, piDstSize[x]);
|
||||
}
|
||||
|
||||
_aligned_free(h264->lumaData);
|
||||
h264->lumaData = _aligned_malloc(piDstSize[0] * 4, 16);
|
||||
{
|
||||
BYTE* tmp = _aligned_recalloc(h264->lumaData, piDstSize[0], 4, 16);
|
||||
if (!tmp)
|
||||
goto fail;
|
||||
h264->lumaData = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for (x = 0; x < 3; x++)
|
||||
{
|
||||
if (!ppYUVDstData[x] || (piDstSize[x] == 0) || (piDstStride[x] == 0))
|
||||
if (!ppOldYUVDstData[x] || !ppYUVDstData[x] || (piDstSize[x] == 0) || (piDstStride[x] == 0))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"YUV buffer not initialized! check your decoder settings");
|
||||
@ -230,14 +424,6 @@ static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, DWORD nDstHeight)
|
||||
|
||||
return TRUE;
|
||||
fail:
|
||||
_aligned_free(ppYUVDstData[0]);
|
||||
_aligned_free(ppYUVDstData[1]);
|
||||
_aligned_free(ppYUVDstData[2]);
|
||||
_aligned_free(h264->lumaData);
|
||||
ppYUVDstData[0] = NULL;
|
||||
ppYUVDstData[1] = NULL;
|
||||
ppYUVDstData[2] = NULL;
|
||||
h264->lumaData = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -297,7 +483,7 @@ INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, const RECTANGLE_16* regionR
|
||||
avc444_frame_type chroma =
|
||||
(codecId == RDPGFX_CODECID_AVC444) ? AVC444_CHROMAv1 : AVC444_CHROMAv2;
|
||||
|
||||
if (!h264 || !regionRects || !pSrcData || !pDstData)
|
||||
if (!h264 || !regionRects || !pSrcData || !pDstData || h264->Compressor)
|
||||
return -1001;
|
||||
|
||||
switch (op)
|
||||
@ -487,11 +673,21 @@ void h264_context_free(H264_CONTEXT* h264)
|
||||
{
|
||||
if (h264)
|
||||
{
|
||||
size_t x;
|
||||
h264->subsystem->Uninit(h264);
|
||||
_aligned_free(h264->pYUV444Data[0]);
|
||||
_aligned_free(h264->pYUV444Data[1]);
|
||||
_aligned_free(h264->pYUV444Data[2]);
|
||||
|
||||
for (x = 0; x < 3; x++)
|
||||
{
|
||||
if (h264->Compressor)
|
||||
{
|
||||
_aligned_free(h264->pYUVData[x]);
|
||||
_aligned_free(h264->pOldYUVData[x]);
|
||||
}
|
||||
_aligned_free(h264->pYUV444Data[x]);
|
||||
_aligned_free(h264->pOldYUV444Data[x]);
|
||||
}
|
||||
_aligned_free(h264->lumaData);
|
||||
|
||||
yuv_context_free(h264->yuv);
|
||||
free(h264);
|
||||
}
|
||||
|
@ -191,6 +191,10 @@ static INLINE YUV_PROCESS_WORK_PARAM pool_decode_param(const RECTANGLE_16* rect,
|
||||
|
||||
static BOOL allocate_objects(PTP_WORK** work, void** params, size_t size, UINT32 count)
|
||||
{
|
||||
if (count == 0)
|
||||
return FALSE;
|
||||
|
||||
count *= 2;
|
||||
{
|
||||
PTP_WORK* tmp;
|
||||
PTP_WORK* cur = *work;
|
||||
@ -198,12 +202,14 @@ static BOOL allocate_objects(PTP_WORK** work, void** params, size_t size, UINT32
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
*work = tmp;
|
||||
memset(tmp, 0, sizeof(PTP_WORK*) * count);
|
||||
}
|
||||
{
|
||||
void* cur = *params;
|
||||
void* tmp = realloc(cur, size * count);
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
memset(tmp, 0, size * count);
|
||||
*params = tmp;
|
||||
}
|
||||
return TRUE;
|
||||
@ -224,13 +230,18 @@ static BOOL submit_object(PTP_WORK* work_object, PTP_WORK_CALLBACK cb, const voi
|
||||
}
|
||||
|
||||
static void free_objects(PTP_WORK* work_objects, void* params, UINT32 waitCount)
|
||||
{
|
||||
if (work_objects)
|
||||
{
|
||||
UINT32 i;
|
||||
for (i = 0; i < waitCount; i++)
|
||||
{
|
||||
if (!work_objects[i])
|
||||
continue;
|
||||
WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE);
|
||||
CloseThreadpoolWork(work_objects[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(work_objects);
|
||||
free(params);
|
||||
@ -260,6 +271,17 @@ static BOOL pool_decode(YUV_CONTEXT* context, PTP_WORK_CALLBACK cb, const BYTE*
|
||||
|
||||
/* case where we use threads */
|
||||
nobjects = (context->height + context->heightStep - 1) / context->heightStep;
|
||||
for (x = 0; x < numRegionRects; x++)
|
||||
{
|
||||
const RECTANGLE_16* rect = ®ionRects[x];
|
||||
const UINT32 height = rect->bottom - rect->top;
|
||||
const UINT32 steps = (height + context->heightStep / 2) / context->heightStep;
|
||||
|
||||
if (waitCount + steps >= nobjects)
|
||||
nobjects *= 2;
|
||||
waitCount += steps;
|
||||
}
|
||||
|
||||
if (!allocate_objects(&work_objects, (void**)¶ms, sizeof(YUV_PROCESS_WORK_PARAM), nobjects))
|
||||
goto fail;
|
||||
|
||||
@ -269,14 +291,6 @@ static BOOL pool_decode(YUV_CONTEXT* context, PTP_WORK_CALLBACK cb, const BYTE*
|
||||
const UINT32 height = rect->bottom - rect->top;
|
||||
const UINT32 steps = (height + context->heightStep / 2) / context->heightStep;
|
||||
|
||||
if (waitCount + steps >= nobjects)
|
||||
{
|
||||
nobjects *= 2;
|
||||
if (!allocate_objects(&work_objects, (void**)¶ms, sizeof(YUV_PROCESS_WORK_PARAM),
|
||||
nobjects))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (y = 0; y < steps; y++)
|
||||
{
|
||||
YUV_PROCESS_WORK_PARAM* cur = ¶ms[waitCount];
|
||||
@ -589,6 +603,17 @@ static BOOL pool_encode(YUV_CONTEXT* context, PTP_WORK_CALLBACK cb, const BYTE*
|
||||
|
||||
/* case where we use threads */
|
||||
nobjects = (context->height + context->heightStep - 1) / context->heightStep;
|
||||
for (x = 0; x < numRegionRects; x++)
|
||||
{
|
||||
const RECTANGLE_16* rect = ®ionRects[x];
|
||||
const UINT32 height = rect->bottom - rect->top;
|
||||
const UINT32 steps = (height + context->heightStep / 2) / context->heightStep;
|
||||
|
||||
if (waitCount + steps >= nobjects)
|
||||
nobjects *= 2;
|
||||
waitCount += steps;
|
||||
}
|
||||
|
||||
if (!allocate_objects(&work_objects, (void**)¶ms, sizeof(YUV_ENCODE_WORK_PARAM), nobjects))
|
||||
goto fail;
|
||||
|
||||
@ -598,14 +623,6 @@ static BOOL pool_encode(YUV_CONTEXT* context, PTP_WORK_CALLBACK cb, const BYTE*
|
||||
const UINT32 height = rect->bottom - rect->top;
|
||||
const UINT32 steps = (height + context->heightStep / 2) / context->heightStep;
|
||||
|
||||
if (waitCount + steps >= nobjects)
|
||||
{
|
||||
nobjects *= 2;
|
||||
if (!allocate_objects(&work_objects, (void**)¶ms, sizeof(YUV_ENCODE_WORK_PARAM),
|
||||
nobjects))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (y = 0; y < steps; y++)
|
||||
{
|
||||
RECTANGLE_16 r = *rect;
|
||||
|
@ -436,7 +436,8 @@ static INLINE void ssse3_RGBToYUV420_BGRX_UV(const BYTE* src1, const BYTE* src2,
|
||||
}
|
||||
|
||||
static pstatus_t ssse3_RGBToYUV420_BGRX(const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep,
|
||||
BYTE* pDst[3], UINT32 dstStep[3], const prim_size_t* roi)
|
||||
BYTE* pDst[3], const UINT32 dstStep[3],
|
||||
const prim_size_t* roi)
|
||||
{
|
||||
UINT32 y;
|
||||
const BYTE* argb = pSrc;
|
||||
@ -478,7 +479,7 @@ static pstatus_t ssse3_RGBToYUV420_BGRX(const BYTE* pSrc, UINT32 srcFormat, UINT
|
||||
}
|
||||
|
||||
static pstatus_t ssse3_RGBToYUV420(const BYTE* pSrc, UINT32 srcFormat, UINT32 srcStep,
|
||||
BYTE* pDst[3], UINT32 dstStep[3], const prim_size_t* roi)
|
||||
BYTE* pDst[3], const UINT32 dstStep[3], const prim_size_t* roi)
|
||||
{
|
||||
switch (srcFormat)
|
||||
{
|
||||
|
@ -828,9 +828,9 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
|
||||
|
||||
if (settings->GfxAVC444 || settings->GfxAVC444v2)
|
||||
{
|
||||
RDPGFX_AVC444_BITMAP_STREAM avc444;
|
||||
RECTANGLE_16 regionRect;
|
||||
RDPGFX_H264_QUANT_QUALITY quantQualityVal;
|
||||
INT32 rc;
|
||||
RDPGFX_AVC444_BITMAP_STREAM avc444 = { 0 };
|
||||
RECTANGLE_16 regionRect = { 0 };
|
||||
BYTE version = settings->GfxAVC444v2 ? 2 : 1;
|
||||
|
||||
if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC444) < 0)
|
||||
@ -839,34 +839,33 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (avc444_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight, version,
|
||||
&avc444.LC, &avc444.bitstream[0].data, &avc444.bitstream[0].length,
|
||||
&avc444.bitstream[1].data, &avc444.bitstream[1].length) < 0)
|
||||
regionRect.left = cmd.left;
|
||||
regionRect.top = cmd.top;
|
||||
regionRect.right = cmd.right;
|
||||
regionRect.bottom = cmd.bottom;
|
||||
rc = avc444_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
|
||||
version, ®ionRect, &avc444.LC, &avc444.bitstream[0].data,
|
||||
&avc444.bitstream[0].length, &avc444.bitstream[1].data,
|
||||
&avc444.bitstream[1].length, &avc444.bitstream[0].meta,
|
||||
&avc444.bitstream[1].meta);
|
||||
if (rc < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "avc420_compress failed for avc444");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
regionRect.left = cmd.left;
|
||||
regionRect.top = cmd.top;
|
||||
regionRect.right = cmd.right;
|
||||
regionRect.bottom = cmd.bottom;
|
||||
quantQualityVal.qp = encoder->h264->QP;
|
||||
quantQualityVal.r = 0;
|
||||
quantQualityVal.p = 0;
|
||||
quantQualityVal.qualityVal = 100 - quantQualityVal.qp;
|
||||
avc444.bitstream[0].meta.numRegionRects = 1;
|
||||
avc444.bitstream[0].meta.regionRects = ®ionRect;
|
||||
avc444.bitstream[0].meta.quantQualityVals = &quantQualityVal;
|
||||
avc444.bitstream[1].meta.numRegionRects = 1;
|
||||
avc444.bitstream[1].meta.regionRects = ®ionRect;
|
||||
avc444.bitstream[1].meta.quantQualityVals = &quantQualityVal;
|
||||
/* rc > 0 means new data */
|
||||
if (rc > 0)
|
||||
{
|
||||
avc444.cbAvc420EncodedBitstream1 = rdpgfx_estimate_h264_avc420(&avc444.bitstream[0]);
|
||||
cmd.codecId = settings->GfxAVC444v2 ? RDPGFX_CODECID_AVC444v2 : RDPGFX_CODECID_AVC444;
|
||||
cmd.extra = (void*)&avc444;
|
||||
IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
|
||||
&cmdend);
|
||||
}
|
||||
|
||||
free_h264_metablock(&avc444.bitstream[0].meta);
|
||||
free_h264_metablock(&avc444.bitstream[1].meta);
|
||||
if (error)
|
||||
{
|
||||
WLog_ERR(TAG, "SurfaceFrameCommand failed with error %" PRIu32 "", error);
|
||||
@ -875,9 +874,9 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
|
||||
}
|
||||
else if (settings->GfxH264)
|
||||
{
|
||||
RDPGFX_AVC420_BITMAP_STREAM avc420;
|
||||
INT32 rc;
|
||||
RDPGFX_AVC420_BITMAP_STREAM avc420 = { 0 };
|
||||
RECTANGLE_16 regionRect;
|
||||
RDPGFX_H264_QUANT_QUALITY quantQualityVal;
|
||||
|
||||
if (shadow_encoder_prepare(encoder, FREERDP_CODEC_AVC420) < 0)
|
||||
{
|
||||
@ -885,28 +884,28 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (avc420_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
|
||||
&avc420.data, &avc420.length) < 0)
|
||||
regionRect.left = cmd.left;
|
||||
regionRect.top = cmd.top;
|
||||
regionRect.right = cmd.right;
|
||||
regionRect.bottom = cmd.bottom;
|
||||
rc = avc420_compress(encoder->h264, pSrcData, cmd.format, nSrcStep, nWidth, nHeight,
|
||||
®ionRect, &avc420.data, &avc420.length, &avc420.meta);
|
||||
if (rc < 0)
|
||||
{
|
||||
WLog_ERR(TAG, "avc420_compress failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* rc > 0 means new data */
|
||||
if (rc > 0)
|
||||
{
|
||||
cmd.codecId = RDPGFX_CODECID_AVC420;
|
||||
cmd.extra = (void*)&avc420;
|
||||
regionRect.left = cmd.left;
|
||||
regionRect.top = cmd.top;
|
||||
regionRect.right = cmd.right;
|
||||
regionRect.bottom = cmd.bottom;
|
||||
quantQualityVal.qp = encoder->h264->QP;
|
||||
quantQualityVal.r = 0;
|
||||
quantQualityVal.p = 0;
|
||||
quantQualityVal.qualityVal = 100 - quantQualityVal.qp;
|
||||
avc420.meta.numRegionRects = 1;
|
||||
avc420.meta.regionRects = ®ionRect;
|
||||
avc420.meta.quantQualityVals = &quantQualityVal;
|
||||
|
||||
IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
|
||||
&cmdend);
|
||||
}
|
||||
free_h264_metablock(&avc420.meta);
|
||||
|
||||
if (error)
|
||||
{
|
||||
|
@ -160,12 +160,19 @@ void* _aligned_offset_realloc(void* memblock, size_t size, size_t alignment, siz
|
||||
return newMemblock;
|
||||
}
|
||||
|
||||
static INLINE size_t cMIN(size_t a, size_t b)
|
||||
{
|
||||
if (a > b)
|
||||
return b;
|
||||
return a;
|
||||
}
|
||||
|
||||
void* _aligned_offset_recalloc(void* memblock, size_t num, size_t size, size_t alignment,
|
||||
size_t offset)
|
||||
{
|
||||
void* newMemblock;
|
||||
WINPR_ALIGNED_MEM* pMem;
|
||||
WINPR_ALIGNED_MEM* pNewMem;
|
||||
void* newMemblock = NULL;
|
||||
WINPR_ALIGNED_MEM* pMem = NULL;
|
||||
WINPR_ALIGNED_MEM* pNewMem = NULL;
|
||||
|
||||
if (!memblock)
|
||||
{
|
||||
@ -186,22 +193,24 @@ void* _aligned_offset_recalloc(void* memblock, size_t num, size_t size, size_t a
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"_aligned_offset_recalloc: memory block was not allocated by _aligned_malloc!");
|
||||
return NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
_aligned_free(memblock);
|
||||
return NULL;
|
||||
}
|
||||
goto fail;
|
||||
|
||||
newMemblock = _aligned_offset_malloc(size * num, alignment, offset);
|
||||
|
||||
if (!newMemblock)
|
||||
return NULL;
|
||||
goto fail;
|
||||
|
||||
pNewMem = WINPR_ALIGNED_MEM_STRUCT_FROM_PTR(newMemblock);
|
||||
ZeroMemory(newMemblock, pNewMem->size);
|
||||
{
|
||||
const size_t size = cMIN(pMem->size, pNewMem->size);
|
||||
memcpy(newMemblock, pMem->base_addr, size);
|
||||
ZeroMemory(newMemblock + size, pNewMem->size - size);
|
||||
}
|
||||
fail:
|
||||
_aligned_free(memblock);
|
||||
return newMemblock;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user