libfreerdp-rfx: initial migration.

This commit is contained in:
Vic Lee 2011-08-10 15:13:39 +08:00
parent 184bfc2482
commit e414a7d9cc
29 changed files with 3141 additions and 0 deletions

View File

@ -92,6 +92,7 @@ add_subdirectory(libfreerdp-gdi)
add_subdirectory(libfreerdp-cache)
add_subdirectory(libfreerdp-chanman)
add_subdirectory(libfreerdp-core)
add_subdirectory(libfreerdp-rfx)
add_subdirectory(channels)
add_subdirectory(client)

View File

@ -8,3 +8,5 @@ option(WITH_DEBUG_NEGO "Print negotiation related debug messages." OFF)
option(WITH_DEBUG_CERTIFICATE "Print certificate related debug messages." OFF)
option(WITH_DEBUG_LICENSE "Print license debug messages." OFF)
option(WITH_DEBUG_GDI "Print graphics debug messages." OFF)
option(WITH_DEBUG_RFX "Print RemoteFX debug messages." OFF)
option(WITH_PROFILER "Compile profiler." OFF)

View File

@ -25,5 +25,7 @@
#cmakedefine WITH_DEBUG_LICENSE
#cmakedefine WITH_DEBUG_GDI
#cmakedefine WITH_DEBUG_ASSERT
#cmakedefine WITH_DEBUG_RFX
#cmakedefine WITH_PROFILER
#endif

View File

@ -23,6 +23,7 @@ include_directories(${CMAKE_SOURCE_DIR}) # for some internal tests
include_directories(../libfreerdp-core)
include_directories(../libfreerdp-gdi)
include_directories(../libfreerdp-cache)
include_directories(../libfreerdp-rfx)
add_executable(test_freerdp
test_per.c
@ -55,6 +56,8 @@ add_executable(test_freerdp
test_cliprdr.h
test_drdynvc.c
test_drdynvc.h
test_librfx.c
test_librfx.h
test_freerdp.c
test_freerdp.h)
@ -64,5 +67,6 @@ target_link_libraries(test_freerdp freerdp-core)
target_link_libraries(test_freerdp freerdp-gdi)
target_link_libraries(test_freerdp freerdp-utils)
target_link_libraries(test_freerdp freerdp-chanman)
target_link_libraries(test_freerdp freerdp-rfx)
add_test(CUnitTests ${EXECUTABLE_OUTPUT_PATH}/test_freerdp)

View File

@ -34,6 +34,7 @@
#include "test_chanman.h"
#include "test_cliprdr.h"
#include "test_drdynvc.h"
#include "test_librfx.h"
#include "test_freerdp.h"
void dump_data(unsigned char * p, int len, int width, char* name)
@ -174,6 +175,10 @@ int main(int argc, char* argv[])
{
add_drdynvc_suite();
}
else if (strcmp("librfx", argv[*pindex]) == 0)
{
add_librfx_suite();
}
else if (strcmp("per", argv[*pindex]) == 0)
{
add_per_suite();

416
cunit/test_librfx.c Normal file
View File

@ -0,0 +1,416 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* RemoteFX Codec Library Unit Tests
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* The sample data comes from [MS-RDPRFX] 4.2.3, which is decoded into three
* vertical bands in red (21x64), green (23x64) and blue(20x64) color.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <freerdp/types.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/hexdump.h>
#include <freerdp/rfx.h>
#include "rfx_types.h"
#include "rfx_bitstream.h"
#include "rfx_rlgr.h"
#include "rfx_differential.h"
#include "rfx_quantization.h"
#include "rfx_dwt.h"
#include "rfx_decode.h"
#include "rfx_encode.h"
#include "test_librfx.h"
static const uint8 y_data[] =
{
0x19, 0x82, 0x1d, 0x10, 0x62, 0x9d, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88,
0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28,
0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2,
0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b,
0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14,
0xb2, 0x88, 0x52, 0xca, 0x21, 0x4b, 0x28, 0x85, 0x2c, 0xa2, 0x14, 0xb0, 0x00, 0x20, 0xf4, 0x40,
0x0c, 0xc1, 0x1e, 0x20, 0x26, 0x22, 0x20, 0x33, 0x23, 0xc4, 0x23, 0x88, 0x86, 0x50, 0xf1, 0x22,
0x68, 0x4c, 0x91, 0x85, 0x10, 0x34, 0x4c, 0x84, 0x78, 0xa2, 0x0d, 0x13, 0x21, 0x1e, 0x29, 0x06,
0x89, 0x90, 0x8f, 0x14, 0x83, 0x44, 0xf4, 0x23, 0xc5, 0x20, 0xd1, 0x3d, 0x08, 0xf1, 0x48, 0x34,
0x4f, 0x42, 0x3c, 0x52, 0x0d, 0x13, 0xd0, 0x8f, 0x14, 0x83, 0x44, 0xf4, 0x23, 0xc5, 0x20, 0xd1,
0x3d, 0x08, 0xf1, 0x48, 0x34, 0x4f, 0x42, 0x3c, 0x52, 0x0d, 0x13, 0xd0, 0x8f, 0x14, 0x83, 0x44,
0xf4, 0x23, 0xc5, 0x20, 0x00, 0x08, 0x47, 0x70, 0x15, 0x02, 0xe0, 0x7f, 0xe4, 0x9d, 0xc2, 0x51,
0x71, 0xf4, 0x99, 0xc9, 0x57, 0xff, 0x32, 0x87, 0x9d, 0x17, 0xd6, 0x50, 0x6e, 0x06, 0x2f, 0xac,
0xa0, 0x9c, 0x0c, 0x5f, 0x59, 0x41, 0x38, 0x18, 0xbe, 0xb2, 0x82, 0x70, 0x31, 0x7d, 0x65, 0x00,
0x00, 0x10, 0xff, 0x9c, 0x33, 0x41, 0xf1, 0xc4, 0xb0, 0x3c, 0xff, 0xa2, 0x15, 0xbd, 0x7b, 0xea,
0x86, 0x9b, 0x5f, 0xfc, 0x78, 0x8c, 0xf5, 0xed, 0xa8, 0x68, 0xda, 0xfd, 0x3c, 0x45, 0x7a, 0xf4,
0xd4, 0x34, 0x6d, 0x7e, 0x9e, 0x22, 0xbd, 0x7a, 0x6a, 0x1a, 0x36, 0xbf, 0x4f, 0x11, 0x5e, 0xbd,
0x35, 0x0d, 0x1b, 0x5f, 0xa7, 0x88, 0xaf, 0x5e, 0x9a, 0x86, 0x8d, 0xaf, 0xd3, 0xc4, 0x57, 0xaf,
0x4d, 0x43, 0x46, 0xd7, 0xe9, 0xe2, 0x20, 0x30, 0x00
};
static const uint8 cb_data[] =
{
0x1b, 0x04, 0x7f, 0x04, 0x31, 0x5f, 0xc2,
0x94, 0xaf, 0x05, 0x29, 0x5e, 0x0a, 0x52, 0xbc, 0x14, 0xa5, 0x78, 0x29, 0x25, 0x78, 0x29, 0x25,
0x78, 0x29, 0x25, 0x68, 0x52, 0x4a, 0xf0, 0x52, 0x4a, 0xf0, 0x52, 0x4a, 0xd0, 0xa4, 0x95, 0xe0,
0xa4, 0x95, 0xe0, 0xa4, 0x95, 0xa1, 0x49, 0x2b, 0xc1, 0x49, 0x2b, 0xc1, 0x49, 0x2b, 0x42, 0x92,
0x57, 0x82, 0x92, 0x57, 0x82, 0x92, 0x56, 0x85, 0x24, 0xaf, 0x05, 0x24, 0xaf, 0x05, 0x24, 0xad,
0x0a, 0x49, 0x5e, 0x0a, 0x49, 0x5e, 0x0a, 0x49, 0x5a, 0x14, 0x92, 0xbc, 0x14, 0x92, 0xbc, 0x14,
0x92, 0xb4, 0x29, 0x25, 0x78, 0x29, 0x25, 0x78, 0x00, 0x02, 0x0f, 0x02, 0x00, 0xac, 0x13, 0xfc,
0xc0, 0x0a, 0x20, 0x10, 0x2b, 0x27, 0xf9, 0x80, 0xb0, 0x08, 0xaa, 0x3d, 0x60, 0x8c, 0x0b, 0x24,
0xff, 0x30, 0x80, 0xc0, 0xaa, 0x13, 0xfc, 0xc2, 0x03, 0x05, 0x90, 0x9f, 0xe6, 0x10, 0x18, 0x2c,
0x84, 0xff, 0x30, 0x81, 0x82, 0xc8, 0x4f, 0xf3, 0x08, 0x18, 0x2c, 0x84, 0xff, 0x31, 0x03, 0x05,
0x90, 0x9f, 0xff, 0xd8, 0x40, 0x60, 0x59, 0x09, 0xfe, 0x61, 0x01, 0x81, 0x64, 0x27, 0xf9, 0x84,
0x06, 0x0b, 0x21, 0x3f, 0xcc, 0x20, 0x30, 0x59, 0x09, 0xfe, 0x61, 0x03, 0x05, 0x90, 0x9f, 0xe6,
0x10, 0x30, 0x59, 0x09, 0xfe, 0x62, 0x00, 0x00, 0x42, 0x15, 0x00, 0x10, 0x15, 0x01, 0xfe, 0x20,
0x84, 0xd5, 0x01, 0x0a, 0x8f, 0xf1, 0x40, 0x33, 0x78, 0x17, 0xf9, 0xc2, 0x03, 0x83, 0x01, 0x78,
0xe1, 0x01, 0xc1, 0x00, 0xbc, 0x70, 0x80, 0xe0, 0x80, 0x5e, 0x38, 0x40, 0x70, 0x40, 0x2f, 0x1c,
0x20, 0x38, 0x20, 0x17, 0x8e, 0x10, 0x00, 0x00, 0x87, 0xd5, 0x08, 0x70, 0xef, 0x81, 0xa2, 0xd8,
0xff, 0xff, 0xff, 0xfb, 0xd1, 0x2d, 0x4e, 0xa6, 0xce, 0x20, 0xa4, 0xef, 0x05, 0x78, 0x35, 0x3a,
0x9b, 0x38, 0x82, 0x93, 0xbc, 0x15, 0xe0, 0xd4, 0xea, 0x66, 0x71, 0x05, 0x27, 0x78, 0x2b, 0xc1,
0x29, 0xd4, 0xcc, 0xe2, 0x0a, 0x4e, 0xf0, 0x57, 0x82, 0x53, 0xa9, 0x99, 0xc4, 0x14, 0x9d, 0xe0,
0xaf, 0x04, 0xa7, 0x53, 0x33, 0x88, 0x29, 0x3b, 0xc1, 0x5e, 0x09, 0x4e, 0xa6, 0x67, 0x10, 0x52,
0x77, 0x82, 0xbc, 0x00, 0x18, 0x00
};
static const uint8 cr_data[] =
{
0x1b, 0xfc, 0x11, 0xc1, 0x0f, 0x4a, 0xc1, 0x4f, 0x4a, 0xc1,
0x4f, 0x4a, 0xa1, 0x4d, 0x95, 0x42, 0x9e, 0x95, 0x42, 0x9e, 0x95, 0x42, 0x9b, 0x2a, 0x85, 0x3d,
0x2a, 0x85, 0x3d, 0x2a, 0x85, 0x36, 0x55, 0x0a, 0x7a, 0x55, 0x0a, 0x7a, 0x55, 0x0a, 0x6c, 0xaa,
0x14, 0xf4, 0xaa, 0x14, 0xf4, 0xaa, 0x14, 0xd9, 0x54, 0x29, 0xe9, 0x54, 0x29, 0xe9, 0x54, 0x29,
0xb2, 0xa8, 0x53, 0xd2, 0xa8, 0x53, 0xd2, 0xa8, 0x53, 0x65, 0x50, 0xa7, 0xa5, 0x50, 0xa7, 0xa5,
0x50, 0xa6, 0xca, 0xa1, 0x4f, 0x4a, 0xa1, 0x4f, 0x4a, 0xa1, 0x4d, 0x95, 0x42, 0x9e, 0x95, 0x42,
0x9e, 0x95, 0x42, 0x9b, 0x2a, 0x80, 0x00, 0x41, 0xe3, 0x80, 0x3f, 0xe2, 0x09, 0x9c, 0x00, 0x22,
0x07, 0x03, 0xe1, 0x26, 0x70, 0x06, 0x07, 0x1f, 0x04, 0x67, 0x00, 0x61, 0xdf, 0x02, 0x67, 0x00,
0x0c, 0x3b, 0xfe, 0x01, 0x33, 0x80, 0x06, 0x1d, 0xff, 0x00, 0x99, 0xc0, 0x03, 0x0e, 0xff, 0x80,
0x4c, 0xe0, 0x01, 0x87, 0x7f, 0xc0, 0x26, 0x70, 0x00, 0xc3, 0xbf, 0xe0, 0x13, 0x38, 0x00, 0x61,
0xdf, 0xf0, 0x09, 0x9c, 0x00, 0x30, 0xef, 0xf8, 0x04, 0xce, 0x00, 0x18, 0x77, 0xfc, 0x02, 0x67,
0x00, 0x0c, 0x3b, 0xfe, 0x01, 0x33, 0x80, 0x06, 0x1d, 0xff, 0x00, 0x99, 0xc0, 0x03, 0x0e, 0xff,
0x80, 0x4c, 0xe0, 0x01, 0x87, 0x7f, 0xc0, 0x26, 0x70, 0x00, 0x00, 0x08, 0x3c, 0x20, 0x1f, 0xf1,
0x00, 0xf0, 0x05, 0x02, 0x93, 0x84, 0x3d, 0x20, 0xf0, 0x52, 0x81, 0xc7, 0xff, 0xff, 0xea, 0x54,
0x01, 0x80, 0x05, 0xf5, 0x4a, 0x80, 0x30, 0x00, 0xb6, 0xa5, 0x40, 0x18, 0x00, 0x5f, 0x54, 0xa8,
0x03, 0x00, 0x0b, 0xea, 0x95, 0x00, 0x60, 0x01, 0x6d, 0x4a, 0x80, 0x30, 0x00, 0x00, 0x22, 0x3f,
0xba, 0x08, 0x10, 0x2b, 0x1f, 0xf2, 0x20, 0x3e, 0x49, 0x9c, 0x1f, 0x6e, 0x0f, 0x5a, 0x0f, 0xfb,
0x18, 0x46, 0xae, 0x27, 0x9b, 0x83, 0xcb, 0x41, 0xf3, 0x18, 0x46, 0xae, 0x27, 0x9b, 0x83, 0xc5,
0xa0, 0xf9, 0x8c, 0x22, 0xd7, 0x13, 0x8d, 0xc1, 0xe2, 0xd0, 0x7c, 0xc6, 0x11, 0x6b, 0x89, 0xc6,
0xe0, 0xf1, 0x68, 0x3e, 0x63, 0x08, 0xb5, 0xc4, 0xe3, 0x70, 0x78, 0xb4, 0x1f, 0x31, 0x84, 0x5a,
0xe2, 0x71, 0xb8, 0x3c, 0x5a, 0x0f, 0x98, 0xc2, 0x2d, 0x71, 0x30, 0x83, 0xc0, 0x00
};
/* HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3 */
static const unsigned int test_quantization_values[] =
{
6, 6, 6, 6, 7, 7, 8, 8, 8, 9
};
static const uint8 rgb_scanline_data[] =
{
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF
};
static uint8* rgb_data;
int init_librfx_suite(void)
{
return 0;
}
int clean_librfx_suite(void)
{
return 0;
}
int add_librfx_suite(void)
{
add_test_suite(librfx);
add_test_function(bitstream);
add_test_function(bitstream_enc);
add_test_function(rlgr);
add_test_function(differential);
add_test_function(quantization);
add_test_function(dwt);
add_test_function(decode);
add_test_function(encode);
add_test_function(message);
return 0;
}
void test_bitstream(void)
{
uint16 b;
RFX_BITSTREAM* bs;
bs = xnew(RFX_BITSTREAM);
rfx_bitstream_attach(bs, (uint8*) y_data, sizeof(y_data));
while (!rfx_bitstream_eos(bs))
{
b = rfx_bitstream_get_bits(bs, 3);
//printf("%u ", b);
}
xfree(bs);
//printf("\n");
}
void test_bitstream_enc(void)
{
uint8 buffer[10];
RFX_BITSTREAM* bs;
int i;
bs = xnew(RFX_BITSTREAM);
memset(buffer, 0, sizeof(buffer));
rfx_bitstream_attach(bs, buffer, sizeof(buffer));
for (i = 0; i < 16; i++)
{
rfx_bitstream_put_bits(bs, i, 5);
}
/*for (i = 0; i < sizeof(buffer); i++)
{
printf("%X ", buffer[i]);
}*/
xfree(bs);
//printf("\n");
}
static sint16 buffer[4096];
void dump_buffer(sint16* buf, int n)
{
int i;
for (i = 0; i < n; i++)
{
if (i % 16 == 0)
printf("\n%04d ", i);
printf("% 4d ", buf[i]);
}
printf("\n");
}
void test_rlgr(void)
{
int n;
n = rfx_rlgr_decode(RLGR3, y_data, sizeof(y_data), buffer, sizeof(buffer) / sizeof(unsigned int));
//printf("RLGR decode %d bytes to %d values.", sizeof(y_data), n);
//dump_buffer(buffer, n);
}
void test_differential(void)
{
rfx_differential_decode(buffer + 4032, 64);
//dump_buffer(buffer + 4032, 64);
}
void test_quantization(void)
{
rfx_quantization_decode(buffer, test_quantization_values);
//dump_buffer(buffer, 4096);
}
void test_dwt(void)
{
RFX_CONTEXT* context;
context = rfx_context_new();
rfx_dwt_2d_decode(buffer, context->priv->dwt_buffer);
//dump_buffer(buffer, 4096);
rfx_context_free(context);
}
/* Dump a .ppm image. */
static void dump_ppm_image(uint8* image_buf)
{
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(image_buf, 1, 4096 * 3, fp);
fflush(fp);
fclose(fp);
frame_id++;
}
void test_decode(void)
{
RFX_CONTEXT* context;
uint8 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, RFX_PIXEL_FORMAT_RGB);
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);
}
void test_encode(void)
{
RFX_CONTEXT* context;
STREAM* enc_stream;
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);
//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, RFX_PIXEL_FORMAT_RGB);
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_message(void)
{
RFX_CONTEXT* context;
STREAM* s;
int size;
int i, j;
RFX_RECT rect = {0, 0, 100, 80};
RFX_MESSAGE * message;
rgb_data = (uint8 *) malloc(100 * 80 * 3);
for (i = 0; i < 80; i++)
memcpy(rgb_data + i * 100 * 3, rgb_scanline_data, 100 * 3);
s = stream_new(65536);
stream_clear(s);
context = rfx_context_new();
context->mode = RLGR3;
context->width = 800;
context->height = 600;
rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_RGB);
rfx_compose_message_header(context, s);
/*hexdump(buffer, size);*/
stream_seal(s);
stream_set_pos(s, 0);
message = rfx_process_message(context, s);
rfx_message_free(context, message);
stream_free(s);
for (i = 0; i < 1; i++)
{
s = stream_new(65536);
stream_clear(s);
rfx_compose_message_data(context, s,
&rect, 1, rgb_data, 100, 80, 100 * 3);
stream_seal(s);
/*hexdump(buffer, size);*/
stream_set_pos(s, 0);
message = rfx_process_message(context, s);
if (i == 0)
{
for (j = 0; j < message->num_tiles; j++)
{
dump_ppm_image(message->tiles[j]->data);
}
}
rfx_message_free(context, message);
stream_free(s);
}
rfx_context_free(context);
free(rgb_data);
}

