Share via


ESCAPE_DEC3 Code Example (Compact 7)

3/12/2014

The ESCAPE_DEC3 escape sequence offloads the RemoteFX display data to the specialized hardware decoder for decoding and optionally, transfers decoded data back to system memory. The decoded data is handled in hardware, such as in video memory, because the data is no longer in system memory. We do not recommend the option of transferring decoded data back to system memory because the memory transfer causes slower performance.

The following code example shows the structure declarations that are required for the ESCAPE_DEC3 escape sequence.

Important

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

#define ESCAPE_DEC3                         (ESCAPE_CODE_BEGIN+1)

struct ct_rect
{
    LONG left;
    LONG top;
    LONG right;
    LONG bottom;
};
typedef struct ct_rect CtRect;

struct Rect 
{
   short llX;
   short llY;
   short urX;
   short urY;
};

typedef struct
{
    int size;
    BYTE buffer;
}
Buffer1D;

struct esc_dec3_in
{
    struct _hdr     hdr;
    UCHAR*          comp_data;
    ULONG           comp_data_size;
    struct ct_rect* rects;
    ULONG           rect_size;
    UCHAR*          uncomp_data;
    ULONG           uncomp_data_size;
};

struct esc_dec3_out
{
    struct dec3_out ioctl_dec3_out;
    ULONG           channelId;
    ULONG           nBytesConsumed;
};

struct _IndexBuffer 
{ 
    // const: 0xABCDDCB1
    ULONG   marker; 
    ULONG   width;          
    ULONG   height;  
    PVOID   tileset;
    PVOID*  tileBuffer;
    PULONG  tileBufferLength;
}

typedef struct tagTS_GFX_RECT {
    LONG left;
    LONG top;
    LONG right;
    LONG bottom;
    } TS_GFX_RECT, *PTS_GFX_RECT;

// Refer to the RemoteFX protocol specification for more details related to the
// following structures.
typedef struct TagTS_RFX_CODEC_QUANT
{
    // Level-3 quantization factor.
    BYTE LL3 : 4; 
    BYTE LH3 : 4;
    BYTE HL3 : 4;
    BYTE HH3 : 4; 

    // Level-2 quantization factor.
    BYTE LH2 : 4; 
    BYTE HL2 : 4;
    BYTE HH2 : 4; 

    // Level-1 quantization factor. 
    BYTE LH1 : 4; 
    BYTE HL1 : 4;
    BYTE HH1 : 4;
}
TS_RFX_CODEC_QUANT;

typedef struct TagTS_RFX_TILE
{
    // H/w Tile Marker:0x90ff    
    USHORT      marker; 

    // 0xa 
    USHORT      size 

    // The X-index of the encoded tile in the screen tile grid. 
    BYTE        xIdx;    

    // The Y-index of the encoded tile in the screen tile grid.
    BYTE        yIdx;    

    // Specifies the size, in bytes, of the Y-Data field of YUVData.
    USHORT      YLen;    

    // Specifies the size, in bytes, of the U-Data field of YUVData. 
    USHORT      ULen;    

    // Specifies the size, in bytes, of the V-Data field of YUVData. 
    USHORT      VLen;        

    // The start of the encoded data for the YUV-component of the tile. 
    BYTE        YUVData[1]; 
} TS_RFX_TILE;

typedef struct TagTS_RFX_TILESET  
{
    // Block Type WBT_EXTENSION: 0xCCC7      
    USHORT                 blockType;  
    UINT                   blockLen;         

    // const: 1      
    BYTE                   codecId;    
    BYTE                   channelId;        

    // 0xCAC2       
    USHORT                 subtype;    
    USHORT                 idx;                 
    USHORT                 lt : 1;
    USHORT                 flags : 3;
    USHORT                 cct : 2;
    USHORT                 xft : 4;   
    USHORT                 et : 4;   
    USHORT                 qt : 2;   
    BYTE                   numQuant;
    BYTE                   tileSize;
    USHORT                 numTiles;
    ULONG                  tilesDataSize;
    TS_RFX_CODEC_QUANT     quantVals;
    TS_RFX_TILE            tiles[1];        
} TS_RFX_TILESET;

The following code example shows how the ESCAPE_DEC3 sequence is implemented in a display driver. The esc_dec3 function validates the escape parameters and the escape header received from the RDP client to ensure that the input buffer is from a trusted source.

#define OUTRECTS_BUFFER_SIZE_DFLT 128
// Global variable declaration
       
Buffer1D _OutBuf;
Rect     *_pOutRects;
int      _cOutRects;
int     _cOutRectsSize;    
int      Width;
int      Height; 
int      TileSize;

PTS_GFX_RECT pDestFrame;

