libfreerdp-rfx: initial migration.
This commit is contained in:
parent
184bfc2482
commit
e414a7d9cc
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -25,5 +25,7 @@
|
||||
#cmakedefine WITH_DEBUG_LICENSE
|
||||
#cmakedefine WITH_DEBUG_GDI
|
||||
#cmakedefine WITH_DEBUG_ASSERT
|
||||
#cmakedefine WITH_DEBUG_RFX
|
||||
#cmakedefine WITH_PROFILER
|
||||
|
||||
#endif
|
||||
|
@ -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)
|
||||
|
@ -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
416
cunit/test_librfx.c
Normal 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
34
cunit/test_librfx.h
Normal 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
134
include/freerdp/rfx.h
Normal 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 */
|
@ -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) \
|
||||
|
46
libfreerdp-rfx/CMakeLists.txt
Normal file
46
libfreerdp-rfx/CMakeLists.txt
Normal 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
819
libfreerdp-rfx/librfx.c
Normal 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);
|
||||
}
|
85
libfreerdp-rfx/rfx_bitstream.c
Normal file
85
libfreerdp-rfx/rfx_bitstream.c
Normal 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++;
|
||||
}
|
||||
}
|
||||
}
|
42
libfreerdp-rfx/rfx_bitstream.h
Normal file
42
libfreerdp-rfx/rfx_bitstream.h
Normal 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 */
|
59
libfreerdp-rfx/rfx_constants.h
Normal file
59
libfreerdp-rfx/rfx_constants.h
Normal 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
152
libfreerdp-rfx/rfx_decode.c
Normal 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);
|
||||
}
|
32
libfreerdp-rfx/rfx_decode.h
Normal file
32
libfreerdp-rfx/rfx_decode.h
Normal 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 */
|
47
libfreerdp-rfx/rfx_differential.c
Normal file
47
libfreerdp-rfx/rfx_differential.c
Normal 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;
|
||||
}
|
||||
}
|
28
libfreerdp-rfx/rfx_differential.h
Normal file
28
libfreerdp-rfx/rfx_differential.h
Normal 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
194
libfreerdp-rfx/rfx_dwt.c
Normal 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
28
libfreerdp-rfx/rfx_dwt.h
Normal 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
187
libfreerdp-rfx/rfx_encode.c
Normal 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);
|
||||
}
|
32
libfreerdp-rfx/rfx_encode.h
Normal file
32
libfreerdp-rfx/rfx_encode.h
Normal 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
112
libfreerdp-rfx/rfx_pool.c
Normal 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
40
libfreerdp-rfx/rfx_pool.h
Normal 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 */
|
76
libfreerdp-rfx/rfx_quantization.c
Normal file
76
libfreerdp-rfx/rfx_quantization.c
Normal 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 */
|
||||
}
|
28
libfreerdp-rfx/rfx_quantization.h
Normal file
28
libfreerdp-rfx/rfx_quantization.h
Normal 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
428
libfreerdp-rfx/rfx_rlgr.c
Normal 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
28
libfreerdp-rfx/rfx_rlgr.h
Normal 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 */
|
73
libfreerdp-rfx/rfx_types.h
Normal file
73
libfreerdp-rfx/rfx_types.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user