34
cunit/test_librfx.h Normal file
View File

@ -0,0 +1,34 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* RemoteFX Codec Library Unit Tests
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "test_freerdp.h"
int init_librfx_suite(void);
int clean_librfx_suite(void);
int add_librfx_suite(void);
void test_bitstream(void);
void test_bitstream_enc(void);
void test_rlgr(void);
void test_differential(void);
void test_quantization(void);
void test_dwt(void);
void test_decode(void);
void test_encode(void);
void test_message(void);

134
include/freerdp/rfx.h Normal file
View File

@ -0,0 +1,134 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - API Header
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_H
#define __RFX_H
#include <freerdp/types.h>
#include <freerdp/utils/stream.h>
#ifdef __cplusplus
extern "C" {
#endif
enum _RLGR_MODE
{
RLGR1,
RLGR3
};
typedef enum _RLGR_MODE RLGR_MODE;
enum _RFX_PIXEL_FORMAT
{
RFX_PIXEL_FORMAT_BGRA,
RFX_PIXEL_FORMAT_RGBA,
RFX_PIXEL_FORMAT_BGR,
RFX_PIXEL_FORMAT_RGB
};
typedef enum _RFX_PIXEL_FORMAT RFX_PIXEL_FORMAT;
struct _RFX_RECT
{
uint16 x;
uint16 y;
uint16 width;
uint16 height;
};
typedef struct _RFX_RECT RFX_RECT;
struct _RFX_TILE
{
uint16 x;
uint16 y;
uint8* data;
};
typedef struct _RFX_TILE RFX_TILE;
struct _RFX_MESSAGE
{
/**
* The rects array represents the updated region of the frame. The UI
* requires to clip drawing destination base on the union of the rects.
*/
uint16 num_rects;
RFX_RECT* rects;
/**
* The tiles array represents the actual frame data. Each tile is always
* 64x64. Note that only pixels inside the updated region (represented as
* rects described above) are valid. Pixels outside of the region may
* contain arbitrary data.
*/
uint16 num_tiles;
RFX_TILE** tiles;
};
typedef struct _RFX_MESSAGE RFX_MESSAGE;
typedef struct _RFX_CONTEXT_PRIV RFX_CONTEXT_PRIV;
struct _RFX_CONTEXT
{
uint16 flags;
uint16 properties;
uint16 width;
uint16 height;
RLGR_MODE mode;
uint32 version;
uint32 codec_id;
uint32 codec_version;
RFX_PIXEL_FORMAT pixel_format;
uint8 bytes_per_pixel;
/* temporary data within a frame */
uint32 frame_idx;
uint8 num_quants;
uint32* quants;
uint8 quant_idx_y;
uint8 quant_idx_cb;
uint8 quant_idx_cr;
/* routines */
void (*decode_ycbcr_to_rgb)(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf);
void (*encode_rgb_to_ycbcr)(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf);
void (*quantization_decode)(sint16* buffer, const uint32* quantization_values);
void (*quantization_encode)(sint16* buffer, const uint32* quantization_values);
void (*dwt_2d_decode)(sint16* buffer, sint16* dwt_buffer);
void (*dwt_2d_encode)(sint16* buffer, sint16* dwt_buffer);
/* private definitions */
RFX_CONTEXT_PRIV* priv;
};
typedef struct _RFX_CONTEXT RFX_CONTEXT;
RFX_CONTEXT* rfx_context_new(void);
void rfx_context_free(RFX_CONTEXT* context);
void rfx_context_set_pixel_format(RFX_CONTEXT* context, RFX_PIXEL_FORMAT pixel_format);
RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, STREAM* data_in);
void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message);
void rfx_compose_message_header(RFX_CONTEXT* context, STREAM* data_out);
void rfx_compose_message_data(RFX_CONTEXT* context, STREAM* data_out,
const RFX_RECT* rects, int num_rects, uint8* image_data, int width, int height, int rowstride);
#ifdef __cplusplus
}
#endif
#endif /* __RFX_H */

View File

@ -35,6 +35,13 @@ typedef struct _STREAM STREAM;
STREAM* stream_new(int size);
void stream_free(STREAM* stream);
#define stream_attach(_s, _buf, _size) do { \
_s->size = _size; \
_s->data = _buf; \
_s->p = _buf; } while (0)
#define stream_detach(_s) memset(_s, 0, sizeof(STREAM))
#define stream_clear(_s) memset(_s->data, 0, _s->size)
void stream_extend(STREAM* stream);
#define stream_check_size(_s,_n) \
while (_s->p - _s->data + (_n) > _s->size) \

View File

