Share via


Extract Rectangle Information from RemoteFX Display Data (Compact 7)

3/12/2014

In full-screen mode, the ESCAPE_COPY2_BMP escape sequence is not sent to the display driver. Therefore, the display driver must extract the destination rectangle information from the RemoteFX-encoded display data. The destination rectangle information is present before the start of each frame in the RemoteFX-encoded data stream. The destination rectangle information is also present before the sync message, which is the first message in a RemoteFX-encoded data stream.

The following code example demonstrates how the destination rectangle information can be extracted from the RemoteFX-encoded display data.

Important

For readability, the following code example does not contain security or error handling. Do not use the following code in a production environment.

const int WF_MAGIC = 0xCACCACCA;

enum cmdType
{
    CMDTYPE_FRAME_MARKER = 0x04,
    CMDTYPE_STREAM_SURFACE_BITS = 0x06

};

enum BlockType
{
    WBT_SYNC = 0xCCC0,
    WBT_CODEC_VERSIONS = 0xCCC1, 
    WBT_CHANNELS = 0xCCC2,
    WBT_CONTEXT = 0xCCC3,
    WBT_FRAME_BEG = 0xCCC4,
    WBT_FRAME_END = 0xCCC5,
    WBT_REGION = 0xCCC6,
    WBT_EXTENSION = 0xCCC7,
    WBT_LAST = 0xCCC8
};

typedef struct tagTS_DEST_RECT
{
    UINT16  destLeft;
    UINT16  destTop;
    UINT16  destRight;
    UINT16  destBottom;
}TS_DEST_RECT, *PTS_DEST_RECT;

typedef struct tagTS_BITMAP_DATA_EX
{
    UINT8     Bpp;
    UINT8     reserved1;
    UINT8     reserved2;
    UINT8     CodecID; 
    UINT16    Width;
    UINT16    Height;
    UINT32    bitmapDataLength;
}TS_BITMAP_DATA_EX , *PTS_BITMAP_DATA_EX;

typedef struct tagTS_SURFCMD_SET_SURF_BITS
{
    UINT16                 CmdType;
    TS_DEST_RECT           destRect;
    TS_BITMAP_DATA_EX      bitmapHeader;
} TS_SURFCMD_SET_SURF_BITS;

typedef struct TAGTS_RFX_BLOCKT
{
    USHORT      blockType;        
    UINT        blockLen;    
} TS_RFX_BLOCKT;

typedef struct TagTS_RFX_SYNC
{
    TS_RFX_BLOCKT block;
    UINT          magic;   
    USHORT        version;
} TS_RFX_SYNC;

typedef struct TagTS_RFX_FRAME_BEGIN
{
    TS_RFX_BLOCKT block;
    BYTE          codecId;          
    BYTE          channelId; 
    UINT          frameIdx;   
    USHORT        numRegions;
} TS_RFX_FRAME_BEGIN;

typedef struct TagTS_RFX_CHANNELS
{
    TS_RFX_BLOCKT block;
    BYTE          numChannels;          
    BYTE          channelId; 
    USHORT        width;   
    USHORT        height;
} TS_RFX_CHANNELS;

// The function GetDestRectangle fills in the pDestFrame structure from 
// destination rectangle information.
void GetDestRectangle( BYTE *mDataBuf)
{
    BYTE *dataBuf = mDataBuf;
    dataBuf = dataBuf - sizeof(TS_SURFCMD_SET_SURF_BITS) +  sizeof(short);
    PTS_DEST_RECT Rect =(PTS_DEST_RECT)(dataBuf);                   
    pDestFrame->left = Rect->destLeft; 
    pDestFrame->top = Rect->destTop; 
    pDestFrame->right = Rect->destRight;
    pDestFrame->bottom = Rect->destBottom;
}

// The function ScanSyncFrameBeginBlock extracts destination rectangle information
// present before the start of each Frame. For the first message in any encoded
// stream, this information is present before sync message.
void ScanSyncFrameBeginBlock(BYTE *mDataBuf )
{
    BYTE *dataBuf = mDataBuf;    
    for (int i=0; 
        (*dataBuf != CMDTYPE_STREAM_SURFACE_BITS)  && 
        (*(dataBuf - 2* sizeof(int)) != CMDTYPE_FRAME_MARKER); i++,dataBuf--)
    {
        TS_RFX_BLOCKT *block = (TS_RFX_BLOCKT*)dataBuf;
        switch (block->blockType)
        {
        case WBT_SYNC:
            { 
                TS_RFX_SYNC *ss = (TS_RFX_SYNC*)dataBuf;
                if (ss->block.blockType == WBT_SYNC && 
                    ss->magic == WF_MAGIC)
                {       
                    GetDestRectangle(dataBuf);     
                }

            }        
            break;

        case WBT_FRAME_BEG:
            {
                TS_RFX_FRAME_BEGIN *fb = (TS_RFX_FRAME_BEGIN*)dataBuf;
                BYTE  *mBuf  = dataBuf - sizeof (TS_RFX_CHANNELS);
                TS_RFX_CHANNELS *ch  =  (TS_RFX_CHANNELS*)mBuf;
                if (fb->block.blockType == WBT_FRAME_BEG  && 
                    ch->block.blockType != WBT_CHANNELS )
                {
                    GetDestRectangle(dataBuf);
                } 
            }
            break;
        }
    }
}
// The _cOutRects and _pOutRects out params of decode call provide the number
// of rects and co-ordinates of each rect, for example, _pOutRects can 
// be 0,0, 34, 26. To calculate the dirty, or changed, region after decoding is 
// done, combine the decoder output with the destination rectangle information as
// follows to place the decoded bitmap on the screen.

   for (int i = 0; i < _cOutRects; i++)
   { 
       TS_GFX_RECT DirtyRect = {
            pDestFrame->left + _pOutRects-> llX,
            pDestFrame->top + _pOutRects-> llY,
            pDestFrame->left + _pOutRects-> urX,
            pDestFrame->top + _pOutRects-> urY,
        };
    }

See Also

Concepts

Implement a RemoteFX Display Driver