video, geometry: fixed geometry handling

It was not working when moving the video window.
This commit is contained in:
David Fort 2018-02-07 17:13:14 +01:00
parent b8e3b232de
commit 73bef4ca23
3 changed files with 82 additions and 28 deletions

View File

@ -27,6 +27,7 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/interlocked.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include <winpr/cmdline.h>
@ -82,8 +83,19 @@ static BOOL mappedGeometryKeyCompare(UINT64 *g1, UINT64 *g2)
return *g1 == *g2;
}
static void mappedGeometryFree(MAPPED_GEOMETRY *g)
void mappedGeometryRef(MAPPED_GEOMETRY *g)
{
InterlockedIncrement(&g->refCounter);
}
void mappedGeometryUnref(MAPPED_GEOMETRY *g)
{
if (InterlockedDecrement(&g->refCounter))
return;
g->MappedGeometryUpdate = NULL;
g->MappedGeometryClear = NULL;
g->custom = NULL;
free(g->geometry.rects);
free(g);
}
@ -214,7 +226,8 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s)
if (mappedGeometry->MappedGeometryClear && !mappedGeometry->MappedGeometryClear(mappedGeometry))
return ERROR_INTERNAL_ERROR;
HashTable_Remove(context->geometries, &id);
if (!HashTable_Remove(context->geometries, &id))
WLog_ERR(TAG, "geometry not removed from geometries");
}
else if (updateType == GEOMETRY_UPDATE)
{
@ -228,6 +241,7 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s)
if (!mappedGeometry)
return CHANNEL_RC_NO_MEMORY;
mappedGeometry->refCounter = 1;
mappedGeometry->mappingId = id;
if (HashTable_Add(context->geometries, &(mappedGeometry->mappingId), mappedGeometry) < 0)
@ -292,7 +306,10 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s)
}
}
else
{
WLog_ERR(TAG, "unknown updateType=%"PRIu32"", updateType);
ret = CHANNEL_RC_OK;
}
return ret;
@ -442,7 +459,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
context->geometries = HashTable_New(FALSE);
context->geometries->hash = (HASH_TABLE_HASH_FN)mappedGeometryHash;
context->geometries->keyCompare = (HASH_TABLE_KEY_COMPARE_FN)mappedGeometryKeyCompare;
context->geometries->valueFree = (HASH_TABLE_VALUE_FREE_FN)mappedGeometryFree;
context->geometries->valueFree = (HASH_TABLE_VALUE_FREE_FN)mappedGeometryUnref;
context->handle = (void*) geometry;
geometry->iface.pInterface = (void*) context;

View File