@ -0,0 +1,46 @@
# FreeRDP: A Remote Desktop Protocol Client
# libfreerdp-core cmake build script
#
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set(LIBFREERDP_RFX_SRCS
rfx_bitstream.c
rfx_bitstream.h
rfx_constants.h
rfx_decode.c
rfx_decode.h
rfx_differential.c
rfx_differential.h
rfx_dwt.c
rfx_dwt.h
rfx_encode.c
rfx_encode.h
rfx_pool.c
rfx_pool.h
rfx_quantization.c
rfx_quantization.h
rfx_rlgr.c
rfx_rlgr.h
rfx_types.h
librfx.c
)
add_library(freerdp-rfx SHARED ${LIBFREERDP_RFX_SRCS})
target_link_libraries(freerdp-rfx freerdp-utils)
install(TARGETS freerdp-rfx DESTINATION lib)

819
libfreerdp-rfx/librfx.c Normal file
View File

@ -0,0 +1,819 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <freerdp/rfx.h>
#include <freerdp/utils/memory.h>
#include "rfx_constants.h"
#include "rfx_types.h"
#include "rfx_pool.h"
#include "rfx_decode.h"
#include "rfx_encode.h"
#include "rfx_quantization.h"
#include "rfx_dwt.h"
#ifdef WITH_SSE
#include "rfx_sse.h"
#endif
#ifdef WITH_NEON
#include "rfx_neon.h"
#endif
#ifndef RFX_INIT_SIMD
#define RFX_INIT_SIMD(_rfx_context) do { } while (0)
#endif
/**
* The quantization values control the compression rate and quality. The value
* range is between 6 and 15. The higher value, the higher compression rate
* and lower quality.
*
* This is the default values being use by the MS RDP server, and we will also
* use it as our default values for the encoder. It can be overrided by setting
* the context->num_quants and context->quants member.
*
* The order of the values are:
* LL3, LH3, HL3, HH3, LH2, HL2, HH2, LH1, HL1, HH1
*/
static const uint32 rfx_default_quantization_values[] =
{
6, 6, 6, 6, 7, 7, 8, 8, 8, 9
};
static void rfx_profiler_create(RFX_CONTEXT* context)
{
PROFILER_CREATE(context->priv->prof_rfx_decode_rgb, "rfx_decode_rgb");
PROFILER_CREATE(context->priv->prof_rfx_decode_component, "rfx_decode_component");
PROFILER_CREATE(context->priv->prof_rfx_rlgr_decode, "rfx_rlgr_decode");
PROFILER_CREATE(context->priv->prof_rfx_differential_decode, "rfx_differential_decode");
PROFILER_CREATE(context->priv->prof_rfx_quantization_decode, "rfx_quantization_decode");
PROFILER_CREATE(context->priv->prof_rfx_dwt_2d_decode, "rfx_dwt_2d_decode");
PROFILER_CREATE(context->priv->prof_rfx_decode_ycbcr_to_rgb, "rfx_decode_ycbcr_to_rgb");
PROFILER_CREATE(context->priv->prof_rfx_decode_format_rgb, "rfx_decode_format_rgb");
PROFILER_CREATE(context->priv->prof_rfx_encode_rgb, "rfx_encode_rgb");
PROFILER_CREATE(context->priv->prof_rfx_encode_component, "rfx_encode_component");
PROFILER_CREATE(context->priv->prof_rfx_rlgr_encode, "rfx_rlgr_encode");
PROFILER_CREATE(context->priv->prof_rfx_differential_encode, "rfx_differential_encode");
PROFILER_CREATE(context->priv->prof_rfx_quantization_encode, "rfx_quantization_encode");
PROFILER_CREATE(context->priv->prof_rfx_dwt_2d_encode, "rfx_dwt_2d_encode");
PROFILER_CREATE(context->priv->prof_rfx_encode_rgb_to_ycbcr, "rfx_encode_rgb_to_ycbcr");
PROFILER_CREATE(context->priv->prof_rfx_encode_format_rgb, "rfx_encode_format_rgb");
}
static void rfx_profiler_free(RFX_CONTEXT* context)
{
PROFILER_FREE(context->priv->prof_rfx_decode_rgb);
PROFILER_FREE(context->priv->prof_rfx_decode_component);
PROFILER_FREE(context->priv->prof_rfx_rlgr_decode);
PROFILER_FREE(context->priv->prof_rfx_differential_decode);
PROFILER_FREE(context->priv->prof_rfx_quantization_decode);
PROFILER_FREE(context->priv->prof_rfx_dwt_2d_decode);
PROFILER_FREE(context->priv->prof_rfx_decode_ycbcr_to_rgb);
PROFILER_FREE(context->priv->prof_rfx_decode_format_rgb);
PROFILER_FREE(context->priv->prof_rfx_encode_rgb);
PROFILER_FREE(context->priv->prof_rfx_encode_component);
PROFILER_FREE(context->priv->prof_rfx_rlgr_encode);
PROFILER_FREE(context->priv->prof_rfx_differential_encode);
PROFILER_FREE(context->priv->prof_rfx_quantization_encode);
PROFILER_FREE(context->priv->prof_rfx_dwt_2d_encode);
PROFILER_FREE(context->priv->prof_rfx_encode_rgb_to_ycbcr);
PROFILER_FREE(context->priv->prof_rfx_encode_format_rgb);
}
static void rfx_profiler_print(RFX_CONTEXT* context)
{
PROFILER_PRINT_HEADER;
PROFILER_PRINT(context->priv->prof_rfx_decode_rgb);
PROFILER_PRINT(context->priv->prof_rfx_decode_component);
PROFILER_PRINT(context->priv->prof_rfx_rlgr_decode);
PROFILER_PRINT(context->priv->prof_rfx_differential_decode);
PROFILER_PRINT(context->priv->prof_rfx_quantization_decode);
PROFILER_PRINT(context->priv->prof_rfx_dwt_2d_decode);
PROFILER_PRINT(context->priv->prof_rfx_decode_ycbcr_to_rgb);
PROFILER_PRINT(context->priv->prof_rfx_decode_format_rgb);
PROFILER_PRINT(context->priv->prof_rfx_encode_rgb);
PROFILER_PRINT(context->priv->prof_rfx_encode_component);
PROFILER_PRINT(context->priv->prof_rfx_rlgr_encode);
PROFILER_PRINT(context->priv->prof_rfx_differential_encode);
PROFILER_PRINT(context->priv->prof_rfx_quantization_encode);
PROFILER_PRINT(context->priv->prof_rfx_dwt_2d_encode);
PROFILER_PRINT(context->priv->prof_rfx_encode_rgb_to_ycbcr);
PROFILER_PRINT(context->priv->prof_rfx_encode_format_rgb);
PROFILER_PRINT_FOOTER;
}
RFX_CONTEXT* rfx_context_new(void)
{
RFX_CONTEXT* context;
context = xnew(RFX_CONTEXT);
context->priv = xnew(RFX_CONTEXT_PRIV);
context->priv->pool = rfx_pool_new();
/* initialize the default pixel format */
rfx_context_set_pixel_format(context, RFX_PIXEL_FORMAT_BGRA);
/* align buffers to 16 byte boundary (needed for SSE/SSE2 instructions) */
context->priv->y_r_buffer = (sint16*)(((uintptr_t)context->priv->y_r_mem + 16) & ~ 0x0F);
context->priv->cb_g_buffer = (sint16*)(((uintptr_t)context->priv->cb_g_mem + 16) & ~ 0x0F);
context->priv->cr_b_buffer = (sint16*)(((uintptr_t)context->priv->cr_b_mem + 16) & ~ 0x0F);
context->priv->dwt_buffer = (sint16*)(((uintptr_t)context->priv->dwt_mem + 16) & ~ 0x0F);
/* create profilers for default decoding routines */
rfx_profiler_create(context);
/* set up default routines */
context->decode_ycbcr_to_rgb = rfx_decode_ycbcr_to_rgb;
context->encode_rgb_to_ycbcr = rfx_encode_rgb_to_ycbcr;
context->quantization_decode = rfx_quantization_decode;
context->quantization_encode = rfx_quantization_encode;
context->dwt_2d_decode = rfx_dwt_2d_decode;
context->dwt_2d_encode = rfx_dwt_2d_encode;
/* detect and enable SIMD CPU acceleration */
RFX_INIT_SIMD(context);
return context;
}
void rfx_context_free(RFX_CONTEXT* context)
{
xfree(context->quants);
rfx_pool_free(context->priv->pool);
rfx_profiler_print(context);
rfx_profiler_free(context);
xfree(context->priv);
xfree(context);
}
void rfx_context_set_pixel_format(RFX_CONTEXT* context, RFX_PIXEL_FORMAT pixel_format)
{
context->pixel_format = pixel_format;
switch (pixel_format)
{
case RFX_PIXEL_FORMAT_BGRA:
case RFX_PIXEL_FORMAT_RGBA:
context->bytes_per_pixel = 4;
break;
case RFX_PIXEL_FORMAT_BGR:
case RFX_PIXEL_FORMAT_RGB:
context->bytes_per_pixel = 3;
break;
default:
context->bytes_per_pixel = 0;
break;
}
}
static void rfx_process_message_sync(RFX_CONTEXT* context, STREAM* data_in)
{
uint32 magic;
/* RFX_SYNC */
stream_read_uint32(data_in, magic); /* magic (4 bytes), 0xCACCACCA */
if (magic != WF_MAGIC)
{
DEBUG_WARN("invalid magic number 0x%X", magic);
return;
}
stream_read_uint16(data_in, context->version); /* version (2 bytes), WF_VERSION_1_0 (0x0100) */
if (context->version != WF_VERSION_1_0)
{
DEBUG_WARN("unknown version number 0x%X", context->version);
return;
}
DEBUG_RFX("version 0x%X", context->version);
}
static void rfx_process_message_codec_versions(RFX_CONTEXT* context, STREAM* data_in)
{
uint8 numCodecs;
stream_read_uint8(data_in, numCodecs); /* numCodecs (1 byte), must be set to 0x01 */
if (numCodecs != 1)
{
DEBUG_WARN("numCodecs: %d, expected:1", numCodecs);
return;
}
/* RFX_CODEC_VERSIONT */
stream_read_uint8(data_in, context->codec_id); /* codecId (1 byte) */
stream_read_uint8(data_in, context->codec_version); /* version (2 bytes) */
DEBUG_RFX("id %d version 0x%X.", context->codec_id, context->codec_version);
}
static void rfx_process_message_channels(RFX_CONTEXT* context, STREAM* data_in)
{
uint8 channelId;
uint8 numChannels;
stream_read_uint8(data_in, numChannels); /* numChannels (1 byte), must bet set to 0x01 */
if (numChannels != 1)
{
DEBUG_WARN("numChannels:%d, expected:1", numChannels);
return;
}
/* RFX_CHANNELT */
stream_read_uint8(data_in, channelId); /* channelId (1 byte) */
stream_read_uint16(data_in, context->width); /* width (2 bytes) */
stream_read_uint16(data_in, context->height); /* height (2 bytes) */
DEBUG_RFX("numChannels %d id %d, %dx%d.",
numChannels, channelId, context->width, context->height);
}
static void rfx_process_message_context(RFX_CONTEXT* context, STREAM* data_in)
{
uint8 ctxId;
uint16 tileSize;
uint16 properties;
stream_read_uint8(data_in, ctxId); /* ctxId (1 byte), must be set to 0x00 */
stream_read_uint16(data_in, tileSize); /* tileSize (2 bytes), must be set to CT_TILE_64x64 (0x0040) */
stream_read_uint16(data_in, properties); /* properties (2 bytes) */
DEBUG_RFX("ctxId %d tileSize %d properties 0x%X.", ctxId, tileSize, properties);
context->properties = properties;
context->flags = (properties & 0x0007);
if (context->flags == CODEC_MODE)
DEBUG_RFX("codec is in image mode.");
else
DEBUG_RFX("codec is in video mode.");
switch ((properties & 0x1E00) >> 9)
{
case CLW_ENTROPY_RLGR1:
context->mode = RLGR1;
DEBUG_RFX("RLGR1.");
break;
case CLW_ENTROPY_RLGR3:
context->mode = RLGR3;
DEBUG_RFX("RLGR3.");
break;
default:
DEBUG_WARN("unknown RLGR algorithm.");
break;
}
}
static void rfx_process_message_frame_begin(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* data_in)
{
uint32 frameIdx;
uint16 numRegions;
stream_read_uint32(data_in, frameIdx); /* frameIdx (4 bytes), if codec is in video mode, must be ignored */
stream_read_uint16(data_in, numRegions); /* numRegions (2 bytes) */
DEBUG_RFX("RFX_FRAME_BEGIN: frameIdx:%d numRegions:%d", frameIdx, numRegions);
}
static void rfx_process_message_frame_end(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* data_in)
{
DEBUG_RFX("RFX_FRAME_END");
}
static void rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* data_in)
{
int i;
stream_seek_uint8(data_in); /* regionFlags (1 byte) */
stream_read_uint16(data_in, message->num_rects); /* numRects (2 bytes) */
if (message->num_rects < 1)
{
DEBUG_WARN("no rects.");
return;
}
if (message->rects != NULL)
message->rects = (RFX_RECT*) xrealloc(message->rects, message->num_rects * sizeof(RFX_RECT));
else
message->rects = (RFX_RECT*) xmalloc(message->num_rects * sizeof(RFX_RECT));
/* rects */
for (i = 0; i < message->num_rects; i++)
{
/* RFX_RECT */
stream_read_uint16(data_in, message->rects[i].x); /* x (2 bytes) */
stream_read_uint16(data_in, message->rects[i].y); /* y (2 bytes) */
stream_read_uint16(data_in, message->rects[i].width); /* width (2 bytes) */
stream_read_uint16(data_in, message->rects[i].height); /* height (2 bytes) */
DEBUG_RFX("rect %d (%d %d %d %d).",
i, message->rects[i].x, message->rects[i].y, message->rects[i].width, message->rects[i].height);
}
}
static void rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, STREAM* data_in)
{
uint8 quantIdxY;
uint8 quantIdxCb;
uint8 quantIdxCr;
uint16 xIdx, yIdx;
uint16 YLen, CbLen, CrLen;
/* RFX_TILE */
stream_read_uint8(data_in, quantIdxY); /* quantIdxY (1 byte) */
stream_read_uint8(data_in, quantIdxCb); /* quantIdxCb (1 byte) */
stream_read_uint8(data_in, quantIdxCr); /* quantIdxCr (1 byte) */
stream_read_uint16(data_in, xIdx); /* xIdx (2 bytes) */
stream_read_uint16(data_in, yIdx); /* yIdx (2 bytes) */
stream_read_uint16(data_in, YLen); /* YLen (2 bytes) */
stream_read_uint16(data_in, CbLen); /* CbLen (2 bytes) */
stream_read_uint16(data_in, 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, data_in,
YLen, context->quants + (quantIdxY * 10),
CbLen, context->quants + (quantIdxCb * 10),
CrLen, context->quants + (quantIdxCr * 10),
tile->data);
}
static void rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, STREAM* data_in)
{
int i;
uint16 subtype;
uint32 blockLen;
uint32 blockType;
uint32 tilesDataSize;
uint32* quants;
uint8 quant;
int pos;
stream_read_uint16(data_in, subtype); /* subtype (2 bytes) must be set to CBT_TILESET (0xCAC2) */
if (subtype != CBT_TILESET)
{
DEBUG_WARN("invalid subtype, expected CBT_TILESET.");
return;
}
stream_seek_uint16(data_in); /* idx (2 bytes), must be set to 0x0000 */
stream_seek_uint16(data_in); /* properties (2 bytes) */
stream_read_uint8(data_in, context->num_quants); /* numQuant (1 byte) */
stream_seek_uint8(data_in); /* tileSize (1 byte), must be set to 0x40 */
if (context->num_quants < 1)
{
DEBUG_WARN("no quantization value.");
return;
}
stream_read_uint16(data_in, message->num_tiles); /* numTiles (2 bytes) */
if (message->num_tiles < 1)
{
DEBUG_WARN("no tiles.");
return;
}
stream_read_uint32(data_in, tilesDataSize); /* tilesDataSize (4 bytes) */
if (context->quants != NULL)
context->quants = (uint32*) xrealloc((void*) context->quants, context->num_quants * 10 * sizeof(uint32));
else
context->quants = (uint32*) xmalloc(context->num_quants * 10 * sizeof(uint32));
quants = context->quants;
/* quantVals */
for (i = 0; i < context->num_quants; i++)
{
/* RFX_CODEC_QUANT */
stream_read_uint8(data_in, quant);
*quants++ = (quant & 0x0F);
*quants++ = (quant >> 4);
stream_read_uint8(data_in, quant);
*quants++ = (quant & 0x0F);
*quants++ = (quant >> 4);
stream_read_uint8(data_in, quant);
*quants++ = (quant & 0x0F);
*quants++ = (quant >> 4);
stream_read_uint8(data_in, quant);
*quants++ = (quant & 0x0F);
*quants++ = (quant >> 4);
stream_read_uint8(data_in, quant);
*quants++ = (quant & 0x0F);
*quants++ = (quant >> 4);
DEBUG_RFX("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]);
}
message->tiles = rfx_pool_get_tiles(context->priv->pool, message->num_tiles);
/* tiles */
for (i = 0; i < message->num_tiles; i++)
{
/* RFX_TILE */
stream_read_uint16(data_in, blockType); /* blockType (2 bytes), must be set to CBT_TILE (0xCAC3) */
stream_read_uint32(data_in, blockLen); /* blockLen (4 bytes) */
pos = stream_get_pos(data_in) - 6 + blockLen;
if (blockType != CBT_TILE)
{
DEBUG_WARN("unknown block type 0x%X, expected CBT_TILE (0xCAC3).", blockType);
break;
}
rfx_process_message_tile(context, message->tiles[i], data_in);
stream_set_pos(data_in, pos);
}
}
RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, STREAM* data_in)
{
uint32 offset;
uint32 blockLen;
uint32 blockType;
RFX_MESSAGE* message;
int pos;
message = xnew(RFX_MESSAGE);
while (stream_get_left(data_in) > 6)
{
/* RFX_BLOCKT */
stream_read_uint16(data_in, blockType); /* blockType (2 bytes) */
stream_read_uint32(data_in, blockLen); /* blockLen (4 bytes) */
DEBUG_RFX("blockType 0x%X blockLen %d", blockType, blockLen);
if (blockLen == 0)
{
DEBUG_WARN("zero blockLen");
break;
}
pos = stream_get_pos(data_in) - 6 + blockLen;
if (blockType >= WBT_CONTEXT && blockType <= WBT_EXTENSION)
{
/* RFX_CODEC_CHANNELT */
/* codecId (1 byte) must be set to 0x01 */
/* channelId (1 byte) must be set to 0x00 */
stream_seek(data_in, 2);
}
switch (blockType)
{
case WBT_SYNC:
rfx_process_message_sync(context, data_in);
break;
case WBT_CODEC_VERSIONS:
rfx_process_message_codec_versions(context, data_in);
break;
case WBT_CHANNELS:
rfx_process_message_channels(context, data_in);
break;
case WBT_CONTEXT:
rfx_process_message_context(context, data_in);
break;
case WBT_FRAME_BEGIN:
rfx_process_message_frame_begin(context, message, data_in);
break;
case WBT_FRAME_END:
rfx_process_message_frame_end(context, message, data_in);
break;
case WBT_REGION:
rfx_process_message_region(context, message, data_in);
break;
case WBT_EXTENSION:
rfx_process_message_tileset(context, message, data_in);
break;
default:
DEBUG_WARN("unknown blockType 0x%X", blockType);
break;
}
stream_set_pos(data_in, pos);
}
return message;
}
void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message)
{
if (message != NULL)
{
xfree(message->rects);
if (message->tiles != NULL)
{
rfx_pool_put_tiles(context->priv->pool, message->tiles, message->num_tiles);
xfree(message->tiles);
}
xfree(message);
}
}
static void rfx_compose_message_sync(RFX_CONTEXT* context, STREAM* data_out)
{
stream_write_uint16(data_out, WBT_SYNC); /* BlockT.blockType */
stream_write_uint32(data_out, 12); /* BlockT.blockLen */
stream_write_uint32(data_out, WF_MAGIC); /* magic */
stream_write_uint16(data_out, WF_VERSION_1_0); /* version */
}
static void rfx_compose_message_codec_versions(RFX_CONTEXT* context, STREAM* data_out)
{
stream_write_uint16(data_out, WBT_CODEC_VERSIONS); /* BlockT.blockType */
stream_write_uint32(data_out, 10); /* BlockT.blockLen */
stream_write_uint8(data_out, 1); /* numCodecs */
stream_write_uint8(data_out, 1); /* codecs.codecId */
stream_write_uint16(data_out, WF_VERSION_1_0); /* codecs.version */
}
static void rfx_compose_message_channels(RFX_CONTEXT* context, STREAM* data_out)
{
stream_write_uint16(data_out, WBT_CHANNELS); /* BlockT.blockType */
stream_write_uint32(data_out, 12); /* BlockT.blockLen */
stream_write_uint8(data_out, 1); /* numChannels */
stream_write_uint8(data_out, 0); /* Channel.channelId */
stream_write_uint16(data_out, context->width); /* Channel.width */
stream_write_uint16(data_out, context->height); /* Channel.height */
}
static void rfx_compose_message_context(RFX_CONTEXT* context, STREAM* data_out)
{
uint16 properties;
stream_write_uint16(data_out, WBT_CONTEXT); /* CodecChannelT.blockType */
stream_write_uint32(data_out, 13); /* CodecChannelT.blockLen */
stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */
stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */
stream_write_uint8(data_out, 0); /* ctxId */
stream_write_uint16(data_out, CT_TILE_64x64); /* tileSize */
/* properties */
properties = context->flags; /* flags */
properties |= (COL_CONV_ICT << 3); /* cct */
properties |= (CLW_XFORM_DWT_53_A << 5); /* xft */
properties |= ((context->mode == RLGR1 ? CLW_ENTROPY_RLGR1 : CLW_ENTROPY_RLGR3) << 9); /* et */
properties |= (SCALAR_QUANTIZATION << 13); /* qt */
stream_write_uint16(data_out, properties);
context->properties = properties;
}
void rfx_compose_message_header(RFX_CONTEXT* context, STREAM* data_out)
{
stream_check_size(data_out, 12 + 10 + 12 + 13);
rfx_compose_message_sync(context, data_out);
rfx_compose_message_codec_versions(context, data_out);
rfx_compose_message_channels(context, data_out);
rfx_compose_message_context(context, data_out);
}
static void rfx_compose_message_frame_begin(RFX_CONTEXT* context, STREAM* data_out)
{
stream_check_size(data_out, 14);
stream_write_uint16(data_out, WBT_FRAME_BEGIN); /* CodecChannelT.blockType */
stream_write_uint32(data_out, 14); /* CodecChannelT.blockLen */
stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */
stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */
stream_write_uint32(data_out, context->frame_idx); /* frameIdx */
stream_write_uint16(data_out, 1); /* numRegions */
}
static void rfx_compose_message_region(RFX_CONTEXT* context, STREAM* data_out,
const RFX_RECT* rects, int num_rects)
{
int size;
int i;
size = 15 + num_rects * 8;
stream_check_size(data_out, size);
stream_write_uint16(data_out, WBT_REGION); /* CodecChannelT.blockType */
stream_write_uint32(data_out, size); /* set CodecChannelT.blockLen later */
stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */
stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */
stream_write_uint8(data_out, 1); /* regionFlags */
stream_write_uint16(data_out, num_rects); /* numRects */
for (i = 0; i < num_rects; i++)
{
stream_write_uint16(data_out, rects[i].x);
stream_write_uint16(data_out, rects[i].y);
stream_write_uint16(data_out, rects[i].width);
stream_write_uint16(data_out, rects[i].height);
}
stream_write_uint16(data_out, CBT_REGION); /* regionType */
stream_write_uint16(data_out, 1); /* numTilesets */
}
static void rfx_compose_message_tile(RFX_CONTEXT* context, STREAM* data_out,
uint8* tile_data, int tile_width, int tile_height, int rowstride,
const uint32* quantVals, int quantIdxY, int quantIdxCb, int quantIdxCr,
int xIdx, int yIdx)
{
int YLen = 0;
int CbLen = 0;
int CrLen = 0;
int start_pos, end_pos;
stream_check_size(data_out, 19);
start_pos = stream_get_pos(data_out);
stream_write_uint16(data_out, CBT_TILE); /* BlockT.blockType */
stream_seek_uint32(data_out); /* set BlockT.blockLen later */
stream_write_uint8(data_out, quantIdxY);
stream_write_uint8(data_out, quantIdxCb);
stream_write_uint8(data_out, quantIdxCr);
stream_write_uint16(data_out, xIdx);
stream_write_uint16(data_out, yIdx);
stream_seek(data_out, 6); /* YLen, CbLen, CrLen */
rfx_encode_rgb(context, tile_data, tile_width, tile_height, rowstride,
quantVals + quantIdxY * 10, quantVals + quantIdxCb * 10, quantVals + quantIdxCr * 10,
data_out, &YLen, &CbLen, &CrLen);
DEBUG_RFX("xIdx=%d yIdx=%d width=%d height=%d YLen=%d CbLen=%d CrLen=%d",
xIdx, yIdx, tile_width, tile_height, YLen, CbLen, CrLen);
end_pos = stream_get_pos(data_out);
stream_set_pos(data_out, start_pos + 2);
stream_write_uint32(data_out, 19 + YLen + CbLen + CrLen); /* BlockT.blockLen */
stream_set_pos(data_out, start_pos + 13);
stream_write_uint16(data_out, YLen);
stream_write_uint16(data_out, CbLen);
stream_write_uint16(data_out, CrLen);
stream_set_pos(data_out, end_pos);
}
static void rfx_compose_message_tileset(RFX_CONTEXT* context, STREAM* data_out,
uint8* image_data, int width, int height, int rowstride)
{
int size;
int start_pos, end_pos;
int i;
int numQuants;
const uint32* quantVals;
const uint32* quantValsPtr;
int quantIdxY;
int quantIdxCb;
int quantIdxCr;
int numTiles;
int numTilesX;
int numTilesY;
int xIdx;
int yIdx;
int tilesDataSize;
if (context->num_quants == 0)
{
numQuants = 1;
quantVals = rfx_default_quantization_values;
quantIdxY = 0;
quantIdxCb = 0;
quantIdxCr = 0;
}
else
{
numQuants = context->num_quants;
quantVals = context->quants;
quantIdxY = context->quant_idx_y;
quantIdxCb = context->quant_idx_cb;
quantIdxCr = context->quant_idx_cr;
}
numTilesX = (width + 63) / 64;
numTilesY = (height + 63) / 64;
numTiles = numTilesX * numTilesY;
size = 22 + numQuants * 5;
stream_check_size(data_out, size);
start_pos = stream_get_pos(data_out);
stream_write_uint16(data_out, WBT_EXTENSION); /* CodecChannelT.blockType */
stream_seek_uint32(data_out); /* set CodecChannelT.blockLen later */
stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */
stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */
stream_write_uint16(data_out, CBT_TILESET); /* subtype */
stream_write_uint16(data_out, 0); /* idx */
stream_write_uint16(data_out, context->properties); /* properties */
stream_write_uint8(data_out, numQuants); /* numQuants */
stream_write_uint8(data_out, 0x40); /* tileSize */
stream_write_uint16(data_out, numTiles); /* numTiles */
stream_seek_uint32(data_out); /* set tilesDataSize later */
quantValsPtr = quantVals;
for (i = 0; i < numQuants * 5; i++)
{
stream_write_uint8(data_out, quantValsPtr[0] + (quantValsPtr[1] << 4));
quantValsPtr += 2;
}
DEBUG_RFX("width:%d height:%d rowstride:%d", width, height, rowstride);
end_pos = stream_get_pos(data_out);
for (yIdx = 0; yIdx < numTilesY; yIdx++)
{
for (xIdx = 0; xIdx < numTilesX; xIdx++)
{
rfx_compose_message_tile(context, data_out,
image_data + yIdx * 64 * rowstride + xIdx * 64 * context->bytes_per_pixel,
xIdx < numTilesX - 1 ? 64 : width - xIdx * 64,
yIdx < numTilesY - 1 ? 64 : height - yIdx * 64,
rowstride, quantVals, quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx);
}
}
tilesDataSize = stream_get_pos(data_out) - end_pos;
size += tilesDataSize;
end_pos = stream_get_pos(data_out);
stream_set_pos(data_out, start_pos + 2);
stream_write_uint32(data_out, size); /* CodecChannelT.blockLen */
stream_set_pos(data_out, start_pos + 18);
stream_write_uint32(data_out, tilesDataSize);
stream_set_pos(data_out, end_pos);
}
static void rfx_compose_message_frame_end(RFX_CONTEXT* context, STREAM* data_out)
{
stream_check_size(data_out, 8);
stream_write_uint16(data_out, WBT_FRAME_END); /* CodecChannelT.blockType */
stream_write_uint32(data_out, 8); /* CodecChannelT.blockLen */
stream_write_uint8(data_out, 1); /* CodecChannelT.codecId */
stream_write_uint8(data_out, 0); /* CodecChannelT.channelId */
}
void rfx_compose_message_data(RFX_CONTEXT* context, STREAM* data_out,
const RFX_RECT* rects, int num_rects, uint8* image_data, int width, int height, int rowstride)
{
rfx_compose_message_frame_begin(context, data_out);
rfx_compose_message_region(context, data_out, rects, num_rects);
rfx_compose_message_tileset(context, data_out, image_data, width, height, rowstride);
rfx_compose_message_frame_end(context, data_out);
}

