void test_decode(void) { RFX_CONTEXT * context; unsigned char * decode_buffer; context = rfx_context_new(); context->mode = RLGR3; rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_RGB); decode_buffer = rfx_decode_rgb(context, y_data, sizeof(y_data), test_quantization_values, cb_data, sizeof(cb_data), test_quantization_values, cr_data, sizeof(cr_data), test_quantization_values); rfx_context_free(context); /* Dump a .ppm image. */ static int frame_id = 0; char buf[100]; FILE * fp; snprintf(buf, sizeof(buf), "/tmp/FreeRDP_Frame_%d.ppm", frame_id); fp = fopen(buf, "wb"); fwrite("P6\n", 1, 3, fp); fwrite("64 64\n", 1, 6, fp); fwrite("255\n", 1, 4, fp); fwrite(decode_buffer, 1, 4096 * 3, fp); fflush(fp); fclose(fp); frame_id++; free(decode_buffer); }
void test_decode(void) { RFX_CONTEXT* context; BYTE decode_buffer[4096 * 3]; STREAM* s; s = stream_new(sizeof(y_data) + sizeof(cb_data) + sizeof(cr_data)); stream_write(s, y_data, sizeof(y_data)); stream_write(s, cb_data, sizeof(cb_data)); stream_write(s, cr_data, sizeof(cr_data)); stream_set_pos(s, 0); context = rfx_context_new(); context->mode = RLGR3; rfx_context_set_pixel_format(context, RDP_PIXEL_FORMAT_R8G8B8); rfx_decode_rgb(context, s, sizeof(y_data), test_quantization_values, sizeof(cb_data), test_quantization_values, sizeof(cr_data), test_quantization_values, decode_buffer); rfx_context_free(context); stream_free(s); dump_ppm_image(decode_buffer); }
static void rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, STREAM* s) { BYTE quantIdxY; BYTE quantIdxCb; BYTE quantIdxCr; UINT16 xIdx, yIdx; UINT16 YLen, CbLen, CrLen; /* RFX_TILE */ stream_read_BYTE(s, quantIdxY); /* quantIdxY (1 byte) */ stream_read_BYTE(s, quantIdxCb); /* quantIdxCb (1 byte) */ stream_read_BYTE(s, quantIdxCr); /* quantIdxCr (1 byte) */ stream_read_UINT16(s, xIdx); /* xIdx (2 bytes) */ stream_read_UINT16(s, yIdx); /* yIdx (2 bytes) */ stream_read_UINT16(s, YLen); /* YLen (2 bytes) */ stream_read_UINT16(s, CbLen); /* CbLen (2 bytes) */ stream_read_UINT16(s, CrLen); /* CrLen (2 bytes) */ DEBUG_RFX("quantIdxY:%d quantIdxCb:%d quantIdxCr:%d xIdx:%d yIdx:%d YLen:%d CbLen:%d CrLen:%d", quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx, YLen, CbLen, CrLen); tile->x = xIdx * 64; tile->y = yIdx * 64; rfx_decode_rgb(context, s, YLen, context->quants + (quantIdxY * 10), CbLen, context->quants + (quantIdxCb * 10), CrLen, context->quants + (quantIdxCr * 10), tile->data); }
void test_decode(void) { RFX_CONTEXT * context; uint8 decode_buffer[4096 * 3]; context = rfx_context_new(); context->mode = RLGR3; rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_RGB); rfx_decode_rgb(context, y_data, sizeof(y_data), test_quantization_values, cb_data, sizeof(cb_data), test_quantization_values, cr_data, sizeof(cr_data), test_quantization_values, decode_buffer); rfx_context_free(context); dump_ppm_image(decode_buffer); }
void test_encode(void) { RFX_CONTEXT* context; STREAM* enc_stream; int y_size, cb_size, cr_size; int i; BYTE decode_buffer[4096 * 3]; rgb_data = (BYTE *) malloc(64 * 64 * 3); for (i = 0; i < 64; i++) memcpy(rgb_data + i * 64 * 3, rgb_scanline_data, 64 * 3); //freerdp_hexdump(rgb_data, 64 * 64 * 3); enc_stream = stream_new(65536); stream_clear(enc_stream); context = rfx_context_new(); context->mode = RLGR3; rfx_context_set_pixel_format(context, RDP_PIXEL_FORMAT_R8G8B8); rfx_encode_rgb(context, rgb_data, 64, 64, 64 * 3, test_quantization_values, test_quantization_values, test_quantization_values, enc_stream, &y_size, &cb_size, &cr_size); //dump_buffer(context->priv->cb_g_buffer, 4096); /*printf("*** Y ***\n"); freerdp_hexdump(stream_get_head(enc_stream), y_size); printf("*** Cb ***\n"); freerdp_hexdump(stream_get_head(enc_stream) + y_size, cb_size); printf("*** Cr ***\n"); freerdp_hexdump(stream_get_head(enc_stream) + y_size + cb_size, cr_size);*/ stream_set_pos(enc_stream, 0); rfx_decode_rgb(context, enc_stream, y_size, test_quantization_values, cb_size, test_quantization_values, cr_size, test_quantization_values, decode_buffer); dump_ppm_image(decode_buffer); rfx_context_free(context); stream_free(enc_stream); free(rgb_data); }
void test_encode(void) { RFX_CONTEXT * context; uint8 ycbcr_buffer[1024000]; int y_size, cb_size, cr_size; int i; uint8 decode_buffer[4096 * 3]; rgb_data = (uint8 *) malloc(64 * 64 * 3); for (i = 0; i < 64; i++) memcpy(rgb_data + i * 64 * 3, rgb_scanline_data, 64 * 3); //hexdump(rgb_data, 64 * 64 * 3); context = rfx_context_new(); context->mode = RLGR3; rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_RGB); rfx_encode_rgb(context, rgb_data, 64, 64, 64 * 3, test_quantization_values, test_quantization_values, test_quantization_values, ycbcr_buffer, sizeof(ycbcr_buffer), &y_size, &cb_size, &cr_size); //dump_buffer(context->cb_g_buffer, 4096); /*printf("*** Y ***\n"); hexdump(ycbcr_buffer, y_size); printf("*** Cb ***\n"); hexdump(ycbcr_buffer + y_size, cb_size); printf("*** Cr ***\n"); hexdump(ycbcr_buffer + y_size + cb_size, cr_size);*/ rfx_decode_rgb(context, ycbcr_buffer, y_size, test_quantization_values, ycbcr_buffer + y_size, cb_size, test_quantization_values, ycbcr_buffer + y_size + cb_size, cr_size, test_quantization_values, decode_buffer); dump_ppm_image(decode_buffer); rfx_context_free(context); free(rgb_data); }
static BOOL rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, STREAM* s) { BYTE quantIdxY; BYTE quantIdxCb; BYTE quantIdxCr; UINT16 xIdx, yIdx; UINT16 YLen, CbLen, CrLen; if (stream_get_left(s) < 13) { DEBUG_WARN("RfxMessageTile packet too small"); return FALSE; } /* RFX_TILE */ stream_read_BYTE(s, quantIdxY); /* quantIdxY (1 byte) */ stream_read_BYTE(s, quantIdxCb); /* quantIdxCb (1 byte) */ stream_read_BYTE(s, quantIdxCr); /* quantIdxCr (1 byte) */ stream_read_UINT16(s, xIdx); /* xIdx (2 bytes) */ stream_read_UINT16(s, yIdx); /* yIdx (2 bytes) */ stream_read_UINT16(s, YLen); /* YLen (2 bytes) */ stream_read_UINT16(s, CbLen); /* CbLen (2 bytes) */ stream_read_UINT16(s, CrLen); /* CrLen (2 bytes) */ DEBUG_RFX("quantIdxY:%d quantIdxCb:%d quantIdxCr:%d xIdx:%d yIdx:%d YLen:%d CbLen:%d CrLen:%d", quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx, YLen, CbLen, CrLen); tile->x = xIdx * 64; tile->y = yIdx * 64; return rfx_decode_rgb(context, s, YLen, context->quants + (quantIdxY * 10), CbLen, context->quants + (quantIdxCb * 10), CrLen, context->quants + (quantIdxCr * 10), tile->data, 64 * 4); }
static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s, UINT16* pExpecedBlockType) { BOOL rc; int i, close_cnt; int pos; BYTE quant; RFX_TILE* tile; UINT32* quants; UINT16 subtype; UINT32 blockLen; UINT32 blockType; UINT32 tilesDataSize; PTP_WORK* work_objects = NULL; RFX_TILE_PROCESS_WORK_PARAM* params = NULL; void *pmem; if (*pExpecedBlockType != WBT_EXTENSION) { WLog_ERR(TAG, "%s: message unexpeced", __FUNCTION__); return FALSE; } *pExpecedBlockType = WBT_FRAME_END; if (Stream_GetRemainingLength(s) < 14) { WLog_ERR(TAG, "RfxMessageTileSet packet too small"); return FALSE; } Stream_Read_UINT16(s, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */ if (subtype != CBT_TILESET) { WLog_ERR(TAG, "invalid subtype, expected CBT_TILESET."); return FALSE; } Stream_Seek_UINT16(s); /* idx (2 bytes), must be set to 0x0000 */ Stream_Seek_UINT16(s); /* properties (2 bytes) */ Stream_Read_UINT8(s, context->numQuant); /* numQuant (1 byte) */ Stream_Seek_UINT8(s); /* tileSize (1 byte), must be set to 0x40 */ if (context->numQuant < 1) { WLog_ERR(TAG, "no quantization value."); return FALSE; } Stream_Read_UINT16(s, message->numTiles); /* numTiles (2 bytes) */ if (message->numTiles < 1) { WLog_ERR(TAG, "no tiles."); return FALSE; } Stream_Read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ if (!(pmem = realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32)))) return FALSE; quants = context->quants = (UINT32*) pmem; /* quantVals */ if (Stream_GetRemainingLength(s) < (size_t) (context->numQuant * 5)) { WLog_ERR(TAG, "RfxMessageTileSet packet too small for num_quants=%d", context->numQuant); return FALSE; } for (i = 0; i < context->numQuant; i++) { /* RFX_CODEC_QUANT */ Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); Stream_Read_UINT8(s, quant); *quants++ = (quant & 0x0F); *quants++ = (quant >> 4); WLog_Print(context->priv->log, WLOG_DEBUG, "quant %d (%d %d %d %d %d %d %d %d %d %d).", i, context->quants[i * 10], context->quants[i * 10 + 1], context->quants[i * 10 + 2], context->quants[i * 10 + 3], context->quants[i * 10 + 4], context->quants[i * 10 + 5], context->quants[i * 10 + 6], context->quants[i * 10 + 7], context->quants[i * 10 + 8], context->quants[i * 10 + 9]); } if (!(message->tiles = (RFX_TILE**) calloc(message->numTiles, sizeof(RFX_TILE*)))) { message->numTiles = 0; return FALSE; } if (context->priv->UseThreads) { work_objects = (PTP_WORK*) calloc(message->numTiles, sizeof(PTP_WORK)); params = (RFX_TILE_PROCESS_WORK_PARAM*) calloc(message->numTiles, sizeof(RFX_TILE_PROCESS_WORK_PARAM)); if (!work_objects) { free(params); return FALSE; } if (!params) { free(work_objects); return FALSE; } } /* tiles */ close_cnt = 0; rc = TRUE; for (i = 0; i < message->numTiles; i++) { if (!(tile = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool))) { WLog_ERR(TAG, "RfxMessageTileSet failed to get tile from object pool"); rc = FALSE; break; } message->tiles[i] = tile; /* RFX_TILE */ if (Stream_GetRemainingLength(s) < 6) { WLog_ERR(TAG, "RfxMessageTileSet packet too small to read tile %d/%d", i, message->numTiles); rc = FALSE; break; } Stream_Read_UINT16(s, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */ Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */ if (Stream_GetRemainingLength(s) < blockLen - 6) { WLog_ERR(TAG, "RfxMessageTileSet not enough bytes to read tile %d/%d with blocklen=%d", i, message->numTiles, blockLen); rc = FALSE; break; } pos = Stream_GetPosition(s) - 6 + blockLen; if (blockType != CBT_TILE) { WLog_ERR(TAG, "unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType); rc = FALSE; break; } Stream_Read_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */ Stream_Read_UINT8(s, tile->quantIdxCb); /* quantIdxCb (1 byte) */ Stream_Read_UINT8(s, tile->quantIdxCr); /* quantIdxCr (1 byte) */ Stream_Read_UINT16(s, tile->xIdx); /* xIdx (2 bytes) */ Stream_Read_UINT16(s, tile->yIdx); /* yIdx (2 bytes) */ Stream_Read_UINT16(s, tile->YLen); /* YLen (2 bytes) */ Stream_Read_UINT16(s, tile->CbLen); /* CbLen (2 bytes) */ Stream_Read_UINT16(s, tile->CrLen); /* CrLen (2 bytes) */ Stream_GetPointer(s, tile->YData); Stream_Seek(s, tile->YLen); Stream_GetPointer(s, tile->CbData); Stream_Seek(s, tile->CbLen); Stream_GetPointer(s, tile->CrData); Stream_Seek(s, tile->CrLen); tile->x = tile->xIdx * 64; tile->y = tile->yIdx * 64; if (context->priv->UseThreads) { assert(params); params[i].context = context; params[i].tile = message->tiles[i]; if (!(work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_process_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv))) { WLog_ERR(TAG, "CreateThreadpoolWork failed."); rc = FALSE; break; } SubmitThreadpoolWork(work_objects[i]); close_cnt = i + 1; } else { rfx_decode_rgb(context, tile, tile->data, 64 * 4); } Stream_SetPosition(s, pos); } if (context->priv->UseThreads) { for (i = 0; i < close_cnt; i++) { WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); CloseThreadpoolWork(work_objects[i]); } free(work_objects); free(params); } for (i = 0; i < message->numTiles; i++) { if (!(tile = message->tiles[i])) continue; tile->YLen = tile->CbLen = tile->CrLen = 0; tile->YData = tile->CbData = tile->CrData = NULL; } return rc; }
void CALLBACK rfx_process_message_tile_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) { RFX_TILE_PROCESS_WORK_PARAM* param = (RFX_TILE_PROCESS_WORK_PARAM*) context; rfx_decode_rgb(param->context, param->tile, param->tile->data, 64 * 4); }