BOOL esc_dec3(
                 SURFOBJ*    pso,
                 ULONG       iEsc,
                 ULONG       cjIn,
                 PVOID       pvIn,
                 ULONG       cjOut,
                 PVOID       pvOut
                 )
{
        struct esc_dec3_in*   p_in                  = NULL;
        struct esc_dec3_out*  p_out                 = NULL;
        struct _IndexBuffer*  _InBuf                = NULL;
        struct ct_rect* rects                       = NULL;
        BOOL                  status                = FALSE;
        ULONG                 bytesConsumed         = 0;
        int nChannelID;
        int cbConsumed = 0;

        do {
                if (!pso)                        
                {
                        break;
                }
                if (
                        (!pvIn)
                        ||
                        (cjIn != sizeof(*p_in)))
                {
                        break;
                }
                p_in = (struct esc_dec3_in*)pvIn;

                if (
                        (p_in->hdr.code  != iEsc)
                        ||
                        (p_in->hdr.magic != ESCAPE_MAGIN_IN)
                        ||
                        (p_in->hdr.size != sizeof(*p_in)))
                {
                        break;
                }

                if (
                        (!pvOut)
                        ||
                        (cjOut != sizeof(*p_out)))
                {
                        break;
                }
                p_out = (struct esc_dec3_out*)pvOut;

                Buffer1D InBuf;

                _InBuf = (struct _IndexBuffer*)p_in->comp_data;

                p_out->nBytesConsumed   = p_in->comp_data_size;
                p_out->ioctl_dec3_out.cx = _InBuf->width;
                p_out->ioctl_dec3_out.cy = _InBuf->height;
                //During initialization, allocate memory as shown below
                pDestFrame =  (PTS_GFX_RECT)malloc(sizeof PTS_GFX_RECT);
                pDestFrame->left =0; 
                pDestFrame->top  =0; 
                pDestFrame->right =0; 
                pDestFrame->bottom=0;

                TS_RFX_TILESET *tileSet = reinterpret_cast<TS_RFX_TILESET*>(_InBuf->tileset);
                // Call ScanSyncFrameBeginBlock function only when registry 
                // FullScreenRFXonly is set.
                // Refer to the Full Screen Mode section for more details.
                ScanSyncFrameBeginBlock((BYTE * )_InBuf->tileset);
                InBuf.buffer = (BYTE )_InBuf->tileset;
                InBuf.size = tileSet->tilesDataSize;
                _pOutRects = (Rect *)malloc(OUTRECTS_BUFFER_SIZE_DFLT * sizeof(Rect));
                _cOutRectsSize = OUTRECTS_BUFFER_SIZE_DFLT;
                Width = _InBuf->width;
                Height = _InBuf->height;
                TileSize = tileSet->tileSize;
                
                for(ULONG i=0; i< tileSet->numTiles; i++)
                {           
                        BYTE *buf = (BYTE*)_InBuf->tileBuffer[i];                        
                        TS_RFX_TILE *pTile =reinterpret_cast<TS_RFX_TILE*>(buf);           
                        int xIdx =  pTile->xIdx;
                        int yIdx =  pTile->yIdx;

                        int lftX = xIdx * TileSize;
                        int lftY = yIdx * TileSize;
                        int rgtX = lftX + TileSize;
                        int rgtY = lftY + TileSize;

                        p_in->rects[i].left = lftX;
                        p_in->rects[i].top =  lftY;
                        p_in->rects[i].right = rgtX;
                        p_in->rects[i].bottom = rgtY;
                }
                // Allocate buffer for the rectangle list returned by the decoder
                _OutBuf.size = Width * Height * 32 / 8;
                _OutBuf.buffer = BYTE(malloc(_OutBuf.size));
                Buffer1D *pOutBuf = (_OutBuf.buffer) ? &_OutBuf : NULL;
//TO DO: The encoded data will be decoded using the specialized hardware decoder 
//such as ASIC or DSP. The Decode function below needs to be implemented by the 
//decoder driver, which will interface with specialized hardware.

//The decoder driver will drive the decoding process, off-loading the data to 
//specialized hardware. It communicates with the hardware through the display 
//driver interface and transfers compressed tiles into the decoder. 
                Decode(InBuf, _cOutRectsSize, _pOutRects, _cOutRects, cbConsumed,
                        nChannelID, Width, Height, pOutBuf);

                p_out->ioctl_dec3_out.rect_count = tileSet->numTiles;
                status = TRUE;

        } while (0);
        return status;
}

The encoded data is decoded by using a specialized hardware decoder, such as ASIC or a DSP. The Decode function in the previous example needs to be implemented by a decoder driver, which interfaces with specialized hardware. The decoder driver drives the decoding process, off-loading the data to specialized hardware. The decoder driver communicates with the hardware through the display driver interface and transfers compressed tiles into the decoder. DMA is recommended to transfer the decoded data in video memory without overloading the processor. If you do not use DMA, the processor copies all the data from the source to the destination, making the processor unavailable for other tasks.

See Also

Concepts

Implement a RemoteFX Display Driver