View File

@ -0,0 +1,85 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Bit Stream
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <freerdp/utils/memory.h>
#include "rfx_bitstream.h"
void rfx_bitstream_attach(RFX_BITSTREAM* bs, uint8* buffer, int nbytes)
{
bs->buffer = buffer;
bs->nbytes = nbytes;
bs->byte_pos = 0;
bs->bits_left = 8;
}
uint16 rfx_bitstream_get_bits(RFX_BITSTREAM* bs, int nbits)
{
int b;
uint16 n = 0;
while (bs->byte_pos < bs->nbytes && nbits > 0)
{
b = nbits;
if (b > bs->bits_left)
b = bs->bits_left;
if (n)
n <<= b;
n |= (bs->buffer[bs->byte_pos] >> (bs->bits_left - b)) & ((1 << b) - 1);
bs->bits_left -= b;
nbits -= b;
if (bs->bits_left == 0)
{
bs->bits_left = 8;
bs->byte_pos++;
}
}
return n;
}
void rfx_bitstream_put_bits(RFX_BITSTREAM* bs, uint16 bits, int nbits)
{
int b;
while (bs->byte_pos < bs->nbytes && nbits > 0)
{
b = nbits;
if (b > bs->bits_left)
b = bs->bits_left;
bs->buffer[bs->byte_pos] |= ((bits >> (nbits - b)) & ((1 << b) - 1)) << (bs->bits_left - b);
bs->bits_left -= b;
nbits -= b;
if (bs->bits_left == 0)
{
bs->bits_left = 8;
bs->byte_pos++;
}
}
}