@ -112,11 +112,13 @@ struct _VideoFrame
{
UINT64 publishTime;
UINT64 hnsDuration;
UINT32 x, y, w, h;
MAPPED_GEOMETRY *geometry;
UINT32 w, h;
BYTE *surfaceData;
PresentationContext *presentation;
};
/** @brief */
struct _PresentationContext
{
VideoClientContext *video;
@ -197,7 +199,7 @@ VideoClientContextPriv *VideoClientContextPriv_new(VideoClientContext *video)
goto error_surfacePool;
}
if (!InitializeCriticalSectionAndSpinCount(&ret->framesLock, 4000))
if (!InitializeCriticalSectionAndSpinCount(&ret->framesLock, 4 * 1000))
{
WLog_ERR(TAG, "unable to initialize frames lock");
goto error_spinlock;
@ -286,30 +288,34 @@ error_h264:
}
static void PresentationContext_unref(PresentationContext *c)
static void PresentationContext_unref(PresentationContext *presentation)
{
VideoClientContextPriv *priv;
MAPPED_GEOMETRY *geometry;
if (!c)
if (!presentation)
return;
if (InterlockedDecrement(&c->refCounter) != 0)
if (InterlockedDecrement(&presentation->refCounter) != 0)
return;
priv = c->video->priv;
if (c->geometry)
geometry = presentation->geometry;
if (geometry)
{
c->geometry->MappedGeometryUpdate = NULL;
c->geometry->MappedGeometryClear = NULL;
c->geometry->custom = NULL;
geometry->MappedGeometryUpdate = NULL;
geometry->MappedGeometryClear = NULL;
geometry->custom = NULL;
mappedGeometryUnref(geometry);
}
h264_context_free(c->h264);
Stream_Free(c->currentSample, TRUE);
c->video->deleteSurface(c->video, c->surface);
BufferPool_Return(priv->surfacePool, c->surfaceData);
yuv_context_free(c->yuv);
free(c);
priv = presentation->video->priv;
h264_context_free(presentation->h264);
Stream_Free(presentation->currentSample, TRUE);
presentation->video->deleteSurface(presentation->video, presentation->surface);
BufferPool_Return(priv->surfacePool, presentation->surfaceData);
yuv_context_free(presentation->yuv);
free(presentation);
}
@ -317,8 +323,9 @@ static void VideoFrame_free(VideoFrame **pframe)
{
VideoFrame *frame = *pframe;
PresentationContext_unref(frame->presentation);
mappedGeometryUnref(frame->geometry);
BufferPool_Return(frame->presentation->video->priv->surfacePool, frame->surfaceData);
PresentationContext_unref(frame->presentation);
free(frame);
*pframe = NULL;
}
@ -374,7 +381,21 @@ static UINT video_control_send_presentation_response(VideoClientContext *context
static BOOL video_onMappedGeometryUpdate(MAPPED_GEOMETRY *geometry)
{
WLog_DBG(TAG, "geometry updated");
PresentationContext *presentation = (PresentationContext *)geometry->custom;
RDP_RECT *r = &geometry->geometry.boundingRect;
WLog_DBG(TAG, "geometry updated topGeom=(%d,%d-%dx%d) geom=(%d,%d-%dx%d) rects=(%d,%d-%dx%d)",
geometry->topLevelLeft, geometry->topLevelTop,
geometry->topLevelRight - geometry->topLevelLeft, geometry->topLevelBottom - geometry->topLevelTop,
geometry->left, geometry->top,
geometry->right - geometry->left, geometry->bottom - geometry->top,
r->x, r->y, r->width, r->height
);
presentation->surface->x = geometry->topLevelLeft + geometry->left + r->x;
presentation->surface->y = geometry->topLevelTop + geometry->top + r->y;
return TRUE;
}
@ -382,6 +403,7 @@ static BOOL video_onMappedGeometryClear(MAPPED_GEOMETRY *geometry)
{
PresentationContext *presentation = (PresentationContext *)geometry->custom;
mappedGeometryUnref(presentation->geometry);
presentation->geometry = NULL;
return TRUE;
}
@ -442,9 +464,11 @@ static UINT video_PresentationRequest(VideoClientContext* video, TSMM_PRESENTATI
return CHANNEL_RC_NO_MEMORY;
}
mappedGeometryRef(geom);
presentation->geometry = geom;
priv->currentPresentation = presentation;
presentation->video = video;
presentation->geometry = geom;
presentation->SourceWidth = req->SourceWidth;
presentation->SourceHeight = req->SourceHeight;
presentation->ScaledWidth = req->ScaledWidth;
@ -629,7 +653,6 @@ static void video_timer(VideoClientContext *video, UINT64 now)
if (frame)
{
/* free skipped frame */
WLog_DBG(TAG, "dropping frame @%"PRIu64, frame->publishTime);
priv->droppedFrames++;
VideoFrame_free(&frame);
@ -650,9 +673,7 @@ static void video_timer(VideoClientContext *video, UINT64 now)
video->showSurface(video, presentation->surface);
PresentationContext_unref(presentation);
BufferPool_Return(priv->surfacePool, frame->surfaceData);
free(frame);
VideoFrame_free(&frame);
treat_feedback:
if (priv->nextFeedbackTime < now)
@ -823,11 +844,11 @@ static UINT video_VideoData(VideoClientContext* context, TSMM_VIDEO_DATA *data)
WLog_ERR(TAG, "unable to create frame");
return CHANNEL_RC_NO_MEMORY;
}
mappedGeometryRef(geom);
frame->presentation = presentation;
frame->publishTime = presentation->lastPublishTime;
frame->x = geom->topLevelLeft + geom->left + geom->geometry.boundingRect.x;
frame->y = geom->topLevelTop + geom->top + geom->geometry.boundingRect.y;
frame->geometry = geom;
frame->w = presentation->SourceWidth;
frame->h = presentation->SourceHeight;
@ -835,6 +856,7 @@ static UINT video_VideoData(VideoClientContext* context, TSMM_VIDEO_DATA *data)
if (!frame->surfaceData)
{
WLog_ERR(TAG, "unable to allocate frame data");
mappedGeometryUnref(geom);
free(frame);
return CHANNEL_RC_NO_MEMORY;
}
@ -843,6 +865,7 @@ static UINT video_VideoData(VideoClientContext* context, TSMM_VIDEO_DATA *data)
{
WLog_ERR(TAG, "error during YUV->RGB conversion");
BufferPool_Return(priv->surfacePool, frame->surfaceData);
mappedGeometryUnref(geom);
free(frame);
return CHANNEL_RC_NO_MEMORY;
}

View File

@ -36,6 +36,7 @@ typedef BOOL (*pcMappedGeometryClear)(MAPPED_GEOMETRY *geometry);
/** @brief a geometry record tracked by the geometry channel */
struct _MAPPED_GEOMETRY
{
volatile LONG refCounter;
UINT64 mappingId;
UINT64 topLevelId;
INT32 left, top, right, bottom;
@ -47,6 +48,7 @@ struct _MAPPED_GEOMETRY
pcMappedGeometryClear MappedGeometryClear;
};
/** @brief the geometry context for client channel */
struct _geometry_client_context
{
@ -57,5 +59,17 @@ struct _geometry_client_context
pcMappedGeometryAdded MappedGeometryAdded;
};
#ifdef __cplusplus
extern "C"
#endif
void mappedGeometryRef(MAPPED_GEOMETRY *g);
void mappedGeometryUnref(MAPPED_GEOMETRY *g);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_CHANNELS_CLIENT_GEOMETRY_H */