View File

@ -0,0 +1,42 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Bit Stream
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_BITSTREAM_H
#define __RFX_BITSTREAM_H
#include <freerdp/rfx.h>
struct _RFX_BITSTREAM
{
uint8* buffer;
int nbytes;
int byte_pos;
int bits_left;
};
typedef struct _RFX_BITSTREAM RFX_BITSTREAM;
void rfx_bitstream_attach(RFX_BITSTREAM* bs, uint8* buffer, int nbytes);
uint16 rfx_bitstream_get_bits(RFX_BITSTREAM* bs, int nbits);
void rfx_bitstream_put_bits(RFX_BITSTREAM* bs, uint16 bits, int nbits);
#define rfx_bitstream_eos(_bs) ((_bs)->byte_pos >= (_bs)->nbytes)
#define rfx_bitstream_left(_bs) ((_bs)->byte_pos >= (_bs)->nbytes ? 0 : ((_bs)->nbytes - (_bs)->byte_pos - 1) * 8 + (_bs)->bits_left)
#define rfx_bitstream_get_processed_bytes(_bs) ((_bs)->bits_left < 8 ? (_bs)->byte_pos + 1 : (_bs)->byte_pos)
#endif /* __RFX_BITSTREAM_H */

View File

@ -0,0 +1,59 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - API Header
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_CONSTANTS_H
#define __RFX_CONSTANTS_H
/* sync */
#define WF_MAGIC 0xCACCACCA
#define WF_VERSION_1_0 0x0100
/* blockType */
#define WBT_SYNC 0xCCC0
#define WBT_CODEC_VERSIONS 0xCCC1
#define WBT_CHANNELS 0xCCC2
#define WBT_CONTEXT 0xCCC3
#define WBT_FRAME_BEGIN 0xCCC4
#define WBT_FRAME_END 0xCCC5
#define WBT_REGION 0xCCC6
#define WBT_EXTENSION 0xCCC7
#define CBT_REGION 0xCAC1
#define CBT_TILESET 0xCAC2
#define CBT_TILE 0xCAC3
/* tileSize */
#define CT_TILE_64x64 0x0040
/* properties.flags */
#define CODEC_MODE 0x02
/* properties.cct */
#define COL_CONV_ICT 0x1
/* properties.xft */
#define CLW_XFORM_DWT_53_A 0x1
/* properties.et */
#define CLW_ENTROPY_RLGR1 0x01
#define CLW_ENTROPY_RLGR3 0x04
/* properties.qt */
#define SCALAR_QUANTIZATION 0x1
#endif /* __RFX_CONSTANTS_H */

152
libfreerdp-rfx/rfx_decode.c Normal file
View File

@ -0,0 +1,152 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Decode
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <freerdp/utils/stream.h>
#include "rfx_types.h"
#include "rfx_rlgr.h"
#include "rfx_differential.h"
#include "rfx_quantization.h"
#include "rfx_dwt.h"
#include "rfx_decode.h"
static void rfx_decode_format_rgb(sint16* r_buf, sint16* g_buf, sint16* b_buf,
RFX_PIXEL_FORMAT pixel_format, uint8* dst_buf)
{
sint16* r = r_buf;
sint16* g = g_buf;
sint16* b = b_buf;
uint8* dst = dst_buf;
int i;
switch (pixel_format)
{
case RFX_PIXEL_FORMAT_BGRA:
for (i = 0; i < 4096; i++)
{
*dst++ = (uint8) (*b++);
*dst++ = (uint8) (*g++);
*dst++ = (uint8) (*r++);
*dst++ = 0xFF;
}
break;
case RFX_PIXEL_FORMAT_RGBA:
for (i = 0; i < 4096; i++)
{
*dst++ = (uint8) (*r++);
*dst++ = (uint8) (*g++);
*dst++ = (uint8) (*b++);
*dst++ = 0xFF;
}
break;
case RFX_PIXEL_FORMAT_BGR:
for (i = 0; i < 4096; i++)
{
*dst++ = (uint8) (*b++);
*dst++ = (uint8) (*g++);
*dst++ = (uint8) (*r++);
}
break;
case RFX_PIXEL_FORMAT_RGB:
for (i = 0; i < 4096; i++)
{
*dst++ = (uint8) (*r++);
*dst++ = (uint8) (*g++);
*dst++ = (uint8) (*b++);
}
break;
default:
break;
}
}
#define MINMAX(_v,_l,_h) ((_v) < (_l) ? (_l) : ((_v) > (_h) ? (_h) : (_v)))
void rfx_decode_ycbcr_to_rgb(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf)
{
sint16 y, cb, cr;
sint16 r, g, b;
int i;
for (i = 0; i < 4096; i++)
{
y = y_r_buf[i] + 128;
cb = cb_g_buf[i];
cr = cr_b_buf[i];
r = (y + cr + (cr >> 2) + (cr >> 3) + (cr >> 5));
y_r_buf[i] = MINMAX(r, 0, 255);
g = (y - ((cb >> 2) + (cb >> 4) + (cb >> 5)) - ((cr >> 1) + (cr >> 3) + (cr >> 4) + (cr >> 5)));
cb_g_buf[i] = MINMAX(g, 0, 255);
b = (y + cb + (cb >> 1) + (cb >> 2) + (cb >> 6));
cr_b_buf[i] = MINMAX(b, 0, 255);
}
}
static void rfx_decode_component(RFX_CONTEXT* context, const uint32* quantization_values,
const uint8* data, int size, sint16* buffer)
{
PROFILER_ENTER(context->priv->prof_rfx_decode_component);
PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode);
rfx_rlgr_decode(context->mode, data, size, buffer, 4096);
PROFILER_EXIT(context->priv->prof_rfx_rlgr_decode);
PROFILER_ENTER(context->priv->prof_rfx_differential_decode);
rfx_differential_decode(buffer + 4032, 64);
PROFILER_EXIT(context->priv->prof_rfx_differential_decode);
PROFILER_ENTER(context->priv->prof_rfx_quantization_decode);
context->quantization_decode(buffer, quantization_values);
PROFILER_EXIT(context->priv->prof_rfx_quantization_decode);
PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_decode);
context->dwt_2d_decode(buffer, context->priv->dwt_buffer);
PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_decode);
PROFILER_EXIT(context->priv->prof_rfx_decode_component);
}
void rfx_decode_rgb(RFX_CONTEXT* context, STREAM* data_in,
int y_size, const uint32 * y_quants,
int cb_size, const uint32 * cb_quants,
int cr_size, const uint32 * cr_quants, uint8* rgb_buffer)
{
PROFILER_ENTER(context->priv->prof_rfx_decode_rgb);
rfx_decode_component(context, y_quants, stream_get_tail(data_in), y_size, context->priv->y_r_buffer); /* YData */
stream_seek(data_in, y_size);
rfx_decode_component(context, cb_quants, stream_get_tail(data_in), cb_size, context->priv->cb_g_buffer); /* CbData */
stream_seek(data_in, cb_size);
rfx_decode_component(context, cr_quants, stream_get_tail(data_in), cr_size, context->priv->cr_b_buffer); /* CrData */
stream_seek(data_in, cr_size);
PROFILER_ENTER(context->priv->prof_rfx_decode_ycbcr_to_rgb);
context->decode_ycbcr_to_rgb(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer);
PROFILER_EXIT(context->priv->prof_rfx_decode_ycbcr_to_rgb);
PROFILER_ENTER(context->priv->prof_rfx_decode_format_rgb);
rfx_decode_format_rgb(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer,
context->pixel_format, rgb_buffer);
PROFILER_EXIT(context->priv->prof_rfx_decode_format_rgb);
PROFILER_EXIT(context->priv->prof_rfx_decode_rgb);
}

View File

@ -0,0 +1,32 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Decode
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_DECODE_H
#define __RFX_DECODE_H
#include <freerdp/rfx.h>
void rfx_decode_ycbcr_to_rgb(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf);
void rfx_decode_rgb(RFX_CONTEXT* context, STREAM* data_in,
int y_size, const uint32 * y_quants,
int cb_size, const uint32 * cb_quants,
int cr_size, const uint32 * cr_quants, uint8* rgb_buffer);
#endif /* __RFX_DECODE_H */

View File

@ -0,0 +1,47 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Differential Encoding
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rfx_differential.h"
void rfx_differential_decode(sint16* buffer, int buffer_size)
{
sint16* src;
sint16* dst;
for (src = buffer, dst = buffer + 1; buffer_size > 1; src++, dst++, buffer_size--)
{
*dst += *src;
}
}
void rfx_differential_encode(sint16* buffer, int buffer_size)
{
sint16 n1, n2;
sint16* dst;
for (n1 = *buffer, dst = buffer + 1; buffer_size > 1; dst++, buffer_size--)
{
n2 = *dst;
*dst -= n1;
n1 = n2;
}
}

View File

@ -0,0 +1,28 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Differential Encoding
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_DIFFERENTIAL_H
#define __RFX_DIFFERENTIAL_H
#include <freerdp/rfx.h>
void rfx_differential_decode(sint16* buffer, int buffer_size);
void rfx_differential_encode(sint16* buffer, int buffer_size);
#endif /* __RFX_DIFFERENTIAL_H */

194
libfreerdp-rfx/rfx_dwt.c Normal file
View File

@ -0,0 +1,194 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - DWT
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rfx_dwt.h"
static void rfx_dwt_2d_decode_block(sint16* buffer, sint16* idwt, int subband_width)
{
sint16 *dst, *l, *h;
sint16 *l_dst, *h_dst;
sint16 *hl, *lh, *hh, *ll;
int total_width;
int x, y;
int n;
total_width = subband_width << 1;
/* Inverse DWT in horizontal direction, results in 2 sub-bands in L, H order in tmp buffer idwt. */
/* The 4 sub-bands are stored in HL(0), LH(1), HH(2), LL(3) order. */
/* The lower part L uses LL(3) and HL(0). */
/* The higher part H uses LH(1) and HH(2). */
ll = buffer + subband_width * subband_width * 3;
hl = buffer;
l_dst = idwt;
lh = buffer + subband_width * subband_width;
hh = buffer + subband_width * subband_width * 2;
h_dst = idwt + subband_width * subband_width * 2;
for (y = 0; y < subband_width; y++)
{
/* Even coefficients */
l_dst[0] = ll[0] - ((hl[0] + hl[0] + 1) >> 1);
h_dst[0] = lh[0] - ((hh[0] + hh[0] + 1) >> 1);
for (n = 1; n < subband_width; n++)
{
x = n << 1;
l_dst[x] = ll[n] - ((hl[n-1] + hl[n] + 1) >> 1);
h_dst[x] = lh[n] - ((hh[n-1] + hh[n] + 1) >> 1);
}
/* Odd coefficients */
for (n = 0; n < subband_width-1; n++)
{
x = n << 1;
l_dst[x + 1] = (hl[n] << 1) + ((l_dst[x] + l_dst[x + 2]) >> 1);
h_dst[x + 1] = (hh[n] << 1) + ((h_dst[x] + h_dst[x + 2]) >> 1);
}
x = n << 1;
l_dst[x + 1] = (hl[n] << 1) + (l_dst[x]);
h_dst[x + 1] = (hh[n] << 1) + (h_dst[x]);
ll += subband_width;
hl += subband_width;
l_dst += total_width;
lh += subband_width;
hh += subband_width;
h_dst += total_width;
}
/* Inverse DWT in vertical direction, results are stored in original buffer. */
for (x = 0; x < total_width; x++)
{
/* Even coefficients */
for (n = 0; n < subband_width; n++)
{
y = n << 1;
dst = buffer + y * total_width + x;
l = idwt + n * total_width + x;
h = l + subband_width * total_width;
dst[0] = *l - (((n > 0 ? *(h - total_width) : *h) + (*h) + 1) >> 1);
}
/* Odd coefficients */
for (n = 0; n < subband_width; n++)
{
y = n << 1;
dst = buffer + y * total_width + x;
l = idwt + n * total_width + x;
h = l + subband_width * total_width;
dst[total_width] = (*h << 1) + ((dst[0] + dst[n < subband_width - 1 ? 2 * total_width : 0]) >> 1);
}
}
}
void rfx_dwt_2d_decode(sint16* buffer, sint16* dwt_buffer)
{
rfx_dwt_2d_decode_block(buffer + 3840, dwt_buffer, 8);
rfx_dwt_2d_decode_block(buffer + 3072, dwt_buffer, 16);
rfx_dwt_2d_decode_block(buffer, dwt_buffer, 32);
}
static void rfx_dwt_2d_encode_block(sint16* buffer, sint16* dwt, int subband_width)
{
sint16 *src, *l, *h;
sint16 *l_src, *h_src;
sint16 *hl, *lh, *hh, *ll;
int total_width;
int x, y;
int n;
total_width = subband_width << 1;
/* DWT in vertical direction, results in 2 sub-bands in L, H order in tmp buffer dwt. */
for (x = 0; x < total_width; x++)
{
for (n = 0; n < subband_width; n++)
{
y = n << 1;
l = dwt + n * total_width + x;
h = l + subband_width * total_width;
src = buffer + y * total_width + x;
/* H */
*h = (src[total_width] - ((src[0] + src[n < subband_width - 1 ? 2 * total_width : total_width]) >> 1)) >> 1;
/* L */
*l = src[0] + (n == 0 ? *h : (*(h - total_width) + *h) >> 1);
}
}
/* DWT in horizontal direction, results in 4 sub-bands in HL(0), LH(1), HH(2), LL(3) order, stored in original buffer. */
/* The lower part L generates LL(3) and HL(0). */
/* The higher part H generates LH(1) and HH(2). */
ll = buffer + subband_width * subband_width * 3;
hl = buffer;
l_src = dwt;
lh = buffer + subband_width * subband_width;
hh = buffer + subband_width * subband_width * 2;
h_src = dwt + subband_width * subband_width * 2;
for (y = 0; y < subband_width; y++)
{
/* L */
for (n = 0; n < subband_width; n++)
{
x = n << 1;
/* HL */
hl[n] = (l_src[x + 1] - ((l_src[x] + l_src[n < subband_width - 1 ? x + 2 : x]) >> 1)) >> 1;
/* LL */
ll[n] = l_src[x] + (n == 0 ? hl[n] : (hl[n - 1] + hl[n]) >> 1);
}
/* H */
for (n = 0; n < subband_width; n++)
{
x = n << 1;
/* HH */
hh[n] = (h_src[x + 1] - ((h_src[x] + h_src[n < subband_width - 1 ? x + 2 : x]) >> 1)) >> 1;
/* LH */
lh[n] = h_src[x] + (n == 0 ? hh[n] : (hh[n - 1] + hh[n]) >> 1);
}
ll += subband_width;
hl += subband_width;
l_src += total_width;
lh += subband_width;
hh += subband_width;
h_src += total_width;
}
}
void rfx_dwt_2d_encode(sint16* buffer, sint16* dwt_buffer)
{
rfx_dwt_2d_encode_block(buffer, dwt_buffer, 32);
rfx_dwt_2d_encode_block(buffer + 3072, dwt_buffer, 16);
rfx_dwt_2d_encode_block(buffer + 3840, dwt_buffer, 8);
}

28
libfreerdp-rfx/rfx_dwt.h Normal file
View File

@ -0,0 +1,28 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - DWT
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_DWT_H
#define __RFX_DWT_H
#include <freerdp/rfx.h>
void rfx_dwt_2d_decode(sint16* buffer, sint16* dwt_buffer);
void rfx_dwt_2d_encode(sint16* buffer, sint16* dwt_buffer);
#endif /* __RFX_DWT_H */

187
libfreerdp-rfx/rfx_encode.c Normal file
View File

@ -0,0 +1,187 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Encode
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rfx_types.h"
#include "rfx_rlgr.h"
#include "rfx_differential.h"
#include "rfx_quantization.h"
#include "rfx_dwt.h"
#include "rfx_encode.h"
#define MINMAX(_v,_l,_h) ((_v) < (_l) ? (_l) : ((_v) > (_h) ? (_h) : (_v)))
static void rfx_encode_format_rgb(const uint8* rgb_data, int width, int height, int rowstride,
RFX_PIXEL_FORMAT pixel_format, sint16* r_buf, sint16* g_buf, sint16* b_buf)
{
int x, y;
int x_exceed;
int y_exceed;
const uint8* src;
x_exceed = 64 - width;
y_exceed = 64 - height;
for (y = 0; y < height; y++)
{
src = rgb_data + y * rowstride;
switch (pixel_format)
{
case RFX_PIXEL_FORMAT_BGRA:
for (x = 0; x < width; x++)
{
*b_buf++ = (sint16) (*src++);
*g_buf++ = (sint16) (*src++);
*r_buf++ = (sint16) (*src++);
src++;
}
break;
case RFX_PIXEL_FORMAT_RGBA:
for (x = 0; x < width; x++)
{
*r_buf++ = (sint16) (*src++);
*g_buf++ = (sint16) (*src++);
*b_buf++ = (sint16) (*src++);
src++;
}
break;
case RFX_PIXEL_FORMAT_BGR:
for (x = 0; x < width; x++)
{
*b_buf++ = (sint16) (*src++);
*g_buf++ = (sint16) (*src++);
*r_buf++ = (sint16) (*src++);
}
break;
case RFX_PIXEL_FORMAT_RGB:
for (x = 0; x < width; x++)
{
*r_buf++ = (sint16) (*src++);
*g_buf++ = (sint16) (*src++);
*b_buf++ = (sint16) (*src++);
}
break;
default:
break;
}
/* Fill the horizontal region outside of 64x64 tile size to 0 in order to be better compressed. */
if (x_exceed > 0)
{
memset(r_buf, 0, x_exceed * sizeof(sint16));
memset(g_buf, 0, x_exceed * sizeof(sint16));
memset(b_buf, 0, x_exceed * sizeof(sint16));
r_buf += x_exceed;
g_buf += x_exceed;
b_buf += x_exceed;
}
}
/* Fill the vertical region outside of 64x64 tile size to 0 in order to be better compressed. */
if (y_exceed > 0)
{
memset(r_buf, 0, y_exceed * 64 * sizeof(sint16));
memset(g_buf, 0, y_exceed * 64 * sizeof(sint16));
memset(b_buf, 0, y_exceed * 64 * sizeof(sint16));
}
}
void rfx_encode_rgb_to_ycbcr(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf)
{
sint16 y, cb, cr;
sint16 r, g, b;
int i;
for (i = 0; i < 4096; i++)
{
r = y_r_buf[i];
g = cb_g_buf[i];
b = cr_b_buf[i];
y = ((r >> 2) + (r >> 5) + (r >> 6)) + ((g >> 1) + (g >> 4) + (g >> 6) + (g >> 7)) + ((b >> 4) + (b >> 5) + (b >> 6));
y_r_buf[i] = MINMAX(y, 0, 255) - 128;
cb = 0 - ((r >> 3) + (r >> 5) + (r >> 7)) - ((g >> 2) + (g >> 4) + (g >> 6)) + (b >> 1);
cb_g_buf[i] = MINMAX(cb, -128, 127);
cr = (r >> 1) - ((g >> 2) + (g >> 3) + (g >> 5) + (g >> 7)) - ((b >> 4) + (b >> 6));
cr_b_buf[i] = MINMAX(cr, -128, 127);
}
}
static void rfx_encode_component(RFX_CONTEXT* context, const uint32* quantization_values,
sint16* data, uint8* buffer, int buffer_size, int* size)
{
PROFILER_ENTER(context->priv->prof_rfx_encode_component);
PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_encode);
context->dwt_2d_encode(data, context->priv->dwt_buffer);
PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_encode);
PROFILER_ENTER(context->priv->prof_rfx_quantization_encode);
context->quantization_encode(data, quantization_values);
PROFILER_EXIT(context->priv->prof_rfx_quantization_encode);
PROFILER_ENTER(context->priv->prof_rfx_differential_encode);
rfx_differential_encode(data + 4032, 64);
PROFILER_EXIT(context->priv->prof_rfx_differential_encode);
PROFILER_ENTER(context->priv->prof_rfx_rlgr_encode);
*size = rfx_rlgr_encode(context->mode, data, 4096, buffer, buffer_size);
PROFILER_EXIT(context->priv->prof_rfx_rlgr_encode);
PROFILER_EXIT(context->priv->prof_rfx_encode_component);
}
void rfx_encode_rgb(RFX_CONTEXT* context, const uint8* rgb_data, int width, int height, int rowstride,
const uint32* y_quants, const uint32* cb_quants, const uint32* cr_quants,
STREAM* data_out, int* y_size, int* cb_size, int* cr_size)
{
sint16* y_r_buffer = context->priv->y_r_buffer;
sint16* cb_g_buffer = context->priv->cb_g_buffer;
sint16* cr_b_buffer = context->priv->cr_b_buffer;
PROFILER_ENTER(context->priv->prof_rfx_encode_rgb);
PROFILER_ENTER(context->priv->prof_rfx_encode_format_rgb);
rfx_encode_format_rgb(rgb_data, width, height, rowstride,
context->pixel_format, y_r_buffer, cb_g_buffer, cr_b_buffer);
PROFILER_EXIT(context->priv->prof_rfx_encode_format_rgb);
PROFILER_ENTER(context->priv->prof_rfx_encode_rgb_to_ycbcr);
context->encode_rgb_to_ycbcr(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer);
PROFILER_EXIT(context->priv->prof_rfx_encode_rgb_to_ycbcr);
/* Ensure the buffer is reasonably large enough */
stream_check_size(data_out, 4096);
rfx_encode_component(context, y_quants, context->priv->y_r_buffer,
stream_get_tail(data_out), stream_get_left(data_out), y_size);
stream_seek(data_out, *y_size);
stream_check_size(data_out, 4096);
rfx_encode_component(context, cb_quants, context->priv->cb_g_buffer,
stream_get_tail(data_out), stream_get_left(data_out), cb_size);
stream_seek(data_out, *cb_size);
stream_check_size(data_out, 4096);
rfx_encode_component(context, cr_quants, context->priv->cr_b_buffer,
stream_get_tail(data_out), stream_get_left(data_out), cr_size);
stream_seek(data_out, *cr_size);
PROFILER_EXIT(context->priv->prof_rfx_encode_rgb);
}

View File

@ -0,0 +1,32 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Encode
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_ENCODE_H
#define __RFX_ENCODE_H
#include <freerdp/rfx.h>
void rfx_encode_rgb_to_ycbcr(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf);
void rfx_encode_rgb(RFX_CONTEXT* context, const uint8* rgb_data, int width, int height, int rowstride,
const uint32* y_quants, const uint32* cb_quants, const uint32* cr_quants,
STREAM* data_out, int* y_size, int* cb_size, int* cr_size);
#endif

112
libfreerdp-rfx/rfx_pool.c Normal file
View File

@ -0,0 +1,112 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Memory Pool
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <freerdp/utils/memory.h>
#include "rfx_pool.h"
RFX_POOL* rfx_pool_new()
{
RFX_POOL* pool;
pool = xnew(RFX_POOL);
pool->size = 64;
pool->tiles = (RFX_TILE**) xzalloc(sizeof(RFX_TILE*) * pool->size);
return pool;
}
void rfx_pool_free(RFX_POOL* pool)
{
int i;
RFX_TILE* tile;
for (i = 0; i < pool->count; i++)
{
tile = pool->tiles[i];
if (tile != NULL)
{
if (tile->data != NULL)
xfree(tile->data);
xfree(tile);
}
}
xfree(pool->tiles);
xfree(pool);
}
void rfx_pool_put_tile(RFX_POOL* pool, RFX_TILE* tile)
{
if (pool->count >= pool->size)
{
pool->size *= 2;
pool->tiles = (RFX_TILE**) xrealloc((void*) pool->tiles, sizeof(RFX_TILE*) * pool->size);
}
pool->tiles[(pool->count)++] = tile;
}
RFX_TILE* rfx_pool_get_tile(RFX_POOL* pool)
{
RFX_TILE* tile;
if (pool->count < 1)
{
tile = xnew(RFX_TILE);
tile->data = (uint8*) xmalloc(4096 * 4); /* 64x64 * 4 */
}
else
{
tile = pool->tiles[--(pool->count)];
}
return tile;
}
void rfx_pool_put_tiles(RFX_POOL* pool, RFX_TILE** tiles, int count)
{
int i;
for (i = 0; i < count; i++)
{
rfx_pool_put_tile(pool, tiles[i]);
}
}
RFX_TILE** rfx_pool_get_tiles(RFX_POOL* pool, int count)
{
int i;
RFX_TILE** tiles;
tiles = (RFX_TILE**) xmalloc(sizeof(RFX_TILE*) * count);
for (i = 0; i < count; i++)
{
tiles[i] = rfx_pool_get_tile(pool);
}
return tiles;
}

40
libfreerdp-rfx/rfx_pool.h Normal file
View File

@ -0,0 +1,40 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Memory Pool
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_POOL_H
#define __RFX_POOL_H
#include <freerdp/rfx.h>
struct _RFX_POOL
{
int size;
int count;
RFX_TILE** tiles;
};
typedef struct _RFX_POOL RFX_POOL;
RFX_POOL* rfx_pool_new();
void rfx_pool_free(RFX_POOL* pool);
void rfx_pool_put_tile(RFX_POOL* pool, RFX_TILE* tile);
RFX_TILE* rfx_pool_get_tile(RFX_POOL* pool);
void rfx_pool_put_tiles(RFX_POOL* pool, RFX_TILE** tiles, int count);
RFX_TILE** rfx_pool_get_tiles(RFX_POOL* pool, int count);
#endif /* __RFX_POOL_H */

View File

@ -0,0 +1,76 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Quantization
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rfx_quantization.h"
static void rfx_quantization_decode_block(sint16* buffer, int buffer_size, uint32 factor)
{
sint16* dst;
if (factor <= 6)
return;
factor -= 6;
for (dst = buffer; buffer_size > 0; dst++, buffer_size--)
{
*dst <<= factor;
}
}
void rfx_quantization_decode(sint16* buffer, const uint32* quantization_values)
{
rfx_quantization_decode_block(buffer, 1024, quantization_values[8]); /* HL1 */
rfx_quantization_decode_block(buffer + 1024, 1024, quantization_values[7]); /* LH1 */
rfx_quantization_decode_block(buffer + 2048, 1024, quantization_values[9]); /* HH1 */
rfx_quantization_decode_block(buffer + 3072, 256, quantization_values[5]); /* HL2 */
rfx_quantization_decode_block(buffer + 3328, 256, quantization_values[4]); /* LH2 */
rfx_quantization_decode_block(buffer + 3584, 256, quantization_values[6]); /* HH2 */
rfx_quantization_decode_block(buffer + 3840, 64, quantization_values[2]); /* HL3 */
rfx_quantization_decode_block(buffer + 3904, 64, quantization_values[1]); /* LH3 */
rfx_quantization_decode_block(buffer + 3868, 64, quantization_values[3]); /* HH3 */
rfx_quantization_decode_block(buffer + 4032, 64, quantization_values[0]); /* LL3 */
}
static void rfx_quantization_encode_block(sint16* buffer, int buffer_size, uint32 factor)
{
sint16* dst;
if (factor <= 6)
return;
factor -= 6;
for (dst = buffer; buffer_size > 0; dst++, buffer_size--)
{
*dst >>= factor;
}
}
void rfx_quantization_encode(sint16* buffer, const uint32* quantization_values)
{
rfx_quantization_encode_block(buffer, 1024, quantization_values[8]); /* HL1 */
rfx_quantization_encode_block(buffer + 1024, 1024, quantization_values[7]); /* LH1 */
rfx_quantization_encode_block(buffer + 2048, 1024, quantization_values[9]); /* HH1 */
rfx_quantization_encode_block(buffer + 3072, 256, quantization_values[5]); /* HL2 */
rfx_quantization_encode_block(buffer + 3328, 256, quantization_values[4]); /* LH2 */
rfx_quantization_encode_block(buffer + 3584, 256, quantization_values[6]); /* HH2 */
rfx_quantization_encode_block(buffer + 3840, 64, quantization_values[2]); /* HL3 */
rfx_quantization_encode_block(buffer + 3904, 64, quantization_values[1]); /* LH3 */
rfx_quantization_encode_block(buffer + 3868, 64, quantization_values[3]); /* HH3 */
rfx_quantization_encode_block(buffer + 4032, 64, quantization_values[0]); /* LL3 */
}

View File

@ -0,0 +1,28 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - Quantization
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_QUANTIZATION_H
#define __RFX_QUANTIZATION_H
#include <freerdp/rfx.h>
void rfx_quantization_decode(sint16* buffer, const uint32* quantization_values);
void rfx_quantization_encode(sint16* buffer, const uint32* quantization_values);
#endif /* __RFX_QUANTIZATION_H */

428
libfreerdp-rfx/rfx_rlgr.c Normal file
View File

@ -0,0 +1,428 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - RLGR
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This implementation of RLGR refers to
* [MS-RDPRFX] 3.1.8.1.7.3 RLGR1/RLGR3 Pseudocode
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <freerdp/utils/memory.h>
#include "rfx_bitstream.h"
#include "rfx_rlgr.h"
/* Constants used within the RLGR1/RLGR3 algorithm */
#define KPMAX (80) /* max value for kp or krp */
#define LSGR (3) /* shift count to convert kp to k */
#define UP_GR (4) /* increase in kp after a zero run in RL mode */
#define DN_GR (6) /* decrease in kp after a nonzero symbol in RL mode */
#define UQ_GR (3) /* increase in kp after nonzero symbol in GR mode */
#define DQ_GR (3) /* decrease in kp after zero symbol in GR mode */
/* Gets (returns) the next nBits from the bitstream */
#define GetBits(nBits) rfx_bitstream_get_bits(bs, nBits)
/* From current output pointer, write "value", check and update buffer_size */
#define WriteValue(value) \
{ \
if (buffer_size > 0) \
*dst++ = (value); \
buffer_size--; \
}
/* From current output pointer, write next nZeroes terms with value 0, check and update buffer_size */
#define WriteZeroes(nZeroes) \
{ \
int nZeroesWritten = (nZeroes); \
if (nZeroesWritten > buffer_size) \
nZeroesWritten = buffer_size; \
if (nZeroesWritten > 0) \
{ \
memset(dst, 0, nZeroesWritten * sizeof(sint16)); \
dst += nZeroesWritten; \
} \
buffer_size -= (nZeroes); \
}
/* Returns the least number of bits required to represent a given value */
#define GetMinBits(_val, _nbits) \
{ \
uint32 _v = _val; \
_nbits = 0; \
while (_v) \
{ \
_v >>= 1; \
_nbits++; \
} \
}
/* Converts from (2 * magnitude - sign) to integer */
#define GetIntFrom2MagSign(twoMs) (((twoMs) & 1) ? -1 * (sint16)(((twoMs) + 1) >> 1) : (sint16)((twoMs) >> 1))
/*
* Update the passed parameter and clamp it to the range [0, KPMAX]
* Return the value of parameter right-shifted by LSGR
*/
#define UpdateParam(_param, _deltaP, _k) \
{ \
_param += _deltaP; \
if (_param > KPMAX) \
_param = KPMAX; \
if (_param < 0) \
_param = 0; \
_k = (_param >> LSGR); \
}
/* Outputs the Golomb/Rice encoding of a non-negative integer */
#define GetGRCode(krp, kr) rfx_rlgr_get_gr_code(bs, krp, kr)
static uint16 rfx_rlgr_get_gr_code(RFX_BITSTREAM* bs, int* krp, int* kr)
{
int vk;
uint16 mag;
/* chew up/count leading 1s and escape 0 */
for (vk = 0; GetBits(1) == 1;)
vk++;
/* get next *kr bits, and combine with leading 1s */
mag = (vk << *kr) | GetBits(*kr);
/* adjust krp and kr based on vk */
if (!vk)
{
UpdateParam(*krp, -2, *kr);
}
else if (vk != 1)
{
/* at 1, no change! */
UpdateParam(*krp, vk, *kr);
}
return mag;
}
int rfx_rlgr_decode(RLGR_MODE mode, const uint8* data, int data_size, sint16* buffer, int buffer_size)
{
int k;
int kp;
int kr;
int krp;
sint16* dst;
RFX_BITSTREAM* bs;
bs = xnew(RFX_BITSTREAM);
rfx_bitstream_attach(bs, (uint8*) data, data_size);
dst = buffer;
/* initialize the parameters */
k = 1;
kp = k << LSGR;
kr = 1;
krp = kr << LSGR;
while (!rfx_bitstream_eos(bs) && buffer_size > 0)
{
int run;
if (k)
{
int mag;
uint32 sign;
/* RL MODE */
while (!rfx_bitstream_eos(bs) && GetBits(1) == 0)
{
/* we have an RL escape "0", which translates to a run (1<<k) of zeros */
WriteZeroes(1 << k);
UpdateParam(kp, UP_GR, k); /* raise k and kp up because of zero run */
}
/* next k bits will contain remaining run or zeros */
run = GetBits(k);
WriteZeroes(run);
/* get nonzero value, starting with sign bit and then GRCode for magnitude -1 */
sign = GetBits(1);
/* magnitude - 1 was coded (because it was nonzero) */
mag = (int) GetGRCode(&krp, &kr) + 1;
WriteValue(sign ? -mag : mag);
UpdateParam(kp, -DN_GR, k); /* lower k and kp because of nonzero term */
}
else
{
uint32 mag;
uint32 nIdx;
uint32 val1;
uint32 val2;
/* GR (GOLOMB-RICE) MODE */
mag = GetGRCode(&krp, &kr); /* values coded are 2 * magnitude - sign */
if (mode == RLGR1)
{
if (!mag)
{
WriteValue(0);
UpdateParam(kp, UQ_GR, k); /* raise k and kp due to zero */
}
else
{
WriteValue(GetIntFrom2MagSign(mag));
UpdateParam(kp, -DQ_GR, k); /* lower k and kp due to nonzero */
}
}
else /* mode == RLGR3 */
{
/*
* In GR mode FOR RLGR3, we have encoded the
* sum of two (2 * mag - sign) values
*/
/* maximum possible bits for first term */
GetMinBits(mag, nIdx);
/* decode val1 is first term's (2 * mag - sign) value */
val1 = GetBits(nIdx);
/* val2 is second term's (2 * mag - sign) value */
val2 = mag - val1;
if (val1 && val2)
{
/* raise k and kp if both terms nonzero */
UpdateParam(kp, -2 * DQ_GR, k);
}
else if (!val1 && !val2)
{
/* lower k and kp if both terms zero */
UpdateParam(kp, 2 * UQ_GR, k);
}
WriteValue(GetIntFrom2MagSign(val1));
WriteValue(GetIntFrom2MagSign(val2));
}
}
}
xfree(bs);
return (dst - buffer);
}
/* Returns the next coefficient (a signed int) to encode, from the input stream */
#define GetNextInput(_n) \
{ \
if (data_size > 0) \
{ \
_n = *data++; \
data_size--; \
} \
else \
{ \
_n = 0; \
} \
}
/* Emit bitPattern to the output bitstream */
#define OutputBits(numBits, bitPattern) rfx_bitstream_put_bits(bs, bitPattern, numBits);
/* Emit a bit (0 or 1), count number of times, to the output bitstream */
#define OutputBit(count, bit) \
{ \
uint16 _b = (bit ? 0xFFFF : 0); \
int _c = (count); \
for (; _c > 0; _c -= 16) \
rfx_bitstream_put_bits(bs, _b, (_c > 16 ? 16 : _c)); \
}
/* Converts the input value to (2 * abs(input) - sign(input)), where sign(input) = (input < 0 ? 1 : 0) and returns it */
#define Get2MagSign(input) ((input) >= 0 ? 2 * (input) : -2 * (input) - 1)
/* Outputs the Golomb/Rice encoding of a non-negative integer */
#define CodeGR(krp, val) rfx_rlgr_code_gr(bs, krp, val)
static void rfx_rlgr_code_gr(RFX_BITSTREAM* bs, int* krp, uint16 val)
{
int kr = *krp >> LSGR;
/* unary part of GR code */
uint16 vk = (val) >> kr;
OutputBit(vk, 1);
OutputBit(1, 0);
/* remainder part of GR code, if needed */
if (kr)
{
OutputBits(kr, val & ((1 << kr) - 1));
}
/* update krp, only if it is not equal to 1 */
if (vk == 0)
{
UpdateParam(*krp, -2, kr);
}
else if (vk > 1)
{
UpdateParam(*krp, vk, kr);
}
}
int rfx_rlgr_encode(RLGR_MODE mode, const sint16* data, int data_size, uint8* buffer, int buffer_size)
{
int k;
int kp;
int kr;
int krp;
RFX_BITSTREAM* bs;
int processed_size;
bs = xnew(RFX_BITSTREAM);
rfx_bitstream_attach(bs, buffer, buffer_size);
/* initialize the parameters */
k = 1;
kp = 1 << LSGR;
kr = 1;
krp = 1 << LSGR;
/* process all the input coefficients */
while (data_size > 0)
{
int input;
if (k)
{
int numZeros;
int runmax;
int mag;
int sign;
/* RUN-LENGTH MODE */
/* collect the run of zeros in the input stream */
numZeros = 0;
GetNextInput(input);
while (input == 0 && data_size > 0)
{
numZeros++;
GetNextInput(input);
}
// emit output zeros
runmax = 1 << k;
while (numZeros >= runmax)
{
OutputBit(1, 0); /* output a zero bit */
numZeros -= runmax;
UpdateParam(kp, UP_GR, k); /* update kp, k */
runmax = 1 << k;
}
/* output a 1 to terminate runs */
OutputBit(1, 1);
/* output the remaining run length using k bits */
OutputBits(k, numZeros);
if (input != 0)
{
/* encode the nonzero value using GR coding */
mag = (input < 0 ? -input : input); /* absolute value of input coefficient */
sign = (input < 0 ? 1 : 0); /* sign of input coefficient */
OutputBit(1, sign); /* output the sign bit */
CodeGR(&krp, mag - 1); /* output GR code for (mag - 1) */
UpdateParam(kp, -DN_GR, k);
}
}
else
{
/* GOLOMB-RICE MODE */
if (mode == RLGR1)
{
uint32 twoMs;
/* RLGR1 variant */
/* convert input to (2*magnitude - sign), encode using GR code */
GetNextInput(input);
twoMs = Get2MagSign(input);
CodeGR(&krp, twoMs);
/* update k, kp */
if (twoMs)
{
UpdateParam(kp, UQ_GR, k);
}
else
{
UpdateParam(kp, -DQ_GR, k);
}
}
else /* mode == RLGR3 */
{
uint32 twoMs1;
uint32 twoMs2;
uint32 sum2Ms;
uint32 nIdx;
/* RLGR3 variant */
/* convert the next two input values to (2*magnitude - sign) and */
/* encode their sum using GR code */
GetNextInput(input);
twoMs1 = Get2MagSign(input);
GetNextInput(input);
twoMs2 = Get2MagSign(input);
sum2Ms = twoMs1 + twoMs2;
CodeGR(&krp, sum2Ms);
/* encode binary representation of the first input (twoMs1). */
GetMinBits(sum2Ms, nIdx);
OutputBits(nIdx, twoMs1);
/* update k,kp for the two input values */
if (twoMs1 && twoMs2)
{
UpdateParam(kp, -2 * DQ_GR, k);
}
else if (!twoMs1 && !twoMs2)
{
UpdateParam(kp, 2 * UQ_GR, k);
}
}
}
}
processed_size = rfx_bitstream_get_processed_bytes(bs);
xfree(bs);
return processed_size;
}

28
libfreerdp-rfx/rfx_rlgr.h Normal file
View File

@ -0,0 +1,28 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library - RLGR
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_RLGR_H
#define __RFX_RLGR_H
#include <freerdp/rfx.h>
int rfx_rlgr_decode(RLGR_MODE mode, const uint8* data, int data_size, sint16* buffer, int buffer_size);
int rfx_rlgr_encode(RLGR_MODE mode, const sint16* data, int data_size, uint8* buffer, int buffer_size);
#endif /* __RFX_RLGR_H */

View File

@ -0,0 +1,73 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RemoteFX Codec Library
*
* Copyright 2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __RFX_TYPES_H
#define __RFX_TYPES_H
#include "config.h"
#include <freerdp/utils/debug.h>
#include <freerdp/utils/profiler.h>
#ifdef WITH_DEBUG_RFX
#define DEBUG_RFX(fmt, ...) DEBUG_CLASS(RFX, fmt, ## __VA_ARGS__)
#else
#define DEBUG_RFX(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif
#include "rfx_pool.h"
struct _RFX_CONTEXT_PRIV
{
/* pre-allocated buffers */
RFX_POOL* pool; /* memory pool */
sint16 y_r_mem[4096 + 8]; /* 4096 = 64x64 (+ 8x2 = 16 for mem align) */
sint16 cb_g_mem[4096 + 8]; /* 4096 = 64x64 (+ 8x2 = 16 for mem align) */
sint16 cr_b_mem[4096 + 8]; /* 4096 = 64x64 (+ 8x2 = 16 for mem align) */
sint16* y_r_buffer;
sint16* cb_g_buffer;
sint16* cr_b_buffer;
sint16 dwt_mem[32 * 32 * 2 * 2 + 8]; /* maximum sub-band width is 32 */
sint16* dwt_buffer;
/* profilers */
PROFILER_DEFINE(prof_rfx_decode_rgb);
PROFILER_DEFINE(prof_rfx_decode_component);
PROFILER_DEFINE(prof_rfx_rlgr_decode);
PROFILER_DEFINE(prof_rfx_differential_decode);
PROFILER_DEFINE(prof_rfx_quantization_decode);
PROFILER_DEFINE(prof_rfx_dwt_2d_decode);
PROFILER_DEFINE(prof_rfx_decode_ycbcr_to_rgb);
PROFILER_DEFINE(prof_rfx_decode_format_rgb);
PROFILER_DEFINE(prof_rfx_encode_rgb);
PROFILER_DEFINE(prof_rfx_encode_component);
PROFILER_DEFINE(prof_rfx_rlgr_encode);
PROFILER_DEFINE(prof_rfx_differential_encode);
PROFILER_DEFINE(prof_rfx_quantization_encode);
PROFILER_DEFINE(prof_rfx_dwt_2d_encode);
PROFILER_DEFINE(prof_rfx_encode_rgb_to_ycbcr);
PROFILER_DEFINE(prof_rfx_encode_format_rgb);
};
#endif /* __RFX_TYPES_H */