Milestone 5: deliver embedded RDP sessions and lifecycle hardening
This commit is contained in:
+142
@@ -0,0 +1,142 @@
|
||||
# codec
|
||||
|
||||
option(WITH_CURSOR_DUMP "Dump mouse cursor data to binary directory" OFF)
|
||||
if(WITH_CURSOR_DUMP)
|
||||
add_compile_definitions(WITH_CURSOR_DUMP)
|
||||
add_compile_definitions(CURSOR_DUMP_DIR="${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
set(CODEC_SRCS
|
||||
bulk.c
|
||||
bulk.h
|
||||
dsp.c
|
||||
color.c
|
||||
color.h
|
||||
audio.c
|
||||
planar.c
|
||||
bitmap.c
|
||||
interleaved.c
|
||||
progressive.c
|
||||
rfx_bitstream.h
|
||||
rfx_constants.h
|
||||
rfx_decode.c
|
||||
rfx_decode.h
|
||||
rfx_differential.h
|
||||
rfx_dwt.c
|
||||
rfx_dwt.h
|
||||
rfx_encode.c
|
||||
rfx_encode.h
|
||||
rfx_quantization.c
|
||||
rfx_quantization.h
|
||||
rfx_rlgr.c
|
||||
rfx_rlgr.h
|
||||
rfx_types.h
|
||||
rfx.c
|
||||
region.c
|
||||
nsc.c
|
||||
nsc_encode.c
|
||||
nsc_encode.h
|
||||
nsc_types.h
|
||||
ncrush.c
|
||||
xcrush.c
|
||||
mppc.c
|
||||
zgfx.c
|
||||
clear.c
|
||||
jpeg.c
|
||||
h264.c
|
||||
yuv.c
|
||||
)
|
||||
|
||||
set(CODEC_SSE3_SRCS sse/rfx_sse2.c sse/rfx_sse2.h sse/nsc_sse2.c sse/nsc_sse2.h)
|
||||
|
||||
set(CODEC_NEON_SRCS neon/rfx_neon.c neon/rfx_neon.h neon/nsc_neon.c neon/nsc_neon.h)
|
||||
|
||||
# Append initializers
|
||||
set(CODEC_LIBS "")
|
||||
list(APPEND CODEC_SRCS ${CODEC_SSE3_SRCS})
|
||||
list(APPEND CODEC_SRCS ${CODEC_NEON_SRCS})
|
||||
|
||||
include(CompilerDetect)
|
||||
include(DetectIntrinsicSupport)
|
||||
|
||||
if(WITH_SIMD)
|
||||
set_simd_source_file_properties("sse3" ${CODEC_SSE3_SRCS})
|
||||
set_simd_source_file_properties("neon" ${CODEC_NEON_SRCS})
|
||||
endif()
|
||||
|
||||
if(WITH_DSP_FFMPEG)
|
||||
set(CODEC_SRCS ${CODEC_SRCS} dsp_ffmpeg.c dsp_ffmpeg.h)
|
||||
include_directories(SYSTEM ${FFMPEG_INCLUDE_DIRS})
|
||||
list(APPEND CODEC_LIBS ${FFMPEG_LIBRARIES})
|
||||
freerdp_pc_add_requires_private("libavfilter;libavformat;libavcodec;libavutil;libswresample")
|
||||
endif(WITH_DSP_FFMPEG)
|
||||
|
||||
if(WITH_SOXR)
|
||||
list(APPEND CODEC_LIBS ${SOXR_LIBRARIES})
|
||||
include_directories(SYSTEM ${SOXR_INCLUDE_DIR})
|
||||
freerdp_pc_add_requires_private("soxr")
|
||||
endif(WITH_SOXR)
|
||||
|
||||
if(GSM_FOUND)
|
||||
list(APPEND CODEC_LIBS ${GSM_LIBRARIES})
|
||||
include_directories(SYSTEM ${GSM_INCLUDE_DIRS})
|
||||
freerdp_pc_add_library_private("gsm")
|
||||
endif()
|
||||
|
||||
if(LAME_FOUND)
|
||||
list(APPEND CODEC_LIBS ${LAME_LIBRARIES})
|
||||
include_directories(SYSTEM ${LAME_INCLUDE_DIRS})
|
||||
freerdp_pc_add_requires_private("lame")
|
||||
endif()
|
||||
|
||||
if(WITH_FDK_AAC)
|
||||
list(APPEND CODEC_SRCS dsp_fdk_impl.c dsp_fdk_impl.h dsp_fdk_aac.c dsp_fdk_aac.h)
|
||||
freerdp_pc_add_requires_private("fdk-aac")
|
||||
endif()
|
||||
|
||||
if(FAAD2_FOUND)
|
||||
list(APPEND CODEC_LIBS ${FAAD2_LIBRARIES})
|
||||
include_directories(SYSTEM ${FAAD2_INCLUDE_DIRS})
|
||||
freerdp_pc_add_requires_private("faad2")
|
||||
endif()
|
||||
|
||||
if(FAAC_FOUND)
|
||||
list(APPEND CODEC_LIBS ${FAAC_LIBRARIES})
|
||||
include_directories(SYSTEM ${FAAC_INCLUDE_DIRS})
|
||||
freerdp_pc_add_requires_private("faac")
|
||||
endif()
|
||||
|
||||
if(WITH_OPENH264)
|
||||
set(CODEC_SRCS ${CODEC_SRCS} h264_openh264.c)
|
||||
include_directories(SYSTEM ${OPENH264_INCLUDE_DIR})
|
||||
if(NOT WITH_OPENH264_LOADING)
|
||||
list(APPEND CODEC_LIBS ${OPENH264_LIBRARIES})
|
||||
freerdp_pc_add_requires_private("openh264")
|
||||
endif(NOT WITH_OPENH264_LOADING)
|
||||
endif()
|
||||
|
||||
if(WITH_VIDEO_FFMPEG)
|
||||
set(CODEC_SRCS ${CODEC_SRCS} h264_ffmpeg.c)
|
||||
include_directories(SYSTEM ${FFMPEG_INCLUDE_DIRS})
|
||||
list(APPEND CODEC_LIBS ${FFMPEG_LIBRARIES})
|
||||
freerdp_pc_add_requires_private("libavfilter;libavformat;libavcodec;libavutil")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND WITH_MEDIA_FOUNDATION)
|
||||
set(CODEC_SRCS ${CODEC_SRCS} h264_mf.c)
|
||||
endif()
|
||||
|
||||
if(ANDROID AND WITH_MEDIACODEC)
|
||||
list(APPEND CODEC_SRCS h264_mediacodec.c)
|
||||
|
||||
find_library(MEDIACODEC mediandk REQUIRED)
|
||||
list(APPEND CODEC_LIBS ${MEDIACODEC})
|
||||
endif()
|
||||
|
||||
add_library(freerdp-codecs OBJECT ${CODEC_SRCS})
|
||||
freerdp_library_add(${CODEC_LIBS})
|
||||
freerdp_object_library_add(freerdp-codecs)
|
||||
|
||||
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Audio Formats
|
||||
*
|
||||
* Copyright 2013 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 <freerdp/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/audio.h>
|
||||
|
||||
#define TAG FREERDP_TAG("codec")
|
||||
|
||||
UINT32 audio_format_compute_time_length(const AUDIO_FORMAT* format, size_t size)
|
||||
{
|
||||
UINT32 mstime = 0;
|
||||
UINT32 wSamples = 0;
|
||||
|
||||
/**
|
||||
* [MSDN-AUDIOFORMAT]:
|
||||
* http://msdn.microsoft.com/en-us/library/ms713497.aspx
|
||||
*/
|
||||
|
||||
if (format->wBitsPerSample)
|
||||
{
|
||||
const size_t samples = (size * 8) / format->wBitsPerSample;
|
||||
WINPR_ASSERT(samples <= UINT32_MAX);
|
||||
wSamples = (UINT32)samples;
|
||||
mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
|
||||
}
|
||||
else
|
||||
{
|
||||
mstime = 0;
|
||||
|
||||
if (format->wFormatTag == WAVE_FORMAT_GSM610)
|
||||
{
|
||||
UINT16 nSamplesPerBlock = 0;
|
||||
|
||||
if ((format->cbSize == 2) && (format->data))
|
||||
{
|
||||
nSamplesPerBlock = *((UINT16*)format->data);
|
||||
const size_t samples = (size / format->nBlockAlign) * nSamplesPerBlock;
|
||||
WINPR_ASSERT(samples <= UINT32_MAX);
|
||||
wSamples = (UINT32)samples;
|
||||
mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"audio_format_compute_time_length: invalid WAVE_FORMAT_GSM610 format");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "audio_format_compute_time_length: unknown format %" PRIu16 "",
|
||||
format->wFormatTag);
|
||||
}
|
||||
}
|
||||
|
||||
return mstime;
|
||||
}
|
||||
|
||||
const char* audio_format_get_tag_string(UINT16 wFormatTag)
|
||||
{
|
||||
switch (wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_PCM:
|
||||
return "WAVE_FORMAT_PCM";
|
||||
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
return "WAVE_FORMAT_ADPCM";
|
||||
|
||||
case WAVE_FORMAT_ALAW:
|
||||
return "WAVE_FORMAT_ALAW";
|
||||
|
||||
case WAVE_FORMAT_MULAW:
|
||||
return "WAVE_FORMAT_MULAW";
|
||||
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
return "WAVE_FORMAT_DVI_ADPCM";
|
||||
|
||||
case WAVE_FORMAT_GSM610:
|
||||
return "WAVE_FORMAT_GSM610";
|
||||
|
||||
case WAVE_FORMAT_MSG723:
|
||||
return "WAVE_FORMAT_MSG723";
|
||||
|
||||
case WAVE_FORMAT_DSPGROUP_TRUESPEECH:
|
||||
return "WAVE_FORMAT_DSPGROUP_TRUESPEECH ";
|
||||
|
||||
case WAVE_FORMAT_MPEGLAYER3:
|
||||
return "WAVE_FORMAT_MPEGLAYER3";
|
||||
|
||||
case WAVE_FORMAT_WMAUDIO2:
|
||||
return "WAVE_FORMAT_WMAUDIO2";
|
||||
|
||||
case WAVE_FORMAT_AAC_MS:
|
||||
return "WAVE_FORMAT_AAC_MS";
|
||||
default:
|
||||
return "WAVE_FORMAT_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void audio_format_print(wLog* log, DWORD level, const AUDIO_FORMAT* format)
|
||||
{
|
||||
WLog_Print(log, level,
|
||||
"%s:\t wFormatTag: 0x%04" PRIX16 " nChannels: %" PRIu16 " nSamplesPerSec: %" PRIu32
|
||||
" "
|
||||
"nAvgBytesPerSec: %" PRIu32 " nBlockAlign: %" PRIu16 " wBitsPerSample: %" PRIu16
|
||||
" cbSize: %" PRIu16 "",
|
||||
audio_format_get_tag_string(format->wFormatTag), format->wFormatTag,
|
||||
format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec,
|
||||
format->nBlockAlign, format->wBitsPerSample, format->cbSize);
|
||||
}
|
||||
|
||||
void audio_formats_print(wLog* log, DWORD level, const AUDIO_FORMAT* formats, UINT16 count)
|
||||
{
|
||||
if (formats)
|
||||
{
|
||||
WLog_Print(log, level, "AUDIO_FORMATS (%" PRIu16 ") ={", count);
|
||||
|
||||
for (UINT32 index = 0; index < count; index++)
|
||||
{
|
||||
const AUDIO_FORMAT* format = &formats[index];
|
||||
WLog_Print(log, level, "\t");
|
||||
audio_format_print(log, level, format);
|
||||
}
|
||||
|
||||
WLog_Print(log, level, "}");
|
||||
}
|
||||
}
|
||||
|
||||
BOOL audio_format_read(wStream* s, AUDIO_FORMAT* format)
|
||||
{
|
||||
if (!s || !format)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
|
||||
return FALSE;
|
||||
|
||||
Stream_Read_UINT16(s, format->wFormatTag);
|
||||
Stream_Read_UINT16(s, format->nChannels);
|
||||
Stream_Read_UINT32(s, format->nSamplesPerSec);
|
||||
Stream_Read_UINT32(s, format->nAvgBytesPerSec);
|
||||
Stream_Read_UINT16(s, format->nBlockAlign);
|
||||
Stream_Read_UINT16(s, format->wBitsPerSample);
|
||||
Stream_Read_UINT16(s, format->cbSize);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, format->cbSize))
|
||||
return FALSE;
|
||||
|
||||
format->data = nullptr;
|
||||
|
||||
if (format->cbSize > 0)
|
||||
{
|
||||
format->data = malloc(format->cbSize);
|
||||
|
||||
if (!format->data)
|
||||
return FALSE;
|
||||
|
||||
Stream_Read(s, format->data, format->cbSize);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL audio_format_write(wStream* s, const AUDIO_FORMAT* format)
|
||||
{
|
||||
if (!s || !format)
|
||||
return FALSE;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, 18 + format->cbSize))
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT16(s, format->wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
|
||||
Stream_Write_UINT16(s, format->nChannels); /* nChannels */
|
||||
Stream_Write_UINT32(s, format->nSamplesPerSec); /* nSamplesPerSec */
|
||||
Stream_Write_UINT32(s, format->nAvgBytesPerSec); /* nAvgBytesPerSec */
|
||||
Stream_Write_UINT16(s, format->nBlockAlign); /* nBlockAlign */
|
||||
Stream_Write_UINT16(s, format->wBitsPerSample); /* wBitsPerSample */
|
||||
Stream_Write_UINT16(s, format->cbSize); /* cbSize */
|
||||
|
||||
if (format->cbSize > 0)
|
||||
Stream_Write(s, format->data, format->cbSize);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL audio_format_copy(const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
|
||||
AUDIO_FORMAT* WINPR_RESTRICT dstFormat)
|
||||
{
|
||||
if (!srcFormat || !dstFormat)
|
||||
return FALSE;
|
||||
|
||||
*dstFormat = *srcFormat;
|
||||
|
||||
if (srcFormat->cbSize > 0)
|
||||
{
|
||||
dstFormat->data = malloc(srcFormat->cbSize);
|
||||
|
||||
if (!dstFormat->data)
|
||||
return FALSE;
|
||||
|
||||
memcpy(dstFormat->data, srcFormat->data, dstFormat->cbSize);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL audio_format_compatible(const AUDIO_FORMAT* with, const AUDIO_FORMAT* what)
|
||||
{
|
||||
if (!with || !what)
|
||||
return FALSE;
|
||||
|
||||
if (with->wFormatTag != WAVE_FORMAT_UNKNOWN)
|
||||
{
|
||||
if (with->wFormatTag != what->wFormatTag)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (with->nChannels != 0)
|
||||
{
|
||||
if (with->nChannels != what->nChannels)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (with->nSamplesPerSec != 0)
|
||||
{
|
||||
if (with->nSamplesPerSec != what->nSamplesPerSec)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (with->wBitsPerSample != 0)
|
||||
{
|
||||
if (with->wBitsPerSample != what->wBitsPerSample)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
AUDIO_FORMAT* audio_format_new(void)
|
||||
{
|
||||
return audio_formats_new(1);
|
||||
}
|
||||
|
||||
AUDIO_FORMAT* audio_formats_new(size_t count)
|
||||
{
|
||||
return calloc(count, sizeof(AUDIO_FORMAT));
|
||||
}
|
||||
|
||||
void audio_format_free(AUDIO_FORMAT* format)
|
||||
{
|
||||
if (format)
|
||||
free(format->data);
|
||||
}
|
||||
|
||||
void audio_formats_free(AUDIO_FORMAT* formats, size_t count)
|
||||
{
|
||||
if (formats)
|
||||
{
|
||||
for (size_t index = 0; index < count; index++)
|
||||
{
|
||||
AUDIO_FORMAT* format = &formats[index];
|
||||
audio_format_free(format);
|
||||
}
|
||||
|
||||
free(formats);
|
||||
}
|
||||
}
|
||||
+1115
File diff suppressed because it is too large
Load Diff
+391
@@ -0,0 +1,391 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Bulk Compression
|
||||
*
|
||||
* Copyright 2014 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 <math.h>
|
||||
#include <winpr/assert.h>
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "../core/settings.h"
|
||||
#include "bulk.h"
|
||||
#include "../codec/mppc.h"
|
||||
#include "../codec/ncrush.h"
|
||||
#include "../codec/xcrush.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#define TAG FREERDP_TAG("core")
|
||||
|
||||
//#define WITH_BULK_DEBUG 1
|
||||
|
||||
struct rdp_bulk
|
||||
{
|
||||
ALIGN64 rdpContext* context;
|
||||
ALIGN64 UINT32 CompressionLevel;
|
||||
ALIGN64 UINT16 CompressionMaxSize;
|
||||
ALIGN64 MPPC_CONTEXT* mppcSend;
|
||||
ALIGN64 MPPC_CONTEXT* mppcRecv;
|
||||
ALIGN64 NCRUSH_CONTEXT* ncrushRecv;
|
||||
ALIGN64 NCRUSH_CONTEXT* ncrushSend;
|
||||
ALIGN64 XCRUSH_CONTEXT* xcrushRecv;
|
||||
ALIGN64 XCRUSH_CONTEXT* xcrushSend;
|
||||
ALIGN64 BYTE OutputBuffer[65536];
|
||||
};
|
||||
|
||||
#if defined(WITH_BULK_DEBUG)
|
||||
static inline const char* bulk_get_compression_flags_string(UINT32 flags)
|
||||
{
|
||||
flags &= BULK_COMPRESSION_FLAGS_MASK;
|
||||
|
||||
if (flags == 0)
|
||||
return "PACKET_UNCOMPRESSED";
|
||||
else if (flags == PACKET_COMPRESSED)
|
||||
return "PACKET_COMPRESSED";
|
||||
else if (flags == PACKET_AT_FRONT)
|
||||
return "PACKET_AT_FRONT";
|
||||
else if (flags == PACKET_FLUSHED)
|
||||
return "PACKET_FLUSHED";
|
||||
else if (flags == (PACKET_COMPRESSED | PACKET_AT_FRONT))
|
||||
return "PACKET_COMPRESSED | PACKET_AT_FRONT";
|
||||
else if (flags == (PACKET_COMPRESSED | PACKET_FLUSHED))
|
||||
return "PACKET_COMPRESSED | PACKET_FLUSHED";
|
||||
else if (flags == (PACKET_AT_FRONT | PACKET_FLUSHED))
|
||||
return "PACKET_AT_FRONT | PACKET_FLUSHED";
|
||||
else if (flags == (PACKET_COMPRESSED | PACKET_AT_FRONT | PACKET_FLUSHED))
|
||||
return "PACKET_COMPRESSED | PACKET_AT_FRONT | PACKET_FLUSHED";
|
||||
|
||||
return "PACKET_UNKNOWN";
|
||||
}
|
||||
#endif
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static UINT32 bulk_compression_level(rdpBulk* WINPR_RESTRICT bulk)
|
||||
{
|
||||
WINPR_ASSERT(bulk);
|
||||
WINPR_ASSERT(bulk->context);
|
||||
const rdpSettings* settings = bulk->context->settings;
|
||||
WINPR_ASSERT(settings);
|
||||
bulk->CompressionLevel = (settings->CompressionLevel >= PACKET_COMPR_TYPE_RDP61)
|
||||
? PACKET_COMPR_TYPE_RDP61
|
||||
: settings->CompressionLevel;
|
||||
WINPR_ASSERT(bulk->CompressionLevel <= UINT16_MAX);
|
||||
return bulk->CompressionLevel;
|
||||
}
|
||||
|
||||
static void bulk_update_compression_max_size(rdpBulk* WINPR_RESTRICT bulk)
|
||||
{
|
||||
WINPR_ASSERT(bulk);
|
||||
const UINT32 CompressionLevel = bulk_compression_level(bulk);
|
||||
bulk->CompressionMaxSize = (CompressionLevel < PACKET_COMPR_TYPE_64K) ? 8192 : UINT16_MAX;
|
||||
}
|
||||
UINT16 bulk_compression_max_size(rdpBulk* WINPR_RESTRICT bulk)
|
||||
{
|
||||
bulk_update_compression_max_size(bulk);
|
||||
return bulk->CompressionMaxSize;
|
||||
}
|
||||
|
||||
#if defined(WITH_BULK_DEBUG)
|
||||
static inline int bulk_compress_validate(rdpBulk* bulk, const BYTE* pSrcData, UINT32 SrcSize,
|
||||
const BYTE* pDstData, UINT32 DstSize, UINT32 Flags)
|
||||
{
|
||||
int status;
|
||||
const BYTE* v_pSrcData = nullptr;
|
||||
const BYTE* v_pDstData = nullptr;
|
||||
UINT32 v_SrcSize = 0;
|
||||
UINT32 v_DstSize = 0;
|
||||
UINT32 v_Flags = 0;
|
||||
|
||||
WINPR_ASSERT(bulk);
|
||||
WINPR_ASSERT(pSrcData);
|
||||
WINPR_ASSERT(pDstData);
|
||||
|
||||
v_pSrcData = pDstData;
|
||||
v_SrcSize = DstSize;
|
||||
v_Flags = Flags | bulk->CompressionLevel;
|
||||
status = bulk_decompress(bulk, v_pSrcData, v_SrcSize, &v_pDstData, &v_DstSize, v_Flags);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_DBG(TAG, "compression/decompression failure");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (v_DstSize != SrcSize)
|
||||
{
|
||||
WLog_DBG(TAG,
|
||||
"compression/decompression size mismatch: Actual: %" PRIu32 ", Expected: %" PRIu32
|
||||
"",
|
||||
v_DstSize, SrcSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(v_pDstData, pSrcData, SrcSize) != 0)
|
||||
{
|
||||
WLog_DBG(TAG, "compression/decompression input/output mismatch! flags: 0x%08" PRIX32 "",
|
||||
v_Flags);
|
||||
#if 1
|
||||
WLog_DBG(TAG, "Actual:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, v_pDstData, SrcSize);
|
||||
WLog_DBG(TAG, "Expected:");
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, pSrcData, SrcSize);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
int bulk_decompress(rdpBulk* WINPR_RESTRICT bulk, const BYTE* WINPR_RESTRICT pSrcData,
|
||||
UINT32 SrcSize, const BYTE** WINPR_RESTRICT ppDstData,
|
||||
UINT32* WINPR_RESTRICT pDstSize, UINT32 flags)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
WINPR_ASSERT(bulk);
|
||||
WINPR_ASSERT(bulk->context);
|
||||
WINPR_ASSERT(pSrcData);
|
||||
WINPR_ASSERT(ppDstData);
|
||||
WINPR_ASSERT(pDstSize);
|
||||
|
||||
rdpMetrics* metrics = bulk->context->metrics;
|
||||
WINPR_ASSERT(metrics);
|
||||
|
||||
bulk_update_compression_max_size(bulk);
|
||||
const UINT32 type = flags & BULK_COMPRESSION_TYPE_MASK;
|
||||
|
||||
if (flags & BULK_COMPRESSION_FLAGS_MASK)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case PACKET_COMPR_TYPE_8K:
|
||||
mppc_set_compression_level(bulk->mppcRecv, 0);
|
||||
status =
|
||||
mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
|
||||
break;
|
||||
|
||||
case PACKET_COMPR_TYPE_64K:
|
||||
mppc_set_compression_level(bulk->mppcRecv, 1);
|
||||
status =
|
||||
mppc_decompress(bulk->mppcRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
|
||||
break;
|
||||
|
||||
case PACKET_COMPR_TYPE_RDP6:
|
||||
status = ncrush_decompress(bulk->ncrushRecv, pSrcData, SrcSize, ppDstData, pDstSize,
|
||||
flags);
|
||||
break;
|
||||
|
||||
case PACKET_COMPR_TYPE_RDP61:
|
||||
status = xcrush_decompress(bulk->xcrushRecv, pSrcData, SrcSize, ppDstData, pDstSize,
|
||||
flags);
|
||||
break;
|
||||
|
||||
case PACKET_COMPR_TYPE_RDP8:
|
||||
WLog_ERR(TAG, "Unsupported bulk compression type %08" PRIx32,
|
||||
bulk->CompressionLevel);
|
||||
status = -1;
|
||||
break;
|
||||
default:
|
||||
WLog_ERR(TAG, "Unknown bulk compression type %08" PRIx32, bulk->CompressionLevel);
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppDstData = pSrcData;
|
||||
*pDstSize = SrcSize;
|
||||
status = 0;
|
||||
}
|
||||
|
||||
if (status >= 0)
|
||||
{
|
||||
const UINT32 CompressedBytes = SrcSize;
|
||||
const UINT32 UncompressedBytes = *pDstSize;
|
||||
const double CompressionRatio =
|
||||
metrics_write_bytes(metrics, UncompressedBytes, CompressedBytes);
|
||||
#ifdef WITH_BULK_DEBUG
|
||||
{
|
||||
WLog_DBG(TAG,
|
||||
"Decompress Type: %" PRIu32 " Flags: %s (0x%08" PRIX32
|
||||
") Compression Ratio: %f (%" PRIu32 " / %" PRIu32 "), Total: %f (%" PRIu64
|
||||
" / %" PRIu64 ")",
|
||||
type, bulk_get_compression_flags_string(flags), flags, CompressionRatio,
|
||||
CompressedBytes, UncompressedBytes, metrics->TotalCompressionRatio,
|
||||
metrics->TotalCompressedBytes, metrics->TotalUncompressedBytes);
|
||||
}
|
||||
#else
|
||||
WINPR_UNUSED(CompressionRatio);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "Decompression failure!");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int bulk_compress(rdpBulk* WINPR_RESTRICT bulk, const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize,
|
||||
const BYTE** WINPR_RESTRICT ppDstData, UINT32* WINPR_RESTRICT pDstSize,
|
||||
UINT32* WINPR_RESTRICT pFlags)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
WINPR_ASSERT(bulk);
|
||||
WINPR_ASSERT(bulk->context);
|
||||
WINPR_ASSERT(pSrcData);
|
||||
WINPR_ASSERT(ppDstData);
|
||||
WINPR_ASSERT(pDstSize);
|
||||
|
||||
rdpMetrics* metrics = bulk->context->metrics;
|
||||
WINPR_ASSERT(metrics);
|
||||
|
||||
if ((SrcSize <= 50) || (SrcSize >= 16384))
|
||||
{
|
||||
*ppDstData = pSrcData;
|
||||
*pDstSize = SrcSize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pDstSize = sizeof(bulk->OutputBuffer);
|
||||
const UINT32 CompressionLevel = bulk_compression_level(bulk);
|
||||
bulk_update_compression_max_size(bulk);
|
||||
|
||||
switch (CompressionLevel)
|
||||
{
|
||||
case PACKET_COMPR_TYPE_8K:
|
||||
case PACKET_COMPR_TYPE_64K:
|
||||
mppc_set_compression_level(bulk->mppcSend, CompressionLevel);
|
||||
status = mppc_compress(bulk->mppcSend, pSrcData, SrcSize, bulk->OutputBuffer, ppDstData,
|
||||
pDstSize, pFlags);
|
||||
break;
|
||||
case PACKET_COMPR_TYPE_RDP6:
|
||||
status = ncrush_compress(bulk->ncrushSend, pSrcData, SrcSize, bulk->OutputBuffer,
|
||||
ppDstData, pDstSize, pFlags);
|
||||
break;
|
||||
case PACKET_COMPR_TYPE_RDP61:
|
||||
status = xcrush_compress(bulk->xcrushSend, pSrcData, SrcSize, bulk->OutputBuffer,
|
||||
ppDstData, pDstSize, pFlags);
|
||||
break;
|
||||
case PACKET_COMPR_TYPE_RDP8:
|
||||
WLog_ERR(TAG, "Unsupported bulk compression type %08" PRIx32, CompressionLevel);
|
||||
status = -1;
|
||||
break;
|
||||
default:
|
||||
WLog_ERR(TAG, "Unknown bulk compression type %08" PRIx32, CompressionLevel);
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status >= 0)
|
||||
{
|
||||
const UINT32 CompressedBytes = *pDstSize;
|
||||
const UINT32 UncompressedBytes = SrcSize;
|
||||
const double CompressionRatio =
|
||||
metrics_write_bytes(metrics, UncompressedBytes, CompressedBytes);
|
||||
#ifdef WITH_BULK_DEBUG
|
||||
{
|
||||
WLog_DBG(TAG,
|
||||
"Compress Type: %" PRIu32 " Flags: %s (0x%08" PRIX32
|
||||
") Compression Ratio: %f (%" PRIu32 " / %" PRIu32 "), Total: %f (%" PRIu64
|
||||
" / %" PRIu64 ")",
|
||||
bulk->CompressionLevel, bulk_get_compression_flags_string(*pFlags), *pFlags,
|
||||
CompressionRatio, CompressedBytes, UncompressedBytes,
|
||||
metrics->TotalCompressionRatio, metrics->TotalCompressedBytes,
|
||||
metrics->TotalUncompressedBytes);
|
||||
}
|
||||
#else
|
||||
WINPR_UNUSED(CompressionRatio);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(WITH_BULK_DEBUG)
|
||||
|
||||
if (bulk_compress_validate(bulk, pSrcData, SrcSize, *ppDstData, *pDstSize, *pFlags) < 0)
|
||||
status = -1;
|
||||
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
void bulk_reset(rdpBulk* WINPR_RESTRICT bulk)
|
||||
{
|
||||
WINPR_ASSERT(bulk);
|
||||
|
||||
mppc_context_reset(bulk->mppcSend, FALSE);
|
||||
mppc_context_reset(bulk->mppcRecv, FALSE);
|
||||
ncrush_context_reset(bulk->ncrushRecv, FALSE);
|
||||
ncrush_context_reset(bulk->ncrushSend, FALSE);
|
||||
xcrush_context_reset(bulk->xcrushRecv, FALSE);
|
||||
xcrush_context_reset(bulk->xcrushSend, FALSE);
|
||||
}
|
||||
|
||||
rdpBulk* bulk_new(rdpContext* context)
|
||||
{
|
||||
rdpBulk* bulk = nullptr;
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
bulk = (rdpBulk*)calloc(1, sizeof(rdpBulk));
|
||||
|
||||
if (!bulk)
|
||||
goto fail;
|
||||
|
||||
bulk->context = context;
|
||||
bulk->mppcSend = mppc_context_new(1, TRUE);
|
||||
if (!bulk->mppcSend)
|
||||
goto fail;
|
||||
bulk->mppcRecv = mppc_context_new(1, FALSE);
|
||||
if (!bulk->mppcRecv)
|
||||
goto fail;
|
||||
bulk->ncrushRecv = ncrush_context_new(FALSE);
|
||||
if (!bulk->ncrushRecv)
|
||||
goto fail;
|
||||
bulk->ncrushSend = ncrush_context_new(TRUE);
|
||||
if (!bulk->ncrushSend)
|
||||
goto fail;
|
||||
bulk->xcrushRecv = xcrush_context_new(FALSE);
|
||||
if (!bulk->xcrushRecv)
|
||||
goto fail;
|
||||
bulk->xcrushSend = xcrush_context_new(TRUE);
|
||||
if (!bulk->xcrushSend)
|
||||
goto fail;
|
||||
bulk->CompressionLevel = context->settings->CompressionLevel;
|
||||
|
||||
return bulk;
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
bulk_free(bulk);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void bulk_free(rdpBulk* bulk)
|
||||
{
|
||||
if (!bulk)
|
||||
return;
|
||||
|
||||
mppc_context_free(bulk->mppcSend);
|
||||
mppc_context_free(bulk->mppcRecv);
|
||||
ncrush_context_free(bulk->ncrushRecv);
|
||||
ncrush_context_free(bulk->ncrushSend);
|
||||
xcrush_context_free(bulk->xcrushRecv);
|
||||
xcrush_context_free(bulk->xcrushSend);
|
||||
free(bulk);
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Bulk Compression
|
||||
*
|
||||
* Copyright 2014 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 FREERDP_LIB_CORE_BULK_H
|
||||
#define FREERDP_LIB_CORE_BULK_H
|
||||
|
||||
typedef struct rdp_bulk rdpBulk;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
|
||||
#define BULK_COMPRESSION_FLAGS_MASK 0xE0
|
||||
#define BULK_COMPRESSION_TYPE_MASK 0x0F
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL UINT16 bulk_compression_max_size(rdpBulk* WINPR_RESTRICT bulk);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int bulk_decompress(rdpBulk* WINPR_RESTRICT bulk, const BYTE* WINPR_RESTRICT pSrcData,
|
||||
UINT32 SrcSize, const BYTE** WINPR_RESTRICT ppDstData,
|
||||
UINT32* WINPR_RESTRICT pDstSize, UINT32 flags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int bulk_compress(rdpBulk* WINPR_RESTRICT bulk, const BYTE* WINPR_RESTRICT pSrcData,
|
||||
UINT32 SrcSize, const BYTE** WINPR_RESTRICT ppDstData,
|
||||
UINT32* WINPR_RESTRICT pDstSize, UINT32* WINPR_RESTRICT pFlags);
|
||||
|
||||
FREERDP_LOCAL void bulk_reset(rdpBulk* WINPR_RESTRICT bulk);
|
||||
|
||||
FREERDP_LOCAL void bulk_free(rdpBulk* bulk);
|
||||
|
||||
WINPR_ATTR_MALLOC(bulk_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL rdpBulk* bulk_new(rdpContext* context);
|
||||
|
||||
#endif /* FREERDP_LIB_CORE_BULK_H */
|
||||
+1286
File diff suppressed because it is too large
Load Diff
+1911
File diff suppressed because it is too large
Load Diff
+151
@@ -0,0 +1,151 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* codec color
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 FREERDP_LIB_CODEC_COLOR_H
|
||||
#define FREERDP_LIB_CODEC_COLOR_H
|
||||
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#define INT_COLOR_TAG FREERDP_TAG("codec.color.h")
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline DWORD FreeRDPAreColorFormatsEqualNoAlpha_int(DWORD first, DWORD second)
|
||||
{
|
||||
const DWORD mask = (DWORD) ~(8UL << 12UL);
|
||||
return (first & mask) == (second & mask);
|
||||
}
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline BOOL FreeRDPWriteColor_int(BYTE* WINPR_RESTRICT dst, UINT32 format, UINT32 color)
|
||||
{
|
||||
switch (FreeRDPGetBitsPerPixel(format))
|
||||
{
|
||||
case 32:
|
||||
dst[0] = (BYTE)(color >> 24);
|
||||
dst[1] = (BYTE)(color >> 16);
|
||||
dst[2] = (BYTE)(color >> 8);
|
||||
dst[3] = (BYTE)color;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
dst[0] = (BYTE)(color >> 16);
|
||||
dst[1] = (BYTE)(color >> 8);
|
||||
dst[2] = (BYTE)color;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
dst[1] = (BYTE)(color >> 8);
|
||||
dst[0] = (BYTE)color;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
if (!FreeRDPColorHasAlpha(format))
|
||||
color = color & 0x7FFF;
|
||||
|
||||
dst[1] = (BYTE)(color >> 8);
|
||||
dst[0] = (BYTE)color;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
dst[0] = (BYTE)color;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(INT_COLOR_TAG, "Unsupported format %s", FreeRDPGetColorFormatName(format));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline BOOL FreeRDPWriteColorIgnoreAlpha_int(BYTE* WINPR_RESTRICT dst, UINT32 format,
|
||||
UINT32 color)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PIXEL_FORMAT_XBGR32:
|
||||
case PIXEL_FORMAT_XRGB32:
|
||||
case PIXEL_FORMAT_ABGR32:
|
||||
case PIXEL_FORMAT_ARGB32:
|
||||
{
|
||||
const UINT32 tmp = ((UINT32)dst[0] << 24ULL) | (color & 0x00FFFFFFULL);
|
||||
return FreeRDPWriteColor_int(dst, format, tmp);
|
||||
}
|
||||
case PIXEL_FORMAT_BGRX32:
|
||||
case PIXEL_FORMAT_RGBX32:
|
||||
case PIXEL_FORMAT_BGRA32:
|
||||
case PIXEL_FORMAT_RGBA32:
|
||||
{
|
||||
const UINT32 tmp = ((UINT32)dst[3]) | (color & 0xFFFFFF00ULL);
|
||||
return FreeRDPWriteColor_int(dst, format, tmp);
|
||||
}
|
||||
default:
|
||||
return FreeRDPWriteColor_int(dst, format, color);
|
||||
}
|
||||
}
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline UINT32 FreeRDPReadColor_int(const BYTE* WINPR_RESTRICT src, UINT32 format)
|
||||
{
|
||||
UINT32 color = 0;
|
||||
|
||||
switch (FreeRDPGetBitsPerPixel(format))
|
||||
{
|
||||
case 32:
|
||||
color =
|
||||
((UINT32)src[0] << 24) | ((UINT32)src[1] << 16) | ((UINT32)src[2] << 8) | src[3];
|
||||
break;
|
||||
|
||||
case 24:
|
||||
color = ((UINT32)src[0] << 16) | ((UINT32)src[1] << 8) | src[2];
|
||||
break;
|
||||
|
||||
case 16:
|
||||
color = ((UINT32)src[1] << 8) | src[0];
|
||||
break;
|
||||
|
||||
case 15:
|
||||
color = ((UINT32)src[1] << 8) | src[0];
|
||||
|
||||
if (!FreeRDPColorHasAlpha(format))
|
||||
color = color & 0x7FFF;
|
||||
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case 4:
|
||||
case 1:
|
||||
color = *src;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(INT_COLOR_TAG, "Unsupported format %s", FreeRDPGetColorFormatName(format));
|
||||
color = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
#endif
|
||||
+1617
File diff suppressed because it is too large
Load Diff
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Digital Sound Processing - backend
|
||||
*
|
||||
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2018 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 FREERDP_LIB_CODEC_DSP_H
|
||||
#define FREERDP_LIB_CODEC_DSP_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/codec/audio.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ALIGN64 AUDIO_FORMAT format;
|
||||
ALIGN64 BOOL encoder;
|
||||
ALIGN64 wStream* buffer;
|
||||
ALIGN64 wStream* resample;
|
||||
ALIGN64 wStream* channelmix;
|
||||
#if defined(WITH_FDK_AAC)
|
||||
ALIGN64 BOOL fdkSetup;
|
||||
ALIGN64 void* fdkAacInstance;
|
||||
ALIGN64 size_t buffersize;
|
||||
ALIGN64 unsigned frames_per_packet;
|
||||
#endif
|
||||
} FREERDP_DSP_COMMON_CONTEXT;
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL freerdp_dsp_common_context_init(FREERDP_DSP_COMMON_CONTEXT* context,
|
||||
BOOL encode);
|
||||
|
||||
FREERDP_LOCAL void freerdp_dsp_common_context_uninit(FREERDP_DSP_COMMON_CONTEXT* context);
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_DSP_H */
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Digital Sound Processing
|
||||
*
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 "dsp_fdk_aac.h"
|
||||
#include "dsp_fdk_impl.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#define TAG FREERDP_TAG("dsp.fdk")
|
||||
|
||||
WINPR_ATTR_FORMAT_ARG(2, 3)
|
||||
static void write_log(unsigned log_level, WINPR_FORMAT_ARG const char* fmt, ...)
|
||||
{
|
||||
wLog* log = WLog_Get(TAG);
|
||||
|
||||
if (WLog_IsLevelActive(log, log_level))
|
||||
{
|
||||
char buffer[1024] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
va_list ap = WINPR_C_ARRAY_INIT;
|
||||
va_start(ap, fmt);
|
||||
(void)vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
WLog_PrintTextMessage(log, log_level, __LINE__, __FILE__, __func__, "%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL fdk_aac_dsp_encode(FREERDP_DSP_COMMON_CONTEXT* context, const AUDIO_FORMAT* srcFormat,
|
||||
const BYTE* data, size_t length, wStream* out)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(srcFormat);
|
||||
|
||||
if (srcFormat->wFormatTag != WAVE_FORMAT_PCM)
|
||||
{
|
||||
WLog_WARN(TAG, "Feeding %s format data to encoder function, but require %s",
|
||||
audio_format_get_tag_string(srcFormat->wFormatTag),
|
||||
audio_format_get_tag_string(WAVE_FORMAT_PCM));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!context->fdkSetup)
|
||||
{
|
||||
ssize_t rc = fdk_aac_dsp_impl_config(
|
||||
context->fdkAacInstance, &context->buffersize, context->encoder,
|
||||
context->format.nSamplesPerSec, context->format.nChannels,
|
||||
context->format.nAvgBytesPerSec, context->frames_per_packet, write_log);
|
||||
if (rc < 0)
|
||||
return FALSE;
|
||||
|
||||
context->fdkSetup = TRUE;
|
||||
}
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(out, context->buffersize))
|
||||
return FALSE;
|
||||
|
||||
{
|
||||
const ssize_t encoded =
|
||||
fdk_aac_dsp_impl_encode(context->fdkAacInstance, data, length, Stream_Pointer(out),
|
||||
Stream_GetRemainingCapacity(out), write_log);
|
||||
if (encoded < 0)
|
||||
return FALSE;
|
||||
Stream_Seek(out, (size_t)encoded);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL fdk_aac_dsp_decode(FREERDP_DSP_COMMON_CONTEXT* context, const AUDIO_FORMAT* srcFormat,
|
||||
const BYTE* data, size_t length, wStream* out)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(srcFormat);
|
||||
|
||||
if (srcFormat->wFormatTag != WAVE_FORMAT_AAC_MS)
|
||||
{
|
||||
WLog_WARN(TAG, "Feeding %s format data to encoder function, but require %s",
|
||||
audio_format_get_tag_string(srcFormat->wFormatTag),
|
||||
audio_format_get_tag_string(WAVE_FORMAT_AAC_MS));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!context->fdkSetup)
|
||||
{
|
||||
ssize_t rc = fdk_aac_dsp_impl_config(
|
||||
context->fdkAacInstance, &context->buffersize, context->encoder,
|
||||
context->format.nSamplesPerSec, context->format.nChannels,
|
||||
context->format.nAvgBytesPerSec, context->frames_per_packet, write_log);
|
||||
if (rc < 0)
|
||||
return FALSE;
|
||||
|
||||
context->fdkSetup = TRUE;
|
||||
}
|
||||
|
||||
ssize_t rest = 0;
|
||||
do
|
||||
{
|
||||
rest = fdk_aac_dsp_impl_decode_fill(context->fdkAacInstance, data, length, write_log);
|
||||
if (rest < 0)
|
||||
{
|
||||
WLog_WARN(TAG, "DecodeFill() failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ssize_t ret = -1;
|
||||
do
|
||||
{
|
||||
const size_t expect = context->buffersize;
|
||||
if (!Stream_EnsureRemainingCapacity(out, expect))
|
||||
return FALSE;
|
||||
|
||||
ret = fdk_aac_dsp_impl_decode_read(context->fdkAacInstance, Stream_Pointer(out), expect,
|
||||
write_log);
|
||||
if (ret < 0)
|
||||
return FALSE;
|
||||
|
||||
Stream_Seek(out, (size_t)ret);
|
||||
} while (ret > 0);
|
||||
} while (rest > 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void fdk_aac_dsp_uninit(FREERDP_DSP_COMMON_CONTEXT* context)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
fdk_aac_dsp_impl_uninit(&context->fdkAacInstance, context->encoder, write_log);
|
||||
}
|
||||
|
||||
BOOL fdk_aac_dsp_init(FREERDP_DSP_COMMON_CONTEXT* context, size_t frames_per_packet)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
context->fdkSetup = FALSE;
|
||||
WINPR_ASSERT(frames_per_packet <= UINT_MAX);
|
||||
context->frames_per_packet = (unsigned)frames_per_packet;
|
||||
return fdk_aac_dsp_impl_init(&context->fdkAacInstance, context->encoder, write_log);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Digital Sound Processing
|
||||
*
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 FREERDP_DSP_FDK_AAC_H_
|
||||
#define FREERDP_DSP_FDK_AAC_H_
|
||||
|
||||
#include <winpr/stream.h>
|
||||
#include <freerdp/codec/audio.h>
|
||||
|
||||
#include "dsp.h"
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL fdk_aac_dsp_init(FREERDP_DSP_COMMON_CONTEXT* context,
|
||||
size_t frames_per_packet);
|
||||
|
||||
FREERDP_LOCAL
|
||||
void fdk_aac_dsp_uninit(FREERDP_DSP_COMMON_CONTEXT* context);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL fdk_aac_dsp_encode(FREERDP_DSP_COMMON_CONTEXT* context,
|
||||
const AUDIO_FORMAT* srcFormat,
|
||||
const BYTE* data, size_t length,
|
||||
wStream* out);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL fdk_aac_dsp_decode(FREERDP_DSP_COMMON_CONTEXT* context,
|
||||
const AUDIO_FORMAT* srcFormat,
|
||||
const BYTE* data, size_t length,
|
||||
wStream* out);
|
||||
|
||||
#endif
|
||||
+616
@@ -0,0 +1,616 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Digital Sound Processing
|
||||
*
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <fdk-aac/aacdecoder_lib.h>
|
||||
#include <fdk-aac/aacenc_lib.h>
|
||||
|
||||
#include "dsp_fdk_impl.h"
|
||||
|
||||
#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ < 202003L))
|
||||
#define nullptr NULL
|
||||
#endif
|
||||
|
||||
#define WLOG_TRACE 0
|
||||
#define WLOG_DEBUG 1
|
||||
#define WLOG_INFO 2
|
||||
#define WLOG_WARN 3
|
||||
#define WLOG_ERROR 4
|
||||
#define WLOG_FATAL 5
|
||||
|
||||
static const char* enc_err_str(AACENC_ERROR err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case AACENC_OK:
|
||||
return "AACENC_OK";
|
||||
case AACENC_INVALID_HANDLE:
|
||||
return "AACENC_INVALID_HANDLE";
|
||||
case AACENC_MEMORY_ERROR:
|
||||
return "AACENC_MEMORY_ERROR";
|
||||
case AACENC_UNSUPPORTED_PARAMETER:
|
||||
return "AACENC_UNSUPPORTED_PARAMETER";
|
||||
case AACENC_INVALID_CONFIG:
|
||||
return "AACENC_INVALID_CONFIG";
|
||||
case AACENC_INIT_ERROR:
|
||||
return "AACENC_INIT_ERROR";
|
||||
case AACENC_INIT_AAC_ERROR:
|
||||
return "AACENC_INIT_AAC_ERROR";
|
||||
case AACENC_INIT_SBR_ERROR:
|
||||
return "AACENC_INIT_SBR_ERROR";
|
||||
case AACENC_INIT_TP_ERROR:
|
||||
return "AACENC_INIT_TP_ERROR";
|
||||
case AACENC_INIT_META_ERROR:
|
||||
return "AACENC_INIT_META_ERROR";
|
||||
#ifdef AACENC_INIT_MPS_ERROR
|
||||
case AACENC_INIT_MPS_ERROR:
|
||||
return "AACENC_INIT_MPS_ERROR";
|
||||
#endif
|
||||
case AACENC_ENCODE_ERROR:
|
||||
return "AACENC_ENCODE_ERROR";
|
||||
case AACENC_ENCODE_EOF:
|
||||
return "AACENC_ENCODE_EOF";
|
||||
default:
|
||||
return "AACENC_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
static const char* dec_err_str(AAC_DECODER_ERROR err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case AAC_DEC_OK:
|
||||
return "AAC_DEC_OK";
|
||||
case AAC_DEC_OUT_OF_MEMORY:
|
||||
return "AAC_DEC_OUT_OF_MEMORY";
|
||||
case AAC_DEC_UNKNOWN:
|
||||
return "AAC_DEC_UNKNOWN";
|
||||
case aac_dec_sync_error_start:
|
||||
return "aac_dec_sync_error_start";
|
||||
case AAC_DEC_TRANSPORT_SYNC_ERROR:
|
||||
return "AAC_DEC_TRANSPORT_SYNC_ERROR";
|
||||
case AAC_DEC_NOT_ENOUGH_BITS:
|
||||
return "AAC_DEC_NOT_ENOUGH_BITS";
|
||||
case aac_dec_sync_error_end:
|
||||
return "aac_dec_sync_error_end";
|
||||
case aac_dec_init_error_start:
|
||||
return "aac_dec_init_error_start";
|
||||
case AAC_DEC_INVALID_HANDLE:
|
||||
return "AAC_DEC_INVALID_HANDLE";
|
||||
case AAC_DEC_UNSUPPORTED_FORMAT:
|
||||
return "AAC_DEC_UNSUPPORTED_FORMAT";
|
||||
case AAC_DEC_UNSUPPORTED_ER_FORMAT:
|
||||
return "AAC_DEC_UNSUPPORTED_ER_FORMAT";
|
||||
case AAC_DEC_UNSUPPORTED_EPCONFIG:
|
||||
return "AAC_DEC_UNSUPPORTED_EPCONFIG";
|
||||
case AAC_DEC_UNSUPPORTED_MULTILAYER:
|
||||
return "AAC_DEC_UNSUPPORTED_MULTILAYER";
|
||||
case AAC_DEC_UNSUPPORTED_CHANNELCONFIG:
|
||||
return "AAC_DEC_UNSUPPORTED_CHANNELCONFIG";
|
||||
case AAC_DEC_UNSUPPORTED_SAMPLINGRATE:
|
||||
return "AAC_DEC_UNSUPPORTED_SAMPLINGRATE";
|
||||
case AAC_DEC_INVALID_SBR_CONFIG:
|
||||
return "AAC_DEC_INVALID_SBR_CONFIG";
|
||||
case AAC_DEC_SET_PARAM_FAIL:
|
||||
return "AAC_DEC_SET_PARAM_FAIL";
|
||||
case AAC_DEC_NEED_TO_RESTART:
|
||||
return "AAC_DEC_NEED_TO_RESTART";
|
||||
case AAC_DEC_OUTPUT_BUFFER_TOO_SMALL:
|
||||
return "AAC_DEC_OUTPUT_BUFFER_TOO_SMALL";
|
||||
case aac_dec_init_error_end:
|
||||
return "aac_dec_init_error_end";
|
||||
case aac_dec_decode_error_start:
|
||||
return "aac_dec_decode_error_start";
|
||||
case AAC_DEC_TRANSPORT_ERROR:
|
||||
return "AAC_DEC_TRANSPORT_ERROR";
|
||||
case AAC_DEC_PARSE_ERROR:
|
||||
return "AAC_DEC_PARSE_ERROR";
|
||||
case AAC_DEC_UNSUPPORTED_EXTENSION_PAYLOAD:
|
||||
return "AAC_DEC_UNSUPPORTED_EXTENSION_PAYLOAD";
|
||||
case AAC_DEC_DECODE_FRAME_ERROR:
|
||||
return "AAC_DEC_DECODE_FRAME_ERROR";
|
||||
case AAC_DEC_CRC_ERROR:
|
||||
return "AAC_DEC_CRC_ERROR";
|
||||
case AAC_DEC_INVALID_CODE_BOOK:
|
||||
return "AAC_DEC_INVALID_CODE_BOOK";
|
||||
case AAC_DEC_UNSUPPORTED_PREDICTION:
|
||||
return "AAC_DEC_UNSUPPORTED_PREDICTION";
|
||||
case AAC_DEC_UNSUPPORTED_CCE:
|
||||
return "AAC_DEC_UNSUPPORTED_CCE";
|
||||
case AAC_DEC_UNSUPPORTED_LFE:
|
||||
return "AAC_DEC_UNSUPPORTED_LFE";
|
||||
case AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA:
|
||||
return "AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA";
|
||||
case AAC_DEC_UNSUPPORTED_SBA:
|
||||
return "AAC_DEC_UNSUPPORTED_SBA";
|
||||
case AAC_DEC_TNS_READ_ERROR:
|
||||
return "AAC_DEC_TNS_READ_ERROR";
|
||||
case AAC_DEC_RVLC_ERROR:
|
||||
return "AAC_DEC_RVLC_ERROR";
|
||||
case aac_dec_decode_error_end:
|
||||
return "aac_dec_decode_error_end";
|
||||
case aac_dec_anc_data_error_start:
|
||||
return "aac_dec_anc_data_error_start";
|
||||
case AAC_DEC_ANC_DATA_ERROR:
|
||||
return "AAC_DEC_ANC_DATA_ERROR";
|
||||
case AAC_DEC_TOO_SMALL_ANC_BUFFER:
|
||||
return "AAC_DEC_TOO_SMALL_ANC_BUFFER";
|
||||
case AAC_DEC_TOO_MANY_ANC_ELEMENTS:
|
||||
return "AAC_DEC_TOO_MANY_ANC_ELEMENTS";
|
||||
case aac_dec_anc_data_error_end:
|
||||
return "aac_dec_anc_data_error_end";
|
||||
default:
|
||||
return "AAC_DEC unknown value";
|
||||
}
|
||||
}
|
||||
|
||||
static void log_dec_info(const CStreamInfo* info, void (*log)(const char* fmt, ...))
|
||||
{
|
||||
assert(info);
|
||||
assert(log);
|
||||
|
||||
log("info:"
|
||||
"aacSampleRate: %d, "
|
||||
"frameSize: %d, "
|
||||
"numChannels: %d, "
|
||||
"pChannelType: %p, "
|
||||
"pChannelIndices: %p, "
|
||||
"aacSampleRate: %d, "
|
||||
"profile: %d, "
|
||||
"aot: %d, " /* TODO: Enum 2 string */
|
||||
"channelConfig: %d, "
|
||||
"bitRate: %d, "
|
||||
"aacSamplesPerFrame: %d, "
|
||||
"aacNumChannels: %d, "
|
||||
"extAot: %d" /* TODO: Enum 2 string */
|
||||
"extSamplingRate: %d, "
|
||||
"outputDelay: %u, "
|
||||
"flags: %u, "
|
||||
"epConfig: %d, "
|
||||
"numLostAccessUnits: %d, "
|
||||
"numTotalBytes: %" PRIu64 ", "
|
||||
"numBadBytes: %" PRIu64 ", "
|
||||
"numTotalAccessUnits: %" PRIu64 ", "
|
||||
"numBadAccessUnits: %" PRIu64 ", "
|
||||
"drcProgRefLev: %d, "
|
||||
"drcPresMode: %d, ",
|
||||
info->aacSampleRate, info->frameSize, info->numChannels, info->pChannelType,
|
||||
info->pChannelIndices, info->aacSampleRate, info->profile, info->aot, info->channelConfig,
|
||||
info->bitRate, info->aacSamplesPerFrame, info->aacNumChannels, info->extAot,
|
||||
info->extSamplingRate, info->outputDelay, info->flags, (int)info->epConfig,
|
||||
info->numLostAccessUnits,
|
||||
|
||||
info->numTotalBytes, info->numBadBytes, info->numTotalAccessUnits, info->numBadAccessUnits,
|
||||
|
||||
(int)info->drcProgRefLev, (int)info->drcPresMode);
|
||||
}
|
||||
|
||||
static void log_enc_info(const AACENC_InfoStruct* info, fdk_log_fkt_t log)
|
||||
{
|
||||
char confBuf[1024] = { 0 };
|
||||
|
||||
assert(info);
|
||||
assert(log);
|
||||
|
||||
size_t offset = 0;
|
||||
size_t remain = sizeof(confBuf) - 1;
|
||||
int rc = snprintf(confBuf, remain, "{");
|
||||
if (rc <= 0)
|
||||
return;
|
||||
offset += (size_t)rc;
|
||||
|
||||
for (size_t x = 0; x < 64; x++)
|
||||
{
|
||||
rc = snprintf(&confBuf[offset], remain - offset, "0x%02x%s", (int)info->confBuf[x],
|
||||
(x > 0) ? ", " : "");
|
||||
if (rc <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
rc = snprintf(confBuf, remain - offset, "}");
|
||||
if (rc <= 0)
|
||||
return;
|
||||
|
||||
log(WLOG_DEBUG,
|
||||
"[encoder info] "
|
||||
"maxOutBufBytes : %u, "
|
||||
"maxAncBytes : %u, "
|
||||
"inBufFillLevel : %u, "
|
||||
"inputChannels : %u, "
|
||||
"frameLength : %u, "
|
||||
#ifdef MODE_7_1_BACK
|
||||
"nDelay : %u, "
|
||||
"nDelayCore : %u, "
|
||||
#endif
|
||||
"confBuf[64] : %s, "
|
||||
"confSize : %u",
|
||||
info->maxOutBufBytes, info->maxAncBytes, info->inBufFillLevel, info->inputChannels,
|
||||
info->frameLength,
|
||||
#ifdef MODE_7_1_BACK
|
||||
info->nDelay, info->nDelayCore,
|
||||
#endif
|
||||
confBuf, info->confSize);
|
||||
}
|
||||
|
||||
static const char* aac_enc_param_str(AACENC_PARAM param)
|
||||
{
|
||||
switch (param)
|
||||
{
|
||||
case AACENC_AOT:
|
||||
return "AACENC_AOT";
|
||||
case AACENC_BITRATE:
|
||||
return "AACENC_BITRATE";
|
||||
case AACENC_BITRATEMODE:
|
||||
return "AACENC_BITRATEMODE";
|
||||
case AACENC_SAMPLERATE:
|
||||
return "AACENC_SAMPLERATE";
|
||||
case AACENC_SBR_MODE:
|
||||
return "AACENC_SBR_MODE";
|
||||
case AACENC_GRANULE_LENGTH:
|
||||
return "AACENC_GRANULE_LENGTH";
|
||||
case AACENC_CHANNELMODE:
|
||||
return "AACENC_CHANNELMODE";
|
||||
case AACENC_CHANNELORDER:
|
||||
return "AACENC_CHANNELORDER";
|
||||
case AACENC_SBR_RATIO:
|
||||
return "AACENC_SBR_RATIO";
|
||||
case AACENC_AFTERBURNER:
|
||||
return "AACENC_AFTERBURNER";
|
||||
case AACENC_BANDWIDTH:
|
||||
return "AACENC_BANDWIDTH";
|
||||
case AACENC_PEAK_BITRATE:
|
||||
return "AACENC_PEAK_BITRATE";
|
||||
case AACENC_TRANSMUX:
|
||||
return "AACENC_TRANSMUX";
|
||||
case AACENC_HEADER_PERIOD:
|
||||
return "AACENC_HEADER_PERIOD";
|
||||
case AACENC_SIGNALING_MODE:
|
||||
return "AACENC_SIGNALING_MODE";
|
||||
case AACENC_TPSUBFRAMES:
|
||||
return "AACENC_TPSUBFRAMES";
|
||||
case AACENC_AUDIOMUXVER:
|
||||
return "AACENC_AUDIOMUXVER";
|
||||
case AACENC_PROTECTION:
|
||||
return "AACENC_PROTECTION";
|
||||
case AACENC_ANCILLARY_BITRATE:
|
||||
return "AACENC_ANCILLARY_BITRATE";
|
||||
case AACENC_METADATA_MODE:
|
||||
return "AACENC_METADATA_MODE";
|
||||
case AACENC_CONTROL_STATE:
|
||||
return "AACENC_CONTROL_STATE";
|
||||
default:
|
||||
return "AACENC_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
int fdk_aac_dsp_impl_init(void** handle, int encoder, fdk_log_fkt_t log)
|
||||
{
|
||||
assert(handle);
|
||||
assert(log);
|
||||
|
||||
if (encoder)
|
||||
{
|
||||
HANDLE_AACENCODER* h = (HANDLE_AACENCODER*)handle;
|
||||
AACENC_ERROR err = aacEncOpen(h, 0, 0);
|
||||
if (err != AACENC_OK)
|
||||
{
|
||||
log(WLOG_ERROR, "aacEncOpen failed with %s", enc_err_str(err));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HANDLE_AACDECODER* h = (HANDLE_AACDECODER*)handle;
|
||||
assert(nullptr == *h);
|
||||
|
||||
*h = aacDecoder_Open(TT_MP4_RAW, 1);
|
||||
if (!*h)
|
||||
{
|
||||
log(WLOG_ERROR, "aacDecoder_Open failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void fdk_aac_dsp_impl_uninit(void** handle, int encoder, fdk_log_fkt_t log)
|
||||
{
|
||||
assert(handle);
|
||||
assert(log);
|
||||
|
||||
if (encoder)
|
||||
{
|
||||
HANDLE_AACENCODER* h = (HANDLE_AACENCODER*)handle;
|
||||
AACENC_ERROR err = aacEncClose(h);
|
||||
if (err != AACENC_OK)
|
||||
log(WLOG_ERROR, "aacEncClose failed with %s", enc_err_str(err));
|
||||
}
|
||||
else
|
||||
{
|
||||
HANDLE_AACDECODER* h = (HANDLE_AACDECODER*)handle;
|
||||
if (h)
|
||||
aacDecoder_Close(*h);
|
||||
}
|
||||
|
||||
*handle = nullptr;
|
||||
}
|
||||
|
||||
ssize_t fdk_aac_dsp_impl_decode_read(void* handle, void* dst, size_t dstSize, fdk_log_fkt_t log)
|
||||
{
|
||||
assert(handle);
|
||||
assert((dstSize / sizeof(INT_PCM)) <= INT_MAX);
|
||||
|
||||
const INT nrsamples = (INT)(dstSize / sizeof(INT_PCM));
|
||||
UINT flags = 0;
|
||||
HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle;
|
||||
AAC_DECODER_ERROR err = aacDecoder_DecodeFrame(self, dst, nrsamples, flags);
|
||||
switch (err)
|
||||
{
|
||||
case AAC_DEC_OK:
|
||||
return fdk_aac_dsp_impl_stream_info(handle, 0, log);
|
||||
case AAC_DEC_NOT_ENOUGH_BITS:
|
||||
return 0;
|
||||
default:
|
||||
log(WLOG_ERROR, "aacDecoder_DecodeFrame failed with %s", dec_err_str(err));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned get_channelmode(unsigned channels)
|
||||
{
|
||||
switch (channels)
|
||||
{
|
||||
case 1:
|
||||
return MODE_1;
|
||||
case 2:
|
||||
return MODE_2;
|
||||
case 3:
|
||||
return MODE_1_2;
|
||||
case 4:
|
||||
return MODE_1_2_1;
|
||||
case 5:
|
||||
return MODE_1_2_2;
|
||||
case 6:
|
||||
return MODE_1_2_2_1;
|
||||
case 7:
|
||||
return MODE_1_2_2_2_1;
|
||||
#ifdef MODE_7_1_BACK
|
||||
case 8:
|
||||
return MODE_7_1_BACK;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return MODE_2;
|
||||
}
|
||||
}
|
||||
|
||||
int fdk_aac_dsp_impl_config(void* handle, size_t* pbuffersize, int encoder, unsigned samplerate,
|
||||
unsigned channels, unsigned bytes_per_second,
|
||||
unsigned frames_per_packet, fdk_log_fkt_t log)
|
||||
{
|
||||
assert(handle);
|
||||
assert(log);
|
||||
assert(pbuffersize);
|
||||
|
||||
log(WLOG_DEBUG,
|
||||
"fdk_aac_dsp_impl_config: samplerate: %ld, channels: %ld, bytes_pers_second: %ld",
|
||||
samplerate, channels, bytes_per_second);
|
||||
|
||||
struct t_param_pair
|
||||
{
|
||||
AACENC_PARAM param;
|
||||
UINT value;
|
||||
};
|
||||
|
||||
const struct t_param_pair params[] = { { AACENC_AOT, 2 },
|
||||
{ AACENC_SAMPLERATE, samplerate },
|
||||
{ AACENC_CHANNELMODE, get_channelmode(channels) },
|
||||
{ AACENC_CHANNELORDER, 0 },
|
||||
{ AACENC_BITRATE, bytes_per_second * 8 },
|
||||
{ AACENC_TRANSMUX, 0 },
|
||||
{ AACENC_AFTERBURNER, 1 } };
|
||||
HANDLE_AACENCODER self = nullptr;
|
||||
if (encoder)
|
||||
self = (HANDLE_AACENCODER)handle;
|
||||
else
|
||||
{
|
||||
AACENC_ERROR err = aacEncOpen(&self, 0, channels);
|
||||
if (err != AACENC_OK)
|
||||
{
|
||||
log(WLOG_ERROR, "aacEncOpen failed with %s", enc_err_str(err));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t x = 0; x < sizeof(params) / sizeof(params[0]); x++)
|
||||
{
|
||||
const struct t_param_pair* param = ¶ms[x];
|
||||
|
||||
AACENC_ERROR err = aacEncoder_SetParam(self, param->param, param->value);
|
||||
if (err != AACENC_OK)
|
||||
{
|
||||
log(WLOG_ERROR, "aacEncoder_SetParam(%s, %d) failed with %s",
|
||||
aac_enc_param_str(param->param), param->value, enc_err_str(err));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
AACENC_ERROR err = aacEncEncode(self, nullptr, nullptr, nullptr, nullptr);
|
||||
if (err != AACENC_OK)
|
||||
{
|
||||
log(WLOG_ERROR, "aacEncEncode failed with %s", enc_err_str(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
AACENC_InfoStruct info = { 0 };
|
||||
err = aacEncInfo(self, &info);
|
||||
if (err != AACENC_OK)
|
||||
{
|
||||
log(WLOG_ERROR, "aacEncInfo failed with %s", enc_err_str(err));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (encoder)
|
||||
{
|
||||
*pbuffersize = info.maxOutBufBytes;
|
||||
log_enc_info(&info, log);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
err = aacEncClose(&self);
|
||||
if (err != AACENC_OK)
|
||||
log(WLOG_WARN, "aacEncClose failed with %s", enc_err_str(err));
|
||||
|
||||
*pbuffersize = sizeof(INT_PCM) * info.frameLength * info.inputChannels;
|
||||
|
||||
HANDLE_AACDECODER aacdec = (HANDLE_AACDECODER)handle;
|
||||
|
||||
UCHAR* asc[] = { info.confBuf };
|
||||
UINT ascSize[] = { info.confSize };
|
||||
|
||||
assert(handle);
|
||||
|
||||
AAC_DECODER_ERROR decerr = aacDecoder_ConfigRaw(aacdec, asc, ascSize);
|
||||
if (decerr != AAC_DEC_OK)
|
||||
{
|
||||
log(WLOG_ERROR, "aacDecoder_ConfigRaw failed with %s", dec_err_str(decerr));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t fdk_aac_dsp_impl_decode_fill(void* handle, const void* data, size_t size, fdk_log_fkt_t log)
|
||||
{
|
||||
assert(handle);
|
||||
assert(log);
|
||||
|
||||
UINT leftBytes = size;
|
||||
HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle;
|
||||
|
||||
union
|
||||
{
|
||||
const void* cpv;
|
||||
UCHAR* puc;
|
||||
} cnv;
|
||||
cnv.cpv = data;
|
||||
UCHAR* pBuffer[] = { cnv.puc };
|
||||
const UINT bufferSize[] = { size };
|
||||
|
||||
assert(handle);
|
||||
assert(data || (size == 0));
|
||||
|
||||
AAC_DECODER_ERROR err = aacDecoder_Fill(self, pBuffer, bufferSize, &leftBytes);
|
||||
if (err != AAC_DEC_OK)
|
||||
{
|
||||
log(WLOG_ERROR, "aacDecoder_Fill failed with %s", dec_err_str(err));
|
||||
return -1;
|
||||
}
|
||||
return leftBytes;
|
||||
}
|
||||
|
||||
ssize_t fdk_aac_dsp_impl_stream_info(void* handle, int encoder, fdk_log_fkt_t log)
|
||||
{
|
||||
assert(handle);
|
||||
assert(log);
|
||||
|
||||
if (encoder)
|
||||
{
|
||||
AACENC_InfoStruct info = { 0 };
|
||||
HANDLE_AACENCODER self = (HANDLE_AACENCODER)handle;
|
||||
AACENC_ERROR err = aacEncInfo(self, &info);
|
||||
if (err != AACENC_OK)
|
||||
{
|
||||
log(WLOG_ERROR, "aacEncInfo failed with %s", enc_err_str(err));
|
||||
return -1;
|
||||
}
|
||||
return info.maxOutBufBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle;
|
||||
CStreamInfo* info = aacDecoder_GetStreamInfo(self);
|
||||
if (!info)
|
||||
{
|
||||
log(WLOG_ERROR, "aacDecoder_GetStreamInfo failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const size_t rsize = sizeof(INT_PCM) * info->numChannels * info->frameSize;
|
||||
return (ssize_t)rsize;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t fdk_aac_dsp_impl_encode(void* handle, const void* data, size_t size, void* dst,
|
||||
size_t dstSize, fdk_log_fkt_t log)
|
||||
{
|
||||
INT inSizes[] = { (INT)size };
|
||||
INT inElSizes[] = { sizeof(INT_PCM) };
|
||||
INT inIdentifiers[] = { IN_AUDIO_DATA };
|
||||
union
|
||||
{
|
||||
const void* cpv;
|
||||
void* pv;
|
||||
} cnv;
|
||||
cnv.cpv = data;
|
||||
void* inBuffers[] = { cnv.pv };
|
||||
|
||||
const AACENC_BufDesc inBufDesc = {
|
||||
.numBufs = 1,
|
||||
.bufs = inBuffers,
|
||||
.bufferIdentifiers = inIdentifiers,
|
||||
.bufSizes = inSizes,
|
||||
.bufElSizes = inElSizes /* TODO: 8/16 bit input? */
|
||||
};
|
||||
|
||||
INT outSizes[] = { (INT)dstSize };
|
||||
INT outElSizes[] = { 1 };
|
||||
INT outIdentifiers[] = { OUT_BITSTREAM_DATA };
|
||||
void* outBuffers[] = { dst };
|
||||
const AACENC_BufDesc outBufDesc = { .numBufs = 1,
|
||||
.bufs = outBuffers,
|
||||
.bufferIdentifiers = outIdentifiers,
|
||||
.bufSizes = outSizes,
|
||||
.bufElSizes = outElSizes };
|
||||
|
||||
const AACENC_InArgs inArgs = { .numInSamples =
|
||||
(INT)(size / sizeof(INT_PCM)), /* TODO: 8/16 bit input? */
|
||||
.numAncBytes = 0 };
|
||||
AACENC_OutArgs outArgs = { 0 };
|
||||
|
||||
HANDLE_AACENCODER self = (HANDLE_AACENCODER)handle;
|
||||
|
||||
assert(handle);
|
||||
assert(log);
|
||||
|
||||
AACENC_ERROR err = aacEncEncode(self, &inBufDesc, &outBufDesc, &inArgs, &outArgs);
|
||||
if (err != AACENC_OK)
|
||||
{
|
||||
log(WLOG_ERROR, "aacEncEncode failed with %s", enc_err_str(err));
|
||||
return -1;
|
||||
}
|
||||
return outArgs.numOutBytes;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Digital Sound Processing
|
||||
*
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2022 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 FREERDP_DSP_FDK_IMPL_H_
|
||||
#define FREERDP_DSP_FDK_IMPL_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef void (*fdk_log_fkt_t)(unsigned log_level, const char* fmt, ...);
|
||||
|
||||
int fdk_aac_dsp_impl_init(void** handle, int encoder, fdk_log_fkt_t log);
|
||||
void fdk_aac_dsp_impl_uninit(void** handle, int encoder, fdk_log_fkt_t log);
|
||||
|
||||
ssize_t fdk_aac_dsp_impl_stream_info(void* handle, int encoder, fdk_log_fkt_t log);
|
||||
|
||||
int fdk_aac_dsp_impl_config(void* handle, size_t* pbuffersize, int encoder, unsigned samplerate,
|
||||
unsigned channels, unsigned bytes_per_second,
|
||||
unsigned frames_per_packet, fdk_log_fkt_t log);
|
||||
|
||||
ssize_t fdk_aac_dsp_impl_decode_fill(void* handle, const void* data, size_t size,
|
||||
fdk_log_fkt_t log);
|
||||
|
||||
ssize_t fdk_aac_dsp_impl_encode(void* handle, const void* data, size_t size, void* dst,
|
||||
size_t dstSize, fdk_log_fkt_t log);
|
||||
|
||||
ssize_t fdk_aac_dsp_impl_decode_read(void* handle, void* dst, size_t dstSize, fdk_log_fkt_t log);
|
||||
|
||||
#endif
|
||||
+898
@@ -0,0 +1,898 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Digital Sound Processing - FFMPEG backend
|
||||
*
|
||||
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2018 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <freerdp/config.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/avutil.h>
|
||||
#include <libavutil/opt.h>
|
||||
#if defined(SWRESAMPLE_FOUND)
|
||||
#include <libswresample/swresample.h>
|
||||
#elif defined(AVRESAMPLE_FOUND)
|
||||
#include <libavresample/avresample.h>
|
||||
#else
|
||||
#error "libswresample or libavresample required"
|
||||
#endif
|
||||
|
||||
#include "dsp.h"
|
||||
#include "dsp_ffmpeg.h"
|
||||
|
||||
#define TAG FREERDP_TAG("dsp.ffmpeg")
|
||||
|
||||
struct S_FREERDP_DSP_CONTEXT
|
||||
{
|
||||
FREERDP_DSP_COMMON_CONTEXT common;
|
||||
|
||||
BOOL isOpen;
|
||||
|
||||
UINT32 bufferedSamples;
|
||||
|
||||
enum AVCodecID id;
|
||||
const AVCodec* codec;
|
||||
AVCodecContext* context;
|
||||
AVFrame* frame;
|
||||
AVFrame* resampled;
|
||||
AVFrame* buffered;
|
||||
AVPacket* packet;
|
||||
#if defined(SWRESAMPLE_FOUND)
|
||||
SwrContext* rcontext;
|
||||
#else
|
||||
AVAudioResampleContext* rcontext;
|
||||
#endif
|
||||
};
|
||||
|
||||
static BOOL ffmpeg_codec_is_filtered(enum AVCodecID id, WINPR_ATTR_UNUSED BOOL encoder)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
#if !defined(WITH_DSP_EXPERIMENTAL)
|
||||
|
||||
case AV_CODEC_ID_ADPCM_IMA_OKI:
|
||||
case AV_CODEC_ID_MP3:
|
||||
case AV_CODEC_ID_ADPCM_MS:
|
||||
case AV_CODEC_ID_G723_1:
|
||||
case AV_CODEC_ID_GSM_MS:
|
||||
case AV_CODEC_ID_PCM_ALAW:
|
||||
case AV_CODEC_ID_PCM_MULAW:
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
case AV_CODEC_ID_NONE:
|
||||
return TRUE;
|
||||
|
||||
case AV_CODEC_ID_AAC:
|
||||
case AV_CODEC_ID_AAC_LATM:
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static enum AVCodecID ffmpeg_get_avcodec(const AUDIO_FORMAT* WINPR_RESTRICT format)
|
||||
{
|
||||
if (!format)
|
||||
return AV_CODEC_ID_NONE;
|
||||
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_UNKNOWN:
|
||||
return AV_CODEC_ID_NONE;
|
||||
|
||||
case WAVE_FORMAT_PCM:
|
||||
switch (format->wBitsPerSample)
|
||||
{
|
||||
case 16:
|
||||
return AV_CODEC_ID_PCM_U16LE;
|
||||
|
||||
case 8:
|
||||
return AV_CODEC_ID_PCM_U8;
|
||||
|
||||
default:
|
||||
return AV_CODEC_ID_NONE;
|
||||
}
|
||||
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
return AV_CODEC_ID_ADPCM_IMA_OKI;
|
||||
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
return AV_CODEC_ID_ADPCM_MS;
|
||||
|
||||
case WAVE_FORMAT_ALAW:
|
||||
return AV_CODEC_ID_PCM_ALAW;
|
||||
|
||||
case WAVE_FORMAT_MULAW:
|
||||
return AV_CODEC_ID_PCM_MULAW;
|
||||
|
||||
case WAVE_FORMAT_GSM610:
|
||||
return AV_CODEC_ID_GSM_MS;
|
||||
|
||||
case WAVE_FORMAT_MSG723:
|
||||
return AV_CODEC_ID_G723_1;
|
||||
|
||||
case WAVE_FORMAT_AAC_MS:
|
||||
return AV_CODEC_ID_AAC;
|
||||
|
||||
case WAVE_FORMAT_OPUS:
|
||||
return AV_CODEC_ID_OPUS;
|
||||
|
||||
default:
|
||||
return AV_CODEC_ID_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static enum AVSampleFormat ffmpeg_sample_format(const AUDIO_FORMAT* WINPR_RESTRICT format)
|
||||
{
|
||||
switch (format->wFormatTag)
|
||||
{
|
||||
case WAVE_FORMAT_PCM:
|
||||
switch (format->wBitsPerSample)
|
||||
{
|
||||
case 8:
|
||||
return AV_SAMPLE_FMT_U8;
|
||||
|
||||
case 16:
|
||||
return AV_SAMPLE_FMT_S16;
|
||||
|
||||
default:
|
||||
return AV_SAMPLE_FMT_NONE;
|
||||
}
|
||||
|
||||
case WAVE_FORMAT_DVI_ADPCM:
|
||||
case WAVE_FORMAT_ADPCM:
|
||||
return AV_SAMPLE_FMT_S16P;
|
||||
|
||||
case WAVE_FORMAT_MPEGLAYER3:
|
||||
case WAVE_FORMAT_AAC_MS:
|
||||
return AV_SAMPLE_FMT_FLTP;
|
||||
|
||||
case WAVE_FORMAT_OPUS:
|
||||
return AV_SAMPLE_FMT_S16;
|
||||
|
||||
case WAVE_FORMAT_MSG723:
|
||||
case WAVE_FORMAT_GSM610:
|
||||
return AV_SAMPLE_FMT_S16P;
|
||||
|
||||
case WAVE_FORMAT_ALAW:
|
||||
return AV_SAMPLE_FMT_S16;
|
||||
|
||||
default:
|
||||
return AV_SAMPLE_FMT_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static void ffmpeg_close_context(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
if (context->context)
|
||||
avcodec_free_context(&context->context);
|
||||
|
||||
if (context->frame)
|
||||
av_frame_free(&context->frame);
|
||||
|
||||
if (context->resampled)
|
||||
av_frame_free(&context->resampled);
|
||||
|
||||
if (context->buffered)
|
||||
av_frame_free(&context->buffered);
|
||||
|
||||
if (context->packet)
|
||||
av_packet_free(&context->packet);
|
||||
|
||||
if (context->rcontext)
|
||||
{
|
||||
#if defined(SWRESAMPLE_FOUND)
|
||||
swr_free(&context->rcontext);
|
||||
#else
|
||||
avresample_free(&context->rcontext);
|
||||
#endif
|
||||
}
|
||||
|
||||
context->id = AV_CODEC_ID_NONE;
|
||||
context->codec = nullptr;
|
||||
context->isOpen = FALSE;
|
||||
context->context = nullptr;
|
||||
context->frame = nullptr;
|
||||
context->resampled = nullptr;
|
||||
context->packet = nullptr;
|
||||
context->rcontext = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void ffmpeg_setup_resample_frame(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
|
||||
const AUDIO_FORMAT* WINPR_RESTRICT format)
|
||||
{
|
||||
if (context->resampled->buf[0] != nullptr)
|
||||
av_frame_unref(context->resampled);
|
||||
|
||||
if (context->common.encoder)
|
||||
{
|
||||
context->resampled->format = context->context->sample_fmt;
|
||||
context->resampled->sample_rate = context->context->sample_rate;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->resampled->format = AV_SAMPLE_FMT_S16;
|
||||
|
||||
WINPR_ASSERT(format->nSamplesPerSec <= INT_MAX);
|
||||
context->resampled->sample_rate = (int)format->nSamplesPerSec;
|
||||
}
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
|
||||
av_channel_layout_default(&context->resampled->ch_layout, format->nChannels);
|
||||
#else
|
||||
const int64_t layout = av_get_default_channel_layout(format->nChannels);
|
||||
context->resampled->channel_layout = layout;
|
||||
context->resampled->channels = format->nChannels;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BOOL ffmpeg_open_context(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!context || context->isOpen)
|
||||
return FALSE;
|
||||
|
||||
const AUDIO_FORMAT* format = &context->common.format;
|
||||
|
||||
if (!format)
|
||||
return FALSE;
|
||||
context->id = ffmpeg_get_avcodec(format);
|
||||
|
||||
if (ffmpeg_codec_is_filtered(context->id, context->common.encoder))
|
||||
goto fail;
|
||||
|
||||
if (context->common.encoder)
|
||||
context->codec = avcodec_find_encoder(context->id);
|
||||
else
|
||||
context->codec = avcodec_find_decoder(context->id);
|
||||
|
||||
if (!context->codec)
|
||||
goto fail;
|
||||
|
||||
context->context = avcodec_alloc_context3(context->codec);
|
||||
|
||||
if (!context->context)
|
||||
goto fail;
|
||||
|
||||
switch (context->id)
|
||||
{
|
||||
/* We need support for multichannel and sample rates != 8000 */
|
||||
case AV_CODEC_ID_GSM_MS:
|
||||
context->context->strict_std_compliance = FF_COMPLIANCE_UNOFFICIAL;
|
||||
break;
|
||||
|
||||
case AV_CODEC_ID_AAC:
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(60, 31, 102)
|
||||
context->context->profile = FF_PROFILE_AAC_MAIN;
|
||||
#elif LIBAVCODEC_VERSION_INT < AV_VERSION_INT(62, 11, 100)
|
||||
context->context->profile = AV_PROFILE_AAC_MAIN;
|
||||
#else
|
||||
context->context->profile = AV_PROFILE_AAC_LOW;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
context->context->max_b_frames = 1;
|
||||
context->context->delay = 0;
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
|
||||
av_channel_layout_default(&context->context->ch_layout, format->nChannels);
|
||||
#else
|
||||
context->context->channels = format->nChannels;
|
||||
const int64_t layout = av_get_default_channel_layout(format->nChannels);
|
||||
context->context->channel_layout = layout;
|
||||
#endif
|
||||
context->context->sample_rate = (int)format->nSamplesPerSec;
|
||||
context->context->block_align = format->nBlockAlign;
|
||||
context->context->bit_rate = format->nAvgBytesPerSec * 8LL;
|
||||
context->context->sample_fmt = ffmpeg_sample_format(format);
|
||||
context->context->time_base = av_make_q(1, context->context->sample_rate);
|
||||
|
||||
if ((ret = avcodec_open2(context->context, context->codec, nullptr)) < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error avcodec_open2 %s [%d]", err, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
context->packet = av_packet_alloc();
|
||||
|
||||
if (!context->packet)
|
||||
goto fail;
|
||||
|
||||
context->frame = av_frame_alloc();
|
||||
|
||||
if (!context->frame)
|
||||
goto fail;
|
||||
|
||||
context->resampled = av_frame_alloc();
|
||||
|
||||
if (!context->resampled)
|
||||
goto fail;
|
||||
|
||||
context->buffered = av_frame_alloc();
|
||||
|
||||
if (!context->buffered)
|
||||
goto fail;
|
||||
|
||||
#if defined(SWRESAMPLE_FOUND)
|
||||
context->rcontext = swr_alloc();
|
||||
#else
|
||||
context->rcontext = avresample_alloc_context();
|
||||
#endif
|
||||
|
||||
if (!context->rcontext)
|
||||
goto fail;
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
|
||||
av_channel_layout_default(&context->frame->ch_layout, format->nChannels);
|
||||
#else
|
||||
context->frame->channel_layout = layout;
|
||||
context->frame->channels = format->nChannels;
|
||||
#endif
|
||||
WINPR_ASSERT(format->nSamplesPerSec <= INT_MAX);
|
||||
context->frame->sample_rate = (int)format->nSamplesPerSec;
|
||||
context->frame->format = AV_SAMPLE_FMT_S16;
|
||||
|
||||
ffmpeg_setup_resample_frame(context, format);
|
||||
|
||||
if (context->context->frame_size > 0)
|
||||
{
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
|
||||
ret = av_channel_layout_copy(&context->buffered->ch_layout, &context->resampled->ch_layout);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
#else
|
||||
context->buffered->channel_layout = context->resampled->channel_layout;
|
||||
context->buffered->channels = context->resampled->channels;
|
||||
#endif
|
||||
context->buffered->format = context->resampled->format;
|
||||
context->buffered->nb_samples = context->context->frame_size;
|
||||
|
||||
ret = av_frame_get_buffer(context->buffered, 1);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
context->isOpen = TRUE;
|
||||
return TRUE;
|
||||
fail:
|
||||
ffmpeg_close_context(context);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if defined(SWRESAMPLE_FOUND)
|
||||
static BOOL ffmpeg_resample_frame(SwrContext* WINPR_RESTRICT context, AVFrame* WINPR_RESTRICT in,
|
||||
AVFrame* WINPR_RESTRICT out)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!swr_is_initialized(context))
|
||||
{
|
||||
if ((ret = swr_config_frame(context, out, in)) < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((ret = (swr_init(context))) < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = swr_convert_frame(context, out, in)) < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#else
|
||||
static BOOL ffmpeg_resample_frame(AVAudioResampleContext* WINPR_RESTRICT context,
|
||||
AVFrame* WINPR_RESTRICT in, AVFrame* WINPR_RESTRICT out)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!avresample_is_open(context))
|
||||
{
|
||||
if ((ret = avresample_config(context, out, in)) < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((ret = (avresample_open(context))) < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = avresample_convert_frame(context, out, in)) < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL ffmpeg_encode_frame(AVCodecContext* WINPR_RESTRICT context, AVFrame* WINPR_RESTRICT in,
|
||||
AVPacket* WINPR_RESTRICT packet, wStream* WINPR_RESTRICT out)
|
||||
{
|
||||
if (in->format == AV_SAMPLE_FMT_FLTP)
|
||||
{
|
||||
uint8_t** pp = in->extended_data;
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(57, 28, 100)
|
||||
const int nr_channels = in->channels;
|
||||
#else
|
||||
const int nr_channels = in->ch_layout.nb_channels;
|
||||
#endif
|
||||
|
||||
for (int y = 0; y < nr_channels; y++)
|
||||
{
|
||||
float* data = (float*)pp[y];
|
||||
for (int x = 0; x < in->nb_samples; x++)
|
||||
{
|
||||
const float val1 = data[x];
|
||||
if (isnan(val1))
|
||||
data[x] = 0.0f;
|
||||
else if (isinf(val1))
|
||||
{
|
||||
if (val1 < 0.0f)
|
||||
data[x] = -1.0f;
|
||||
else
|
||||
data[x] = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* send the packet with the compressed data to the encoder */
|
||||
int ret = avcodec_send_frame(context, in);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
// Ignore errors: AAC encoder sometimes returns -22
|
||||
// The log message from ffmpeg is '[aac @ 0x7f140db753c0] Input contains (near) NaN/+-Inf'
|
||||
if (ret == AVERROR(EINVAL))
|
||||
{
|
||||
WLog_DBG(TAG, "Error submitting the packet to the encoder %s [%d], ignoring", err, ret);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WLog_ERR(TAG, "Error submitting the packet to the encoder %s [%d]", err, ret);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* read all the output frames (in general there may be any number of them */
|
||||
while (TRUE)
|
||||
{
|
||||
ret = avcodec_receive_packet(context, packet);
|
||||
|
||||
if ((ret == AVERROR(EAGAIN)) || (ret == AVERROR_EOF))
|
||||
break;
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during encoding %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(packet->size >= 0);
|
||||
if (!Stream_EnsureRemainingCapacity(out, (size_t)packet->size))
|
||||
return FALSE;
|
||||
|
||||
Stream_Write(out, packet->data, (size_t)packet->size);
|
||||
av_packet_unref(packet);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL ffmpeg_fill_frame(AVFrame* WINPR_RESTRICT frame,
|
||||
const AUDIO_FORMAT* WINPR_RESTRICT inputFormat,
|
||||
const BYTE* WINPR_RESTRICT data, size_t size)
|
||||
{
|
||||
int ret = 0;
|
||||
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(57, 28, 100)
|
||||
frame->channels = inputFormat->nChannels;
|
||||
frame->channel_layout = av_get_default_channel_layout(frame->channels);
|
||||
#else
|
||||
av_channel_layout_default(&frame->ch_layout, inputFormat->nChannels);
|
||||
#endif
|
||||
WINPR_ASSERT(inputFormat->nSamplesPerSec <= INT_MAX);
|
||||
frame->sample_rate = (int)inputFormat->nSamplesPerSec;
|
||||
frame->format = ffmpeg_sample_format(inputFormat);
|
||||
|
||||
const int bpp =
|
||||
av_get_bytes_per_sample(WINPR_ASSERTING_INT_CAST(enum AVSampleFormat, frame->format));
|
||||
WINPR_ASSERT(bpp >= 0);
|
||||
WINPR_ASSERT(size <= INT_MAX);
|
||||
const size_t nb_samples = size / inputFormat->nChannels / (size_t)bpp;
|
||||
frame->nb_samples = (int)nb_samples;
|
||||
|
||||
if ((ret = avcodec_fill_audio_frame(
|
||||
frame, inputFormat->nChannels,
|
||||
WINPR_ASSERTING_INT_CAST(enum AVSampleFormat, frame->format), data, (int)size, 1)) < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during audio frame fill %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#if defined(SWRESAMPLE_FOUND)
|
||||
static BOOL ffmpeg_decode(AVCodecContext* WINPR_RESTRICT dec_ctx, AVPacket* WINPR_RESTRICT pkt,
|
||||
AVFrame* WINPR_RESTRICT frame, SwrContext* WINPR_RESTRICT resampleContext,
|
||||
AVFrame* WINPR_RESTRICT resampled, wStream* WINPR_RESTRICT out)
|
||||
#else
|
||||
static BOOL ffmpeg_decode(AVCodecContext* dec_ctx, AVPacket* pkt, AVFrame* frame,
|
||||
AVAudioResampleContext* resampleContext, AVFrame* resampled, wStream* out)
|
||||
#endif
|
||||
{
|
||||
/* send the packet with the compressed data to the decoder */
|
||||
int ret = avcodec_send_packet(dec_ctx, pkt);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error submitting the packet to the decoder %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* read all the output frames (in general there may be any number of them */
|
||||
while (ret >= 0)
|
||||
{
|
||||
ret = avcodec_receive_frame(dec_ctx, frame);
|
||||
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
||||
break;
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during decoding %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if defined(SWRESAMPLE_FOUND)
|
||||
if (!swr_is_initialized(resampleContext))
|
||||
{
|
||||
if ((ret = swr_config_frame(resampleContext, resampled, frame)) < 0)
|
||||
{
|
||||
#else
|
||||
if (!avresample_is_open(resampleContext))
|
||||
{
|
||||
if ((ret = avresample_config(resampleContext, resampled, frame)) < 0)
|
||||
{
|
||||
#endif
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if defined(SWRESAMPLE_FOUND)
|
||||
ret = (swr_init(resampleContext));
|
||||
#else
|
||||
ret = (avresample_open(resampleContext));
|
||||
#endif
|
||||
if (ret < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SWRESAMPLE_FOUND)
|
||||
ret = swr_convert_frame(resampleContext, resampled, frame);
|
||||
#else
|
||||
ret = avresample_convert_frame(resampleContext, resampled, frame);
|
||||
#endif
|
||||
if (ret < 0)
|
||||
{
|
||||
const char* err = av_err2str(ret);
|
||||
WLog_ERR(TAG, "Error during resampling %s [%d]", err, ret);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
|
||||
WINPR_ASSERT(resampled->ch_layout.nb_channels >= 0);
|
||||
const size_t nrchannels = (size_t)resampled->ch_layout.nb_channels;
|
||||
#else
|
||||
const size_t nrchannels = resampled->channels;
|
||||
#endif
|
||||
WINPR_ASSERT(resampled->nb_samples >= 0);
|
||||
const size_t data_size = nrchannels * (size_t)resampled->nb_samples * 2ull;
|
||||
if (!Stream_EnsureRemainingCapacity(out, data_size))
|
||||
return FALSE;
|
||||
Stream_Write(out, resampled->data[0], data_size);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL freerdp_dsp_ffmpeg_supports_format(const AUDIO_FORMAT* WINPR_RESTRICT format, BOOL encode)
|
||||
{
|
||||
enum AVCodecID id = ffmpeg_get_avcodec(format);
|
||||
|
||||
if (ffmpeg_codec_is_filtered(id, encode))
|
||||
return FALSE;
|
||||
|
||||
if (encode)
|
||||
return avcodec_find_encoder(id) != nullptr;
|
||||
else
|
||||
return avcodec_find_decoder(id) != nullptr;
|
||||
}
|
||||
|
||||
FREERDP_DSP_CONTEXT* freerdp_dsp_ffmpeg_context_new(BOOL encode)
|
||||
{
|
||||
FREERDP_DSP_CONTEXT* context = nullptr;
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
|
||||
avcodec_register_all();
|
||||
#endif
|
||||
context = calloc(1, sizeof(FREERDP_DSP_CONTEXT));
|
||||
|
||||
if (!context)
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_dsp_common_context_init(&context->common, encode))
|
||||
goto fail;
|
||||
|
||||
return context;
|
||||
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
freerdp_dsp_ffmpeg_context_free(context);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void freerdp_dsp_ffmpeg_context_free(FREERDP_DSP_CONTEXT* context)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
ffmpeg_close_context(context);
|
||||
freerdp_dsp_common_context_uninit(&context->common);
|
||||
free(context);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL freerdp_dsp_ffmpeg_context_reset(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
|
||||
const AUDIO_FORMAT* WINPR_RESTRICT targetFormat)
|
||||
{
|
||||
if (!context || !targetFormat)
|
||||
return FALSE;
|
||||
|
||||
ffmpeg_close_context(context);
|
||||
context->common.format = *targetFormat;
|
||||
return ffmpeg_open_context(context);
|
||||
}
|
||||
|
||||
static BOOL freerdp_dsp_channel_mix(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
|
||||
const BYTE* WINPR_RESTRICT src, size_t size,
|
||||
const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
|
||||
const BYTE** WINPR_RESTRICT data, size_t* WINPR_RESTRICT length,
|
||||
AUDIO_FORMAT* WINPR_RESTRICT dstFormat)
|
||||
{
|
||||
UINT32 bpp = 0;
|
||||
size_t samples = 0;
|
||||
|
||||
if (!context || !data || !length || !dstFormat)
|
||||
return FALSE;
|
||||
|
||||
if (srcFormat->wFormatTag != WAVE_FORMAT_PCM)
|
||||
return FALSE;
|
||||
|
||||
bpp = srcFormat->wBitsPerSample > 8 ? 2 : 1;
|
||||
samples = size / bpp / srcFormat->nChannels;
|
||||
|
||||
*dstFormat = *srcFormat;
|
||||
if (context->common.format.nChannels == srcFormat->nChannels)
|
||||
{
|
||||
*data = src;
|
||||
*length = size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Stream_ResetPosition(context->common.channelmix);
|
||||
|
||||
/* Destination has more channels than source */
|
||||
if (context->common.format.nChannels > srcFormat->nChannels)
|
||||
{
|
||||
switch (srcFormat->nChannels)
|
||||
{
|
||||
case 1:
|
||||
if (!Stream_EnsureCapacity(context->common.channelmix, size * 2))
|
||||
return FALSE;
|
||||
|
||||
for (size_t x = 0; x < samples; x++)
|
||||
{
|
||||
for (size_t y = 0; y < bpp; y++)
|
||||
Stream_Write_UINT8(context->common.channelmix, src[x * bpp + y]);
|
||||
|
||||
for (size_t y = 0; y < bpp; y++)
|
||||
Stream_Write_UINT8(context->common.channelmix, src[x * bpp + y]);
|
||||
}
|
||||
|
||||
Stream_SealLength(context->common.channelmix);
|
||||
*data = Stream_Buffer(context->common.channelmix);
|
||||
*length = Stream_Length(context->common.channelmix);
|
||||
dstFormat->nChannels = 2;
|
||||
return TRUE;
|
||||
|
||||
case 2: /* We only support stereo, so we can not handle this case. */
|
||||
default: /* Unsupported number of channels */
|
||||
WLog_WARN(TAG, "[%s] unsupported source channel count %" PRIu16, __func__,
|
||||
srcFormat->nChannels);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Destination has less channels than source */
|
||||
switch (srcFormat->nChannels)
|
||||
{
|
||||
case 2:
|
||||
if (!Stream_EnsureCapacity(context->common.channelmix, size / 2))
|
||||
return FALSE;
|
||||
|
||||
/* Simply drop second channel.
|
||||
* TODO: Calculate average */
|
||||
for (size_t x = 0; x < samples; x++)
|
||||
{
|
||||
for (size_t y = 0; y < bpp; y++)
|
||||
Stream_Write_UINT8(context->common.channelmix, src[2 * x * bpp + y]);
|
||||
}
|
||||
|
||||
Stream_SealLength(context->common.channelmix);
|
||||
*data = Stream_Buffer(context->common.channelmix);
|
||||
*length = Stream_Length(context->common.channelmix);
|
||||
dstFormat->nChannels = 1;
|
||||
return TRUE;
|
||||
|
||||
case 1: /* Invalid, do we want to use a 0 channel sound? */
|
||||
default: /* Unsupported number of channels */
|
||||
WLog_WARN(TAG, "[%s] unsupported channel count %" PRIu16, __func__,
|
||||
srcFormat->nChannels);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL freerdp_dsp_ffmpeg_encode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
|
||||
const AUDIO_FORMAT* WINPR_RESTRICT format,
|
||||
const BYTE* WINPR_RESTRICT sdata, size_t length,
|
||||
wStream* WINPR_RESTRICT out)
|
||||
{
|
||||
AUDIO_FORMAT fmt = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (!context || !format || !sdata || !out || !context->common.encoder)
|
||||
return FALSE;
|
||||
|
||||
/* https://github.com/FreeRDP/FreeRDP/issues/7607
|
||||
*
|
||||
* we get noisy data with channel transformation, so do it ourselves.
|
||||
*/
|
||||
const BYTE* data = nullptr;
|
||||
if (!freerdp_dsp_channel_mix(context, sdata, length, format, &data, &length, &fmt))
|
||||
return FALSE;
|
||||
|
||||
/* Create input frame */
|
||||
if (!ffmpeg_fill_frame(context->frame, format, data, length))
|
||||
return FALSE;
|
||||
|
||||
ffmpeg_setup_resample_frame(context, format);
|
||||
/* Resample to desired format. */
|
||||
if (!ffmpeg_resample_frame(context->rcontext, context->frame, context->resampled))
|
||||
return FALSE;
|
||||
|
||||
if (context->context->frame_size <= 0)
|
||||
{
|
||||
return ffmpeg_encode_frame(context->context, context->resampled, context->packet, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
int copied = 0;
|
||||
int rest = context->resampled->nb_samples;
|
||||
|
||||
do
|
||||
{
|
||||
int inSamples = rest;
|
||||
|
||||
if ((inSamples < 0) || (context->bufferedSamples > (UINT32)(INT_MAX - inSamples)))
|
||||
return FALSE;
|
||||
|
||||
if (inSamples + (int)context->bufferedSamples > context->context->frame_size)
|
||||
inSamples = context->context->frame_size - (int)context->bufferedSamples;
|
||||
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
|
||||
const int nrchannels = context->context->ch_layout.nb_channels;
|
||||
#else
|
||||
const int nrchannels = context->context->channels;
|
||||
#endif
|
||||
const int rc =
|
||||
av_samples_copy(context->buffered->extended_data, context->resampled->extended_data,
|
||||
(int)context->bufferedSamples, copied, inSamples, nrchannels,
|
||||
context->context->sample_fmt);
|
||||
if (rc < 0)
|
||||
return FALSE;
|
||||
rest -= inSamples;
|
||||
copied += inSamples;
|
||||
context->bufferedSamples += (UINT32)inSamples;
|
||||
|
||||
if (context->context->frame_size <= (int)context->bufferedSamples)
|
||||
{
|
||||
/* Encode in desired format. */
|
||||
if (!ffmpeg_encode_frame(context->context, context->buffered, context->packet, out))
|
||||
return FALSE;
|
||||
|
||||
context->bufferedSamples = 0;
|
||||
}
|
||||
} while (rest > 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL freerdp_dsp_ffmpeg_decode(FREERDP_DSP_CONTEXT* WINPR_RESTRICT context,
|
||||
const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
|
||||
const BYTE* WINPR_RESTRICT data, size_t length,
|
||||
wStream* WINPR_RESTRICT out)
|
||||
{
|
||||
if (!context || !srcFormat || !data || !out || context->common.encoder)
|
||||
return FALSE;
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
|
||||
av_init_packet(context->packet);
|
||||
#endif
|
||||
context->packet->data = WINPR_CAST_CONST_PTR_AWAY(data, uint8_t*);
|
||||
|
||||
WINPR_ASSERT(length <= INT_MAX);
|
||||
context->packet->size = (int)length;
|
||||
return ffmpeg_decode(context->context, context->packet, context->frame, context->rcontext,
|
||||
context->resampled, out);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Digital Sound Processing - FFMPEG backend
|
||||
*
|
||||
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2018 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 FREERDP_LIB_CODEC_DSP_FFMPEG_H
|
||||
#define FREERDP_LIB_CODEC_DSP_FFMPEG_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/codec/audio.h>
|
||||
#include <freerdp/codec/dsp.h>
|
||||
|
||||
#include <libavcodec/version.h>
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
|
||||
#error \
|
||||
"DSP module requires libavcodec version >= 57.48.101. Upgrade or set WITH_DSP_FFMPEG=OFF to continue"
|
||||
#endif
|
||||
|
||||
FREERDP_LOCAL void freerdp_dsp_ffmpeg_context_free(FREERDP_DSP_CONTEXT* context);
|
||||
|
||||
WINPR_ATTR_MALLOC(freerdp_dsp_ffmpeg_context_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL FREERDP_DSP_CONTEXT* freerdp_dsp_ffmpeg_context_new(BOOL encode);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL
|
||||
freerdp_dsp_ffmpeg_supports_format(const AUDIO_FORMAT* format, BOOL encode);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL freerdp_dsp_ffmpeg_encode(FREERDP_DSP_CONTEXT* context,
|
||||
const AUDIO_FORMAT* srcFormat,
|
||||
const BYTE* data, size_t length,
|
||||
wStream* out);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL freerdp_dsp_ffmpeg_decode(FREERDP_DSP_CONTEXT* context,
|
||||
const AUDIO_FORMAT* srcFormat,
|
||||
const BYTE* data, size_t length,
|
||||
wStream* out);
|
||||
|
||||
WINPR_ATTR_NODISCARD FREERDP_LOCAL BOOL
|
||||
freerdp_dsp_ffmpeg_context_reset(FREERDP_DSP_CONTEXT* context, const AUDIO_FORMAT* targetFormat);
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_DSP_FFMPEG_H */
|
||||
+895
@@ -0,0 +1,895 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* H.264 Bitmap Compression
|
||||
*
|
||||
* Copyright 2014 Mike McDonald <Mike.McDonald@software.dell.com>
|
||||
* Copyright 2017 David Fort <contact@hardening-consulting.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 <freerdp/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/library.h>
|
||||
#include <winpr/bitstream.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#include <freerdp/primitives.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
#include <freerdp/codec/yuv.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "h264.h"
|
||||
|
||||
#define TAG FREERDP_TAG("codec")
|
||||
|
||||
static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, DWORD nDstHeight);
|
||||
|
||||
static BOOL yuv_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT32 height)
|
||||
{
|
||||
BOOL isNull = FALSE;
|
||||
UINT32 pheight = height;
|
||||
|
||||
if (!h264)
|
||||
return FALSE;
|
||||
|
||||
if (stride == 0)
|
||||
stride = width;
|
||||
|
||||
if (stride % 16 != 0)
|
||||
stride += 16 - stride % 16;
|
||||
|
||||
if (pheight % 16 != 0)
|
||||
pheight += 16 - pheight % 16;
|
||||
|
||||
const size_t nPlanes = h264->hwAccel ? 2 : 3;
|
||||
|
||||
for (size_t x = 0; x < nPlanes; x++)
|
||||
{
|
||||
if (!h264->pYUVData[x] || !h264->pOldYUVData[x])
|
||||
isNull = TRUE;
|
||||
}
|
||||
|
||||
if (pheight == 0)
|
||||
return FALSE;
|
||||
if (stride == 0)
|
||||
return FALSE;
|
||||
|
||||
if (isNull || (width != h264->width) || (height != h264->height) ||
|
||||
(stride != h264->iStride[0]))
|
||||
{
|
||||
if (h264->hwAccel) /* NV12 */
|
||||
{
|
||||
h264->iStride[0] = stride;
|
||||
h264->iStride[1] = stride;
|
||||
h264->iStride[2] = 0;
|
||||
}
|
||||
else /* I420 */
|
||||
{
|
||||
h264->iStride[0] = stride;
|
||||
h264->iStride[1] = (stride + 1) / 2;
|
||||
h264->iStride[2] = (stride + 1) / 2;
|
||||
}
|
||||
|
||||
h264->width = width;
|
||||
h264->height = height;
|
||||
|
||||
for (size_t x = 0; x < nPlanes; x++)
|
||||
{
|
||||
BYTE* tmp1 = winpr_aligned_recalloc(h264->pYUVData[x], h264->iStride[x], pheight, 16);
|
||||
BYTE* tmp2 =
|
||||
winpr_aligned_recalloc(h264->pOldYUVData[x], h264->iStride[x], pheight, 16);
|
||||
if (tmp1)
|
||||
h264->pYUVData[x] = tmp1;
|
||||
if (tmp2)
|
||||
h264->pOldYUVData[x] = tmp2;
|
||||
if (!tmp1 || !tmp2)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width, UINT32 height)
|
||||
{
|
||||
return yuv_ensure_buffer(h264, stride, width, height);
|
||||
}
|
||||
|
||||
static BOOL isRectValid(UINT32 width, UINT32 height, const RECTANGLE_16* rect)
|
||||
{
|
||||
WINPR_ASSERT(rect);
|
||||
if (rect->left > width)
|
||||
return FALSE;
|
||||
if (rect->right > width)
|
||||
return FALSE;
|
||||
if (rect->left >= rect->right)
|
||||
return FALSE;
|
||||
if (rect->top > height)
|
||||
return FALSE;
|
||||
if (rect->bottom > height)
|
||||
return FALSE;
|
||||
if (rect->top >= rect->bottom)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL areRectsValid(UINT32 width, UINT32 height, const RECTANGLE_16* rects, UINT32 count)
|
||||
{
|
||||
WINPR_ASSERT(rects || (count == 0));
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
const RECTANGLE_16* rect = &rects[x];
|
||||
if (!isRectValid(width, height, rect))
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
INT32 avc420_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData,
|
||||
DWORD DstFormat, UINT32 nDstStep, WINPR_ATTR_UNUSED UINT32 nDstWidth,
|
||||
WINPR_ATTR_UNUSED UINT32 nDstHeight, const RECTANGLE_16* regionRects,
|
||||
UINT32 numRegionRects)
|
||||
{
|
||||
int status = 0;
|
||||
const BYTE* pYUVData[3];
|
||||
|
||||
if (!h264 || h264->Compressor)
|
||||
return -1001;
|
||||
|
||||
if (!areRectsValid(nDstWidth, nDstHeight, regionRects, numRegionRects))
|
||||
return -1013;
|
||||
|
||||
status = h264->subsystem->Decompress(h264, pSrcData, SrcSize);
|
||||
|
||||
if (status == 0)
|
||||
return 1;
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
pYUVData[0] = h264->pYUVData[0];
|
||||
pYUVData[1] = h264->pYUVData[1];
|
||||
pYUVData[2] = h264->pYUVData[2];
|
||||
if (!yuv420_context_decode(h264->yuv, pYUVData, h264->iStride, h264->height, DstFormat,
|
||||
pDstData, nDstStep, regionRects, numRegionRects))
|
||||
return -1002;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL allocate_h264_metablock(UINT32 QP, RECTANGLE_16* rectangles,
|
||||
RDPGFX_H264_METABLOCK* meta, size_t count)
|
||||
{
|
||||
/* [MS-RDPEGFX] 2.2.4.4.2 RDPGFX_AVC420_QUANT_QUALITY */
|
||||
if (!meta || (QP > UINT8_MAX))
|
||||
{
|
||||
free(rectangles);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
meta->regionRects = rectangles;
|
||||
if (count == 0)
|
||||
return TRUE;
|
||||
|
||||
if (count > UINT32_MAX)
|
||||
return FALSE;
|
||||
|
||||
meta->quantQualityVals = calloc(count, sizeof(RDPGFX_H264_QUANT_QUALITY));
|
||||
|
||||
if (!meta->quantQualityVals || !meta->regionRects)
|
||||
return FALSE;
|
||||
meta->numRegionRects = (UINT32)count;
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
RDPGFX_H264_QUANT_QUALITY* cur = &meta->quantQualityVals[x];
|
||||
cur->qp = (UINT8)QP;
|
||||
|
||||
/* qpVal bit 6 and 7 are flags, so mask them out here.
|
||||
* qualityVal is [0-100] so 100 - qpVal [0-64] is always in range */
|
||||
cur->qualityVal = 100 - (QP & 0x3F);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline BOOL diff_tile(const RECTANGLE_16* regionRect, BYTE* pYUVData[3],
|
||||
BYTE* pOldYUVData[3], UINT32 const iStride[3])
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
if (!regionRect || !pYUVData || !pOldYUVData || !iStride)
|
||||
return FALSE;
|
||||
size = regionRect->right - regionRect->left;
|
||||
if (regionRect->right > iStride[0])
|
||||
return FALSE;
|
||||
if (regionRect->right / 2u > iStride[1])
|
||||
return FALSE;
|
||||
if (regionRect->right / 2u > iStride[2])
|
||||
return FALSE;
|
||||
|
||||
for (size_t y = regionRect->top; y < regionRect->bottom; y++)
|
||||
{
|
||||
const BYTE* cur0 = &pYUVData[0][y * iStride[0]];
|
||||
const BYTE* cur1 = &pYUVData[1][y * iStride[1]];
|
||||
const BYTE* cur2 = &pYUVData[2][y * iStride[2]];
|
||||
const BYTE* old0 = &pOldYUVData[0][y * iStride[0]];
|
||||
const BYTE* old1 = &pOldYUVData[1][y * iStride[1]];
|
||||
const BYTE* old2 = &pOldYUVData[2][y * iStride[2]];
|
||||
|
||||
if (memcmp(&cur0[regionRect->left], &old0[regionRect->left], size) != 0)
|
||||
return TRUE;
|
||||
if (memcmp(&cur1[regionRect->left / 2], &old1[regionRect->left / 2], size / 2) != 0)
|
||||
return TRUE;
|
||||
if (memcmp(&cur2[regionRect->left / 2], &old2[regionRect->left / 2], size / 2) != 0)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL detect_changes(BOOL firstFrameDone, const UINT32 QP, const RECTANGLE_16* regionRect,
|
||||
BYTE* pYUVData[3], BYTE* pOldYUVData[3], UINT32 const iStride[3],
|
||||
RDPGFX_H264_METABLOCK* meta)
|
||||
{
|
||||
size_t count = 0;
|
||||
size_t wc = 0;
|
||||
size_t hc = 0;
|
||||
RECTANGLE_16* rectangles = nullptr;
|
||||
|
||||
if (!regionRect || !pYUVData || !pOldYUVData || !iStride || !meta)
|
||||
return FALSE;
|
||||
|
||||
wc = (regionRect->right - regionRect->left) / 64 + 1;
|
||||
hc = (regionRect->bottom - regionRect->top) / 64 + 1;
|
||||
rectangles = calloc(wc * hc, sizeof(RECTANGLE_16));
|
||||
if (!rectangles)
|
||||
return FALSE;
|
||||
if (!firstFrameDone)
|
||||
{
|
||||
rectangles[0] = *regionRect;
|
||||
count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t y = regionRect->top; y < regionRect->bottom; y += 64)
|
||||
{
|
||||
for (size_t x = regionRect->left; x < regionRect->right; x += 64)
|
||||
{
|
||||
RECTANGLE_16 rect;
|
||||
rect.left = (UINT16)MIN(UINT16_MAX, regionRect->left + x);
|
||||
rect.top = (UINT16)MIN(UINT16_MAX, regionRect->top + y);
|
||||
rect.right =
|
||||
(UINT16)MIN(UINT16_MAX, MIN(regionRect->left + x + 64, regionRect->right));
|
||||
rect.bottom =
|
||||
(UINT16)MIN(UINT16_MAX, MIN(regionRect->top + y + 64, regionRect->bottom));
|
||||
if (diff_tile(&rect, pYUVData, pOldYUVData, iStride))
|
||||
rectangles[count++] = rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!allocate_h264_metablock(QP, rectangles, meta, count))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
INT32 h264_get_yuv_buffer(H264_CONTEXT* h264, UINT32 nSrcStride, UINT32 nSrcWidth,
|
||||
UINT32 nSrcHeight, BYTE* YUVData[3], UINT32 stride[3])
|
||||
{
|
||||
if (!h264 || !h264->Compressor || !h264->subsystem || !h264->subsystem->Compress)
|
||||
return -1;
|
||||
|
||||
if (!yuv_ensure_buffer(h264, nSrcStride, nSrcWidth, nSrcHeight))
|
||||
return -1;
|
||||
|
||||
for (size_t x = 0; x < 3; x++)
|
||||
{
|
||||
YUVData[x] = h264->pYUVData[x];
|
||||
stride[x] = h264->iStride[x];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 h264_compress(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize)
|
||||
{
|
||||
if (!h264 || !h264->Compressor || !h264->subsystem || !h264->subsystem->Compress)
|
||||
return -1;
|
||||
|
||||
const BYTE* pcYUVData[3] = { h264->pYUVData[0], h264->pYUVData[1], h264->pYUVData[2] };
|
||||
|
||||
return h264->subsystem->Compress(h264, pcYUVData, h264->iStride, ppDstData, pDstSize);
|
||||
}
|
||||
|
||||
INT32 avc420_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
|
||||
UINT32 nSrcWidth, UINT32 nSrcHeight, const RECTANGLE_16* regionRect,
|
||||
BYTE** ppDstData, UINT32* pDstSize, RDPGFX_H264_METABLOCK* meta)
|
||||
{
|
||||
INT32 rc = -1;
|
||||
BYTE* pYUVData[3] = WINPR_C_ARRAY_INIT;
|
||||
const BYTE* pcYUVData[3] = WINPR_C_ARRAY_INIT;
|
||||
BYTE* pOldYUVData[3] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (!h264 || !regionRect || !meta || !h264->Compressor)
|
||||
return -1;
|
||||
|
||||
if (!h264->subsystem->Compress)
|
||||
return -1;
|
||||
|
||||
if (!avc420_ensure_buffer(h264, nSrcStep, nSrcWidth, nSrcHeight))
|
||||
return -1;
|
||||
|
||||
if (h264->encodingBuffer)
|
||||
{
|
||||
for (size_t x = 0; x < 3; x++)
|
||||
{
|
||||
pYUVData[x] = h264->pYUVData[x];
|
||||
pOldYUVData[x] = h264->pOldYUVData[x];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t x = 0; x < 3; x++)
|
||||
{
|
||||
pYUVData[x] = h264->pOldYUVData[x];
|
||||
pOldYUVData[x] = h264->pYUVData[x];
|
||||
}
|
||||
}
|
||||
h264->encodingBuffer = !h264->encodingBuffer;
|
||||
|
||||
if (!yuv420_context_encode(h264->yuv, pSrcData, nSrcStep, SrcFormat, h264->iStride, pYUVData,
|
||||
regionRect, 1))
|
||||
goto fail;
|
||||
|
||||
if (!detect_changes(h264->firstLumaFrameDone, h264->QP, regionRect, pYUVData, pOldYUVData,
|
||||
h264->iStride, meta))
|
||||
goto fail;
|
||||
|
||||
if (meta->numRegionRects == 0)
|
||||
{
|
||||
rc = 0;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (size_t x = 0; x < 3; x++)
|
||||
pcYUVData[x] = pYUVData[x];
|
||||
|
||||
rc = h264->subsystem->Compress(h264, pcYUVData, h264->iStride, ppDstData, pDstSize);
|
||||
if (rc >= 0)
|
||||
h264->firstLumaFrameDone = TRUE;
|
||||
|
||||
fail:
|
||||
if (rc < 0)
|
||||
free_h264_metablock(meta);
|
||||
return rc;
|
||||
}
|
||||
|
||||
INT32 avc444_compress(H264_CONTEXT* h264, const BYTE* pSrcData, DWORD SrcFormat, UINT32 nSrcStep,
|
||||
UINT32 nSrcWidth, UINT32 nSrcHeight, BYTE version, const RECTANGLE_16* region,
|
||||
BYTE* op, BYTE** ppDstData, UINT32* pDstSize, BYTE** ppAuxDstData,
|
||||
UINT32* pAuxDstSize, RDPGFX_H264_METABLOCK* meta,
|
||||
RDPGFX_H264_METABLOCK* auxMeta)
|
||||
{
|
||||
int rc = -1;
|
||||
BYTE* coded = nullptr;
|
||||
UINT32 codedSize = 0;
|
||||
BYTE** pYUV444Data = nullptr;
|
||||
BYTE** pOldYUV444Data = nullptr;
|
||||
BYTE** pYUVData = nullptr;
|
||||
BYTE** pOldYUVData = nullptr;
|
||||
|
||||
if (!h264 || !h264->Compressor)
|
||||
return -1;
|
||||
|
||||
if (!h264->subsystem->Compress)
|
||||
return -1;
|
||||
|
||||
if (!avc420_ensure_buffer(h264, nSrcStep, nSrcWidth, nSrcHeight))
|
||||
return -1;
|
||||
|
||||
if (!avc444_ensure_buffer(h264, nSrcHeight))
|
||||
return -1;
|
||||
|
||||
if (h264->encodingBuffer)
|
||||
{
|
||||
pYUV444Data = h264->pOldYUV444Data;
|
||||
pOldYUV444Data = h264->pYUV444Data;
|
||||
pYUVData = h264->pOldYUVData;
|
||||
pOldYUVData = h264->pYUVData;
|
||||
}
|
||||
else
|
||||
{
|
||||
pYUV444Data = h264->pYUV444Data;
|
||||
pOldYUV444Data = h264->pOldYUV444Data;
|
||||
pYUVData = h264->pYUVData;
|
||||
pOldYUVData = h264->pOldYUVData;
|
||||
}
|
||||
h264->encodingBuffer = !h264->encodingBuffer;
|
||||
|
||||
if (!yuv444_context_encode(h264->yuv, version, pSrcData, nSrcStep, SrcFormat, h264->iStride,
|
||||
pYUV444Data, pYUVData, region, 1))
|
||||
goto fail;
|
||||
|
||||
if (!detect_changes(h264->firstLumaFrameDone, h264->QP, region, pYUV444Data, pOldYUV444Data,
|
||||
h264->iStride, meta))
|
||||
goto fail;
|
||||
if (!detect_changes(h264->firstChromaFrameDone, h264->QP, region, pYUVData, pOldYUVData,
|
||||
h264->iStride, auxMeta))
|
||||
goto fail;
|
||||
|
||||
/* [MS-RDPEGFX] 2.2.4.5 RFX_AVC444_BITMAP_STREAM
|
||||
* LC:
|
||||
* 0 ... Luma & Chroma
|
||||
* 1 ... Luma
|
||||
* 2 ... Chroma
|
||||
*/
|
||||
if ((meta->numRegionRects > 0) && (auxMeta->numRegionRects > 0))
|
||||
*op = 0;
|
||||
else if (meta->numRegionRects > 0)
|
||||
*op = 1;
|
||||
else if (auxMeta->numRegionRects > 0)
|
||||
*op = 2;
|
||||
else
|
||||
{
|
||||
WLog_INFO(TAG, "no changes detected for luma or chroma frame");
|
||||
rc = 0;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((*op == 0) || (*op == 1))
|
||||
{
|
||||
const BYTE* pcYUV444Data[3] = { pYUV444Data[0], pYUV444Data[1], pYUV444Data[2] };
|
||||
|
||||
if (h264->subsystem->Compress(h264, pcYUV444Data, h264->iStride, &coded, &codedSize) < 0)
|
||||
goto fail;
|
||||
h264->firstLumaFrameDone = TRUE;
|
||||
memcpy(h264->lumaData, coded, codedSize);
|
||||
*ppDstData = h264->lumaData;
|
||||
*pDstSize = codedSize;
|
||||
}
|
||||
|
||||
if ((*op == 0) || (*op == 2))
|
||||
{
|
||||
const BYTE* pcYUVData[3] = { pYUVData[0], pYUVData[1], pYUVData[2] };
|
||||
|
||||
if (h264->subsystem->Compress(h264, pcYUVData, h264->iStride, &coded, &codedSize) < 0)
|
||||
goto fail;
|
||||
h264->firstChromaFrameDone = TRUE;
|
||||
*ppAuxDstData = coded;
|
||||
*pAuxDstSize = codedSize;
|
||||
}
|
||||
|
||||
rc = 1;
|
||||
fail:
|
||||
if (rc < 0)
|
||||
{
|
||||
free_h264_metablock(meta);
|
||||
free_h264_metablock(auxMeta);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL avc444_ensure_buffer(H264_CONTEXT* h264, DWORD nDstHeight)
|
||||
{
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
const UINT32* piMainStride = h264->iStride;
|
||||
UINT32* piDstSize = h264->iYUV444Size;
|
||||
UINT32* piDstStride = h264->iYUV444Stride;
|
||||
BYTE** ppYUVDstData = h264->pYUV444Data;
|
||||
BYTE** ppOldYUVDstData = h264->pOldYUV444Data;
|
||||
|
||||
nDstHeight = MAX(h264->height, nDstHeight);
|
||||
const UINT32 pad = nDstHeight % 16;
|
||||
UINT32 padDstHeight = nDstHeight; /* Need alignment to 16x16 blocks */
|
||||
|
||||
if (pad != 0)
|
||||
padDstHeight += 16 - pad;
|
||||
|
||||
if ((piMainStride[0] != piDstStride[0]) ||
|
||||
(piDstSize[0] != 1ull * piMainStride[0] * padDstHeight))
|
||||
{
|
||||
for (UINT32 x = 0; x < 3; x++)
|
||||
{
|
||||
piDstStride[x] = piMainStride[0];
|
||||
piDstSize[x] = piDstStride[x] * padDstHeight;
|
||||
|
||||
if (piDstSize[x] == 0)
|
||||
return FALSE;
|
||||
|
||||
BYTE* tmp1 = winpr_aligned_recalloc(ppYUVDstData[x], piDstSize[x], 1, 16);
|
||||
if (!tmp1)
|
||||
return FALSE;
|
||||
ppYUVDstData[x] = tmp1;
|
||||
BYTE* tmp2 = winpr_aligned_recalloc(ppOldYUVDstData[x], piDstSize[x], 1, 16);
|
||||
if (!tmp2)
|
||||
return FALSE;
|
||||
ppOldYUVDstData[x] = tmp2;
|
||||
}
|
||||
|
||||
{
|
||||
BYTE* tmp = winpr_aligned_recalloc(h264->lumaData, piDstSize[0], 4, 16);
|
||||
if (!tmp)
|
||||
goto fail;
|
||||
h264->lumaData = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
for (UINT32 x = 0; x < 3; x++)
|
||||
{
|
||||
if (!ppOldYUVDstData[x] || !ppYUVDstData[x] || (piDstSize[x] == 0) || (piDstStride[x] == 0))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"YUV buffer not initialized! check your decoder settings");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!h264->lumaData)
|
||||
goto fail;
|
||||
|
||||
return TRUE;
|
||||
fail:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL avc444_process_rects(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep,
|
||||
WINPR_ATTR_UNUSED UINT32 nDstWidth, UINT32 nDstHeight,
|
||||
const RECTANGLE_16* rects, UINT32 nrRects, avc444_frame_type type)
|
||||
{
|
||||
const BYTE* pYUVData[3];
|
||||
BYTE* pYUVDstData[3];
|
||||
UINT32* piDstStride = h264->iYUV444Stride;
|
||||
BYTE** ppYUVDstData = h264->pYUV444Data;
|
||||
const UINT32* piStride = h264->iStride;
|
||||
|
||||
if (h264->subsystem->Decompress(h264, pSrcData, SrcSize) < 0)
|
||||
return FALSE;
|
||||
|
||||
pYUVData[0] = h264->pYUVData[0];
|
||||
pYUVData[1] = h264->pYUVData[1];
|
||||
pYUVData[2] = h264->pYUVData[2];
|
||||
if (!avc444_ensure_buffer(h264, nDstHeight))
|
||||
return FALSE;
|
||||
|
||||
pYUVDstData[0] = ppYUVDstData[0];
|
||||
pYUVDstData[1] = ppYUVDstData[1];
|
||||
pYUVDstData[2] = ppYUVDstData[2];
|
||||
return (yuv444_context_decode(h264->yuv, (BYTE)type, pYUVData, piStride, h264->height,
|
||||
pYUVDstData, piDstStride, DstFormat, pDstData, nDstStep, rects,
|
||||
nrRects));
|
||||
}
|
||||
|
||||
#if defined(AVC444_FRAME_STAT)
|
||||
static UINT64 op1 = 0;
|
||||
static double op1sum = 0;
|
||||
static UINT64 op2 = 0;
|
||||
static double op2sum = 0;
|
||||
static UINT64 op3 = 0;
|
||||
static double op3sum = 0;
|
||||
static double avg(UINT64* count, double old, double size)
|
||||
{
|
||||
double tmp = size + *count * old;
|
||||
(*count)++;
|
||||
tmp = tmp / *count;
|
||||
return tmp;
|
||||
}
|
||||
#endif
|
||||
|
||||
INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op, const RECTANGLE_16* regionRects,
|
||||
UINT32 numRegionRects, const BYTE* pSrcData, UINT32 SrcSize,
|
||||
const RECTANGLE_16* auxRegionRects, UINT32 numAuxRegionRect,
|
||||
const BYTE* pAuxSrcData, UINT32 AuxSrcSize, BYTE* pDstData, DWORD DstFormat,
|
||||
UINT32 nDstStep, UINT32 nDstWidth, UINT32 nDstHeight, UINT32 codecId)
|
||||
{
|
||||
INT32 status = -1;
|
||||
avc444_frame_type chroma =
|
||||
(codecId == RDPGFX_CODECID_AVC444) ? AVC444_CHROMAv1 : AVC444_CHROMAv2;
|
||||
|
||||
if (!h264 || !regionRects || !pSrcData || !pDstData || h264->Compressor)
|
||||
return -1001;
|
||||
|
||||
if (!areRectsValid(nDstWidth, nDstHeight, regionRects, numRegionRects))
|
||||
return -1013;
|
||||
if (!areRectsValid(nDstWidth, nDstHeight, auxRegionRects, numAuxRegionRect))
|
||||
return -1014;
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0: /* YUV420 in stream 1
|
||||
* Chroma420 in stream 2 */
|
||||
if (!avc444_process_rects(h264, pSrcData, SrcSize, pDstData, DstFormat, nDstStep,
|
||||
nDstWidth, nDstHeight, regionRects, numRegionRects,
|
||||
AVC444_LUMA))
|
||||
status = -1;
|
||||
else if (!avc444_process_rects(h264, pAuxSrcData, AuxSrcSize, pDstData, DstFormat,
|
||||
nDstStep, nDstWidth, nDstHeight, auxRegionRects,
|
||||
numAuxRegionRect, chroma))
|
||||
status = -1;
|
||||
else
|
||||
status = 0;
|
||||
|
||||
break;
|
||||
|
||||
case 2: /* Chroma420 in stream 1 */
|
||||
if (!avc444_process_rects(h264, pSrcData, SrcSize, pDstData, DstFormat, nDstStep,
|
||||
nDstWidth, nDstHeight, regionRects, numRegionRects, chroma))
|
||||
status = -1;
|
||||
else
|
||||
status = 0;
|
||||
|
||||
break;
|
||||
|
||||
case 1: /* YUV420 in stream 1 */
|
||||
if (!avc444_process_rects(h264, pSrcData, SrcSize, pDstData, DstFormat, nDstStep,
|
||||
nDstWidth, nDstHeight, regionRects, numRegionRects,
|
||||
AVC444_LUMA))
|
||||
status = -1;
|
||||
else
|
||||
status = 0;
|
||||
|
||||
break;
|
||||
|
||||
default: /* WTF? */
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(AVC444_FRAME_STAT)
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0:
|
||||
op1sum = avg(&op1, op1sum, SrcSize + AuxSrcSize);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
op2sum = avg(&op2, op2sum, SrcSize);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
op3sum = avg(&op3, op3sum, SrcSize);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
WLog_Print(h264->log, WLOG_INFO,
|
||||
"luma=%" PRIu64 " [avg=%lf] chroma=%" PRIu64 " [avg=%lf] combined=%" PRIu64
|
||||
" [avg=%lf]",
|
||||
op1, op1sum, op2, op2sum, op3, op3sum);
|
||||
#endif
|
||||
return status;
|
||||
}
|
||||
|
||||
#define MAX_SUBSYSTEMS 10
|
||||
static INIT_ONCE subsystems_once = INIT_ONCE_STATIC_INIT;
|
||||
static const H264_CONTEXT_SUBSYSTEM* subSystems[MAX_SUBSYSTEMS] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
static BOOL CALLBACK h264_register_subsystems(WINPR_ATTR_UNUSED PINIT_ONCE once,
|
||||
WINPR_ATTR_UNUSED PVOID param,
|
||||
WINPR_ATTR_UNUSED PVOID* context)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
#ifdef WITH_MEDIACODEC
|
||||
{
|
||||
subSystems[i] = &g_Subsystem_mediacodec;
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
#if defined(_WIN32) && defined(WITH_MEDIA_FOUNDATION)
|
||||
{
|
||||
subSystems[i] = &g_Subsystem_MF;
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_OPENH264
|
||||
{
|
||||
subSystems[i] = &g_Subsystem_OpenH264;
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_VIDEO_FFMPEG
|
||||
{
|
||||
subSystems[i] = &g_Subsystem_libavcodec;
|
||||
i++;
|
||||
}
|
||||
#endif
|
||||
return i > 0;
|
||||
}
|
||||
|
||||
static BOOL h264_context_init(H264_CONTEXT* h264)
|
||||
{
|
||||
if (!h264)
|
||||
return FALSE;
|
||||
|
||||
h264->subsystem = nullptr;
|
||||
if (!InitOnceExecuteOnce(&subsystems_once, h264_register_subsystems, nullptr, nullptr))
|
||||
return FALSE;
|
||||
|
||||
for (size_t i = 0; i < MAX_SUBSYSTEMS; i++)
|
||||
{
|
||||
const H264_CONTEXT_SUBSYSTEM* subsystem = subSystems[i];
|
||||
|
||||
if (!subsystem || !subsystem->Init)
|
||||
break;
|
||||
|
||||
if (subsystem->Init(h264))
|
||||
{
|
||||
h264->subsystem = subsystem;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL h264_context_reset(H264_CONTEXT* h264, UINT32 width, UINT32 height)
|
||||
{
|
||||
if (!h264)
|
||||
return FALSE;
|
||||
|
||||
h264->width = width;
|
||||
h264->height = height;
|
||||
|
||||
if (h264->subsystem && h264->subsystem->Uninit)
|
||||
h264->subsystem->Uninit(h264);
|
||||
if (!h264_context_init(h264))
|
||||
return FALSE;
|
||||
|
||||
return yuv_context_reset(h264->yuv, width, height);
|
||||
}
|
||||
|
||||
H264_CONTEXT* h264_context_new(BOOL Compressor)
|
||||
{
|
||||
H264_CONTEXT* h264 = (H264_CONTEXT*)calloc(1, sizeof(H264_CONTEXT));
|
||||
if (!h264)
|
||||
return nullptr;
|
||||
|
||||
h264->log = WLog_Get(TAG);
|
||||
|
||||
if (!h264->log)
|
||||
goto fail;
|
||||
|
||||
h264->Compressor = Compressor;
|
||||
if (Compressor)
|
||||
{
|
||||
/* Default compressor settings, may be changed by caller */
|
||||
h264->BitRate = 1000000;
|
||||
h264->FrameRate = 30;
|
||||
}
|
||||
|
||||
if (!h264_context_init(h264))
|
||||
goto fail;
|
||||
|
||||
h264->yuv = yuv_context_new(Compressor, 0);
|
||||
if (!h264->yuv)
|
||||
goto fail;
|
||||
|
||||
return h264;
|
||||
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
h264_context_free(h264);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void h264_context_free(H264_CONTEXT* h264)
|
||||
{
|
||||
if (h264)
|
||||
{
|
||||
if (h264->subsystem)
|
||||
{
|
||||
WINPR_ASSERT(h264->subsystem->Uninit);
|
||||
h264->subsystem->Uninit(h264);
|
||||
}
|
||||
|
||||
for (size_t x = 0; x < 3; x++)
|
||||
{
|
||||
if (h264->Compressor)
|
||||
{
|
||||
winpr_aligned_free(h264->pYUVData[x]);
|
||||
winpr_aligned_free(h264->pOldYUVData[x]);
|
||||
}
|
||||
winpr_aligned_free(h264->pYUV444Data[x]);
|
||||
winpr_aligned_free(h264->pOldYUV444Data[x]);
|
||||
}
|
||||
winpr_aligned_free(h264->lumaData);
|
||||
|
||||
yuv_context_free(h264->yuv);
|
||||
free(h264);
|
||||
}
|
||||
}
|
||||
|
||||
void free_h264_metablock(RDPGFX_H264_METABLOCK* meta)
|
||||
{
|
||||
RDPGFX_H264_METABLOCK m = WINPR_C_ARRAY_INIT;
|
||||
if (!meta)
|
||||
return;
|
||||
free(meta->quantQualityVals);
|
||||
free(meta->regionRects);
|
||||
*meta = m;
|
||||
}
|
||||
|
||||
BOOL h264_context_set_option(H264_CONTEXT* h264, H264_CONTEXT_OPTION option, UINT32 value)
|
||||
{
|
||||
WINPR_ASSERT(h264);
|
||||
switch (option)
|
||||
{
|
||||
case H264_CONTEXT_OPTION_BITRATE:
|
||||
h264->BitRate = value;
|
||||
return TRUE;
|
||||
case H264_CONTEXT_OPTION_FRAMERATE:
|
||||
h264->FrameRate = value;
|
||||
return TRUE;
|
||||
case H264_CONTEXT_OPTION_RATECONTROL:
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case H264_RATECONTROL_VBR:
|
||||
h264->RateControlMode = H264_RATECONTROL_VBR;
|
||||
return TRUE;
|
||||
case H264_RATECONTROL_CQP:
|
||||
h264->RateControlMode = H264_RATECONTROL_CQP;
|
||||
return TRUE;
|
||||
default:
|
||||
WLog_Print(h264->log, WLOG_WARN,
|
||||
"Unknown H264_CONTEXT_OPTION_RATECONTROL value [0x%08" PRIx32 "]",
|
||||
value);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
case H264_CONTEXT_OPTION_QP:
|
||||
h264->QP = value;
|
||||
return TRUE;
|
||||
case H264_CONTEXT_OPTION_USAGETYPE:
|
||||
h264->UsageType = value;
|
||||
return TRUE;
|
||||
case H264_CONTEXT_OPTION_HW_ACCEL:
|
||||
h264->hwAccel = (value);
|
||||
return TRUE;
|
||||
default:
|
||||
WLog_Print(h264->log, WLOG_WARN, "Unknown H264_CONTEXT_OPTION[0x%08" PRIx32 "]",
|
||||
option);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 h264_context_get_option(H264_CONTEXT* h264, H264_CONTEXT_OPTION option)
|
||||
{
|
||||
WINPR_ASSERT(h264);
|
||||
switch (option)
|
||||
{
|
||||
case H264_CONTEXT_OPTION_BITRATE:
|
||||
return h264->BitRate;
|
||||
case H264_CONTEXT_OPTION_FRAMERATE:
|
||||
return h264->FrameRate;
|
||||
case H264_CONTEXT_OPTION_RATECONTROL:
|
||||
return h264->RateControlMode;
|
||||
case H264_CONTEXT_OPTION_QP:
|
||||
return h264->QP;
|
||||
case H264_CONTEXT_OPTION_USAGETYPE:
|
||||
return h264->UsageType;
|
||||
case H264_CONTEXT_OPTION_HW_ACCEL:
|
||||
return h264->hwAccel;
|
||||
default:
|
||||
WLog_Print(h264->log, WLOG_WARN, "Unknown H264_CONTEXT_OPTION[0x%08" PRIx32 "]",
|
||||
option);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX Codec Library - Decode
|
||||
*
|
||||
* Copyright 2018 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2018 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 FREERDP_LIB_CODEC_H264_H
|
||||
#define FREERDP_LIB_CODEC_H264_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/config.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef BOOL (*pfnH264SubsystemInit)(H264_CONTEXT* h264);
|
||||
typedef void (*pfnH264SubsystemUninit)(H264_CONTEXT* h264);
|
||||
|
||||
typedef int (*pfnH264SubsystemDecompress)(H264_CONTEXT* WINPR_RESTRICT h264,
|
||||
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize);
|
||||
typedef int (*pfnH264SubsystemCompress)(H264_CONTEXT* WINPR_RESTRICT h264,
|
||||
const BYTE** WINPR_RESTRICT pSrcYuv,
|
||||
const UINT32* WINPR_RESTRICT pStride,
|
||||
BYTE** WINPR_RESTRICT ppDstData,
|
||||
UINT32* WINPR_RESTRICT pDstSize);
|
||||
|
||||
struct S_H264_CONTEXT_SUBSYSTEM
|
||||
{
|
||||
const char* name;
|
||||
WINPR_ATTR_NODISCARD pfnH264SubsystemInit Init;
|
||||
pfnH264SubsystemUninit Uninit;
|
||||
WINPR_ATTR_NODISCARD pfnH264SubsystemDecompress Decompress;
|
||||
WINPR_ATTR_NODISCARD pfnH264SubsystemCompress Compress;
|
||||
};
|
||||
|
||||
struct S_H264_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
|
||||
H264_RATECONTROL_MODE RateControlMode;
|
||||
UINT32 BitRate;
|
||||
UINT32 FrameRate;
|
||||
UINT32 QP;
|
||||
UINT32 UsageType;
|
||||
UINT32 hwAccel;
|
||||
UINT32 NumberOfThreads;
|
||||
|
||||
UINT32 iStride[3];
|
||||
BYTE* pOldYUVData[3];
|
||||
BYTE* pYUVData[3];
|
||||
|
||||
UINT32 iYUV444Size[3];
|
||||
UINT32 iYUV444Stride[3];
|
||||
BYTE* pOldYUV444Data[3];
|
||||
BYTE* pYUV444Data[3];
|
||||
|
||||
UINT32 numSystemData;
|
||||
void* pSystemData;
|
||||
const H264_CONTEXT_SUBSYSTEM* subsystem;
|
||||
YUV_CONTEXT* yuv;
|
||||
|
||||
BOOL encodingBuffer;
|
||||
BOOL firstLumaFrameDone;
|
||||
BOOL firstChromaFrameDone;
|
||||
|
||||
void* lumaData;
|
||||
wLog* log;
|
||||
};
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL avc420_ensure_buffer(H264_CONTEXT* h264, UINT32 stride, UINT32 width,
|
||||
UINT32 height);
|
||||
|
||||
#ifdef WITH_MEDIACODEC
|
||||
extern const H264_CONTEXT_SUBSYSTEM g_Subsystem_mediacodec;
|
||||
#endif
|
||||
#if defined(_WIN32) && defined(WITH_MEDIA_FOUNDATION)
|
||||
extern const H264_CONTEXT_SUBSYSTEM g_Subsystem_MF;
|
||||
#endif
|
||||
#ifdef WITH_OPENH264
|
||||
extern const H264_CONTEXT_SUBSYSTEM g_Subsystem_OpenH264;
|
||||
#endif
|
||||
#ifdef WITH_VIDEO_FFMPEG
|
||||
extern const H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_H264_H */
|
||||
+812
@@ -0,0 +1,812 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* H.264 Bitmap Compression
|
||||
*
|
||||
* Copyright 2015 Marc-André Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2014 Mike McDonald <Mike.McDonald@software.dell.com>
|
||||
* Copyright 2014 erbth <t.erbesdobler@team103.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 <freerdp/config.h>
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/opt.h>
|
||||
|
||||
#include "h264.h"
|
||||
|
||||
#ifdef WITH_VAAPI
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 9, 0)
|
||||
#include <libavutil/hwcontext.h>
|
||||
#else
|
||||
#pragma warning You have asked for VA - API decoding, \
|
||||
but your version of libavutil is too old !Disabling.
|
||||
#undef WITH_VAAPI
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Fallback support for older libavcodec versions */
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100)
|
||||
#define AV_CODEC_ID_H264 CODEC_ID_H264
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 34, 2)
|
||||
#define AV_CODEC_FLAG_LOOP_FILTER CODEC_FLAG_LOOP_FILTER
|
||||
#define AV_CODEC_CAP_TRUNCATED CODEC_CAP_TRUNCATED
|
||||
#define AV_CODEC_FLAG_TRUNCATED CODEC_FLAG_TRUNCATED
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_VERSION_MAJOR < 52
|
||||
#define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
|
||||
#endif
|
||||
|
||||
/* Ubuntu 14.04 ships without the functions provided by avutil,
|
||||
* so define error to string methods here. */
|
||||
#if !defined(av_err2str)
|
||||
static inline char* error_string(char* errbuf, size_t errbuf_size, int errnum)
|
||||
{
|
||||
av_strerror(errnum, errbuf, errbuf_size);
|
||||
return errbuf;
|
||||
}
|
||||
|
||||
#define av_err2str(errnum) error_string((char[64]){ 0 }, 64, errnum)
|
||||
#endif
|
||||
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
#define VAAPI_DEVICE "/dev/dri/renderD128"
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const AVCodec* codecDecoder;
|
||||
AVCodecContext* codecDecoderContext;
|
||||
const AVCodec* codecEncoder;
|
||||
AVCodecContext* codecEncoderContext;
|
||||
AVCodecParserContext* codecParser;
|
||||
AVFrame* videoFrame;
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
|
||||
AVPacket bufferpacket;
|
||||
#endif
|
||||
AVPacket* packet;
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
AVBufferRef* hwctx;
|
||||
AVFrame* hwVideoFrame;
|
||||
enum AVPixelFormat hw_pix_fmt;
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100)
|
||||
AVBufferRef* hw_frames_ctx;
|
||||
#endif
|
||||
#endif
|
||||
} H264_CONTEXT_LIBAVCODEC;
|
||||
|
||||
static void libavcodec_destroy_encoder_context(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
{
|
||||
H264_CONTEXT_LIBAVCODEC* sys = nullptr;
|
||||
|
||||
if (!h264 || !h264->subsystem)
|
||||
return;
|
||||
|
||||
sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
|
||||
if (sys->codecEncoderContext)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
|
||||
avcodec_free_context(&sys->codecEncoderContext);
|
||||
#else
|
||||
avcodec_close(sys->codecEncoderContext);
|
||||
av_free(sys->codecEncoderContext);
|
||||
#endif
|
||||
}
|
||||
|
||||
sys->codecEncoderContext = nullptr;
|
||||
}
|
||||
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
static int set_hw_frames_ctx(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
{
|
||||
H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
AVBufferRef* hw_frames_ref = nullptr;
|
||||
AVHWFramesContext* frames_ctx = nullptr;
|
||||
int err = 0;
|
||||
|
||||
if (!(hw_frames_ref = av_hwframe_ctx_alloc(sys->hwctx)))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to create VAAPI frame context");
|
||||
return -1;
|
||||
}
|
||||
frames_ctx = (AVHWFramesContext*)(hw_frames_ref->data);
|
||||
frames_ctx->format = AV_PIX_FMT_VAAPI;
|
||||
frames_ctx->sw_format = AV_PIX_FMT_NV12;
|
||||
frames_ctx->width = sys->codecEncoderContext->width;
|
||||
frames_ctx->height = sys->codecEncoderContext->height;
|
||||
frames_ctx->initial_pool_size = 20;
|
||||
if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to initialize VAAPI frame context."
|
||||
"Error code: %s",
|
||||
av_err2str(err));
|
||||
av_buffer_unref(&hw_frames_ref);
|
||||
return err;
|
||||
}
|
||||
sys->codecEncoderContext->hw_frames_ctx = av_buffer_ref(hw_frames_ref);
|
||||
if (!sys->codecEncoderContext->hw_frames_ctx)
|
||||
err = AVERROR(ENOMEM);
|
||||
|
||||
av_buffer_unref(&hw_frames_ref);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL libavcodec_create_encoder_context(H264_CONTEXT* WINPR_RESTRICT h264)
|
||||
{
|
||||
BOOL recreate = FALSE;
|
||||
H264_CONTEXT_LIBAVCODEC* sys = nullptr;
|
||||
|
||||
if (!h264 || !h264->subsystem)
|
||||
return FALSE;
|
||||
|
||||
if ((h264->width > INT_MAX) || (h264->height > INT_MAX))
|
||||
return FALSE;
|
||||
|
||||
sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
if (!sys || !sys->codecEncoder)
|
||||
return FALSE;
|
||||
|
||||
recreate = !sys->codecEncoderContext;
|
||||
|
||||
if (sys->codecEncoderContext)
|
||||
{
|
||||
if ((sys->codecEncoderContext->width != (int)h264->width) ||
|
||||
(sys->codecEncoderContext->height != (int)h264->height))
|
||||
recreate = TRUE;
|
||||
}
|
||||
|
||||
if (!recreate)
|
||||
return TRUE;
|
||||
|
||||
libavcodec_destroy_encoder_context(h264);
|
||||
|
||||
sys->codecEncoderContext = avcodec_alloc_context3(sys->codecEncoder);
|
||||
|
||||
if (!sys->codecEncoderContext)
|
||||
goto EXCEPTION;
|
||||
|
||||
switch (h264->RateControlMode)
|
||||
{
|
||||
case H264_RATECONTROL_VBR:
|
||||
sys->codecEncoderContext->bit_rate = h264->BitRate;
|
||||
break;
|
||||
|
||||
case H264_RATECONTROL_CQP:
|
||||
if (av_opt_set_int(sys->codecEncoderContext, "qp", h264->QP, AV_OPT_SEARCH_CHILDREN) <
|
||||
0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "av_opt_set_int failed");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sys->codecEncoderContext->width = (int)MIN(INT32_MAX, h264->width);
|
||||
sys->codecEncoderContext->height = (int)MIN(INT32_MAX, h264->height);
|
||||
sys->codecEncoderContext->delay = 0;
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 13, 100)
|
||||
sys->codecEncoderContext->framerate =
|
||||
(AVRational){ WINPR_ASSERTING_INT_CAST(int, h264->FrameRate), 1 };
|
||||
#endif
|
||||
sys->codecEncoderContext->time_base =
|
||||
(AVRational){ 1, WINPR_ASSERTING_INT_CAST(int, h264->FrameRate) };
|
||||
av_opt_set(sys->codecEncoderContext, "tune", "zerolatency", AV_OPT_SEARCH_CHILDREN);
|
||||
|
||||
sys->codecEncoderContext->flags |= AV_CODEC_FLAG_LOOP_FILTER;
|
||||
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
if (sys->hwctx)
|
||||
{
|
||||
av_opt_set(sys->codecEncoderContext, "preset", "veryslow", AV_OPT_SEARCH_CHILDREN);
|
||||
|
||||
sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_VAAPI;
|
||||
/* set hw_frames_ctx for encoder's AVCodecContext */
|
||||
if (set_hw_frames_ctx(h264) < 0)
|
||||
goto EXCEPTION;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
av_opt_set(sys->codecEncoderContext, "preset", "medium", AV_OPT_SEARCH_CHILDREN);
|
||||
sys->codecEncoderContext->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
}
|
||||
|
||||
if (avcodec_open2(sys->codecEncoderContext, sys->codecEncoder, nullptr) < 0)
|
||||
goto EXCEPTION;
|
||||
|
||||
return TRUE;
|
||||
EXCEPTION:
|
||||
libavcodec_destroy_encoder_context(h264);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int libavcodec_decompress(H264_CONTEXT* WINPR_RESTRICT h264,
|
||||
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize)
|
||||
{
|
||||
union
|
||||
{
|
||||
const BYTE* cpv;
|
||||
BYTE* pv;
|
||||
} cnv;
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
int gotFrame = 0;
|
||||
AVPacket* packet = nullptr;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
WINPR_ASSERT(pSrcData || (SrcSize == 0));
|
||||
|
||||
H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
BYTE** pYUVData = h264->pYUVData;
|
||||
UINT32* iStride = h264->iStride;
|
||||
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
|
||||
packet = &sys->bufferpacket;
|
||||
WINPR_ASSERT(packet);
|
||||
av_init_packet(packet);
|
||||
#else
|
||||
packet = av_packet_alloc();
|
||||
#endif
|
||||
if (!packet)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate AVPacket");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cnv.cpv = pSrcData;
|
||||
packet->data = cnv.pv;
|
||||
packet->size = (int)MIN(SrcSize, INT32_MAX);
|
||||
|
||||
WINPR_ASSERT(sys->codecDecoderContext);
|
||||
/* avcodec_decode_video2 is deprecated with libavcodec 57.48.101 */
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
|
||||
status = avcodec_send_packet(sys->codecDecoderContext, packet);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to decode video frame (status=%d)", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
sys->videoFrame->format = AV_PIX_FMT_YUV420P;
|
||||
|
||||
#ifdef WITH_VAAPI
|
||||
status = avcodec_receive_frame(sys->codecDecoderContext,
|
||||
sys->hwctx ? sys->hwVideoFrame : sys->videoFrame);
|
||||
#else
|
||||
status = avcodec_receive_frame(sys->codecDecoderContext, sys->videoFrame);
|
||||
#endif
|
||||
if (status == AVERROR(EAGAIN))
|
||||
{
|
||||
rc = 0;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
gotFrame = (status == 0);
|
||||
#else
|
||||
#ifdef WITH_VAAPI
|
||||
status =
|
||||
avcodec_decode_video2(sys->codecDecoderContext,
|
||||
sys->hwctx ? sys->hwVideoFrame : sys->videoFrame, &gotFrame, packet);
|
||||
#else
|
||||
status = avcodec_decode_video2(sys->codecDecoderContext, sys->videoFrame, &gotFrame, packet);
|
||||
#endif
|
||||
#endif
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to decode video frame (status=%d)", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#ifdef WITH_VAAPI
|
||||
|
||||
if (sys->hwctx)
|
||||
{
|
||||
if (sys->hwVideoFrame->format == sys->hw_pix_fmt)
|
||||
{
|
||||
sys->videoFrame->width = sys->hwVideoFrame->width;
|
||||
sys->videoFrame->height = sys->hwVideoFrame->height;
|
||||
status = av_hwframe_transfer_data(sys->videoFrame, sys->hwVideoFrame, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = av_frame_copy(sys->videoFrame, sys->hwVideoFrame);
|
||||
}
|
||||
}
|
||||
|
||||
gotFrame = (status == 0);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to transfer video frame (status=%d) (%s)", status,
|
||||
av_err2str(status));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (gotFrame)
|
||||
{
|
||||
WINPR_ASSERT(sys->videoFrame);
|
||||
|
||||
pYUVData[0] = sys->videoFrame->data[0];
|
||||
pYUVData[1] = sys->videoFrame->data[1];
|
||||
pYUVData[2] = sys->videoFrame->data[2];
|
||||
iStride[0] = (UINT32)MAX(0, sys->videoFrame->linesize[0]);
|
||||
iStride[1] = (UINT32)MAX(0, sys->videoFrame->linesize[1]);
|
||||
iStride[2] = (UINT32)MAX(0, sys->videoFrame->linesize[2]);
|
||||
|
||||
rc = 1;
|
||||
}
|
||||
else
|
||||
rc = -2;
|
||||
|
||||
fail:
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
|
||||
av_packet_unref(packet);
|
||||
#else
|
||||
av_packet_free(&packet);
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int libavcodec_compress(H264_CONTEXT* WINPR_RESTRICT h264,
|
||||
const BYTE** WINPR_RESTRICT pSrcYuv,
|
||||
const UINT32* WINPR_RESTRICT pStride,
|
||||
BYTE** WINPR_RESTRICT ppDstData, UINT32* WINPR_RESTRICT pDstSize)
|
||||
{
|
||||
union
|
||||
{
|
||||
const BYTE* cpv;
|
||||
uint8_t* pv;
|
||||
} cnv;
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
int gotFrame = 0;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
if (!libavcodec_create_encoder_context(h264))
|
||||
return -1;
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
|
||||
sys->packet = &sys->bufferpacket;
|
||||
av_packet_unref(sys->packet);
|
||||
av_init_packet(sys->packet);
|
||||
#else
|
||||
av_packet_free(&sys->packet);
|
||||
sys->packet = av_packet_alloc();
|
||||
#endif
|
||||
if (!sys->packet)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate AVPacket");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(sys->packet);
|
||||
sys->packet->data = nullptr;
|
||||
sys->packet->size = 0;
|
||||
|
||||
WINPR_ASSERT(sys->videoFrame);
|
||||
WINPR_ASSERT(sys->codecEncoderContext);
|
||||
sys->videoFrame->format = AV_PIX_FMT_YUV420P;
|
||||
sys->videoFrame->width = sys->codecEncoderContext->width;
|
||||
sys->videoFrame->height = sys->codecEncoderContext->height;
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 48, 100)
|
||||
sys->videoFrame->colorspace = AVCOL_SPC_BT709;
|
||||
#endif
|
||||
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 92, 100)
|
||||
sys->videoFrame->chroma_location = AVCHROMA_LOC_LEFT;
|
||||
#endif
|
||||
cnv.cpv = pSrcYuv[0];
|
||||
sys->videoFrame->data[0] = cnv.pv;
|
||||
|
||||
cnv.cpv = pSrcYuv[1];
|
||||
sys->videoFrame->data[1] = cnv.pv;
|
||||
|
||||
cnv.cpv = pSrcYuv[2];
|
||||
sys->videoFrame->data[2] = cnv.pv;
|
||||
|
||||
sys->videoFrame->linesize[0] = (int)pStride[0];
|
||||
sys->videoFrame->linesize[1] = (int)pStride[1];
|
||||
sys->videoFrame->linesize[2] = (int)pStride[2];
|
||||
sys->videoFrame->pts++;
|
||||
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
if (sys->hwctx)
|
||||
{
|
||||
av_frame_unref(sys->hwVideoFrame);
|
||||
if ((status = av_hwframe_get_buffer(sys->codecEncoderContext->hw_frames_ctx,
|
||||
sys->hwVideoFrame, 0)) < 0 ||
|
||||
!sys->hwVideoFrame->hw_frames_ctx)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "av_hwframe_get_buffer failed (%s [%d])",
|
||||
av_err2str(status), status);
|
||||
goto fail;
|
||||
}
|
||||
sys->videoFrame->format = AV_PIX_FMT_NV12;
|
||||
if ((status = av_hwframe_transfer_data(sys->hwVideoFrame, sys->videoFrame, 0)) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "av_hwframe_transfer_data failed (%s [%d])",
|
||||
av_err2str(status), status);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* avcodec_encode_video2 is deprecated with libavcodec 57.48.101 */
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
status = avcodec_send_frame(sys->codecEncoderContext,
|
||||
sys->hwctx ? sys->hwVideoFrame : sys->videoFrame);
|
||||
#else
|
||||
status = avcodec_send_frame(sys->codecEncoderContext, sys->videoFrame);
|
||||
#endif
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])",
|
||||
av_err2str(status), status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
status = avcodec_receive_packet(sys->codecEncoderContext, sys->packet);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])",
|
||||
av_err2str(status), status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
gotFrame = (status == 0);
|
||||
#elif LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 59, 100)
|
||||
|
||||
do
|
||||
{
|
||||
status = avcodec_encode_video2(sys->codecEncoderContext, sys->packet, sys->videoFrame,
|
||||
&gotFrame);
|
||||
} while ((status >= 0) && (gotFrame == 0));
|
||||
|
||||
#else
|
||||
sys->packet->size =
|
||||
avpicture_get_size(sys->codecDecoderContext->pix_fmt, sys->codecDecoderContext->width,
|
||||
sys->codecDecoderContext->height);
|
||||
sys->packet->data = av_malloc(sys->packet->size);
|
||||
|
||||
if (!sys->packet->data)
|
||||
status = -1;
|
||||
else
|
||||
{
|
||||
status = avcodec_encode_video(sys->codecDecoderContext, sys->packet->data,
|
||||
sys->packet->size, sys->videoFrame);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to encode video frame (%s [%d])",
|
||||
av_err2str(status), status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(sys->packet);
|
||||
*ppDstData = sys->packet->data;
|
||||
*pDstSize = (UINT32)MAX(0, sys->packet->size);
|
||||
|
||||
if (!gotFrame)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Did not get frame! (%s [%d])", av_err2str(status),
|
||||
status);
|
||||
rc = -2;
|
||||
}
|
||||
else
|
||||
rc = 1;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void libavcodec_uninit(H264_CONTEXT* h264)
|
||||
{
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
|
||||
if (!sys)
|
||||
return;
|
||||
|
||||
if (sys->packet)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 133, 100)
|
||||
av_packet_unref(sys->packet);
|
||||
#else
|
||||
av_packet_free(&sys->packet);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sys->videoFrame)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
|
||||
av_frame_free(&sys->videoFrame);
|
||||
#else
|
||||
av_free(sys->videoFrame);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
if (sys->hwVideoFrame)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
|
||||
av_frame_free(&sys->hwVideoFrame);
|
||||
#else
|
||||
av_free(sys->hwVideoFrame);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sys->hwctx)
|
||||
av_buffer_unref(&sys->hwctx);
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100)
|
||||
|
||||
if (sys->hw_frames_ctx)
|
||||
av_buffer_unref(&sys->hw_frames_ctx);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
if (sys->codecParser)
|
||||
av_parser_close(sys->codecParser);
|
||||
|
||||
if (sys->codecDecoderContext)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 69, 100)
|
||||
avcodec_free_context(&sys->codecDecoderContext);
|
||||
#else
|
||||
avcodec_close(sys->codecDecoderContext);
|
||||
av_free(sys->codecDecoderContext);
|
||||
#endif
|
||||
}
|
||||
|
||||
libavcodec_destroy_encoder_context(h264);
|
||||
free(sys);
|
||||
h264->pSystemData = nullptr;
|
||||
}
|
||||
|
||||
#ifdef WITH_VAAPI
|
||||
static enum AVPixelFormat libavcodec_get_format(struct AVCodecContext* ctx,
|
||||
const enum AVPixelFormat* fmts)
|
||||
{
|
||||
WINPR_ASSERT(ctx);
|
||||
|
||||
H264_CONTEXT* h264 = (H264_CONTEXT*)ctx->opaque;
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*)h264->pSystemData;
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
for (const enum AVPixelFormat* p = fmts; *p != AV_PIX_FMT_NONE; p++)
|
||||
{
|
||||
if (*p == sys->hw_pix_fmt)
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 80, 100)
|
||||
sys->hw_frames_ctx = av_hwframe_ctx_alloc(sys->hwctx);
|
||||
|
||||
if (!sys->hw_frames_ctx)
|
||||
{
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
sys->codecDecoderContext->pix_fmt = *p;
|
||||
AVHWFramesContext* frames = (AVHWFramesContext*)sys->hw_frames_ctx->data;
|
||||
frames->format = *p;
|
||||
frames->height = sys->codecDecoderContext->coded_height;
|
||||
frames->width = sys->codecDecoderContext->coded_width;
|
||||
frames->sw_format =
|
||||
(sys->codecDecoderContext->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? AV_PIX_FMT_P010
|
||||
: AV_PIX_FMT_NV12);
|
||||
frames->initial_pool_size = 20;
|
||||
|
||||
if (sys->codecDecoderContext->active_thread_type & FF_THREAD_FRAME)
|
||||
frames->initial_pool_size += sys->codecDecoderContext->thread_count;
|
||||
|
||||
int err = av_hwframe_ctx_init(sys->hw_frames_ctx);
|
||||
|
||||
if (err < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Could not init hwframes context: %s",
|
||||
av_err2str(err));
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
sys->codecDecoderContext->hw_frames_ctx = av_buffer_ref(sys->hw_frames_ctx);
|
||||
#endif
|
||||
return *p;
|
||||
}
|
||||
}
|
||||
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL libavcodec_init(H264_CONTEXT* h264)
|
||||
{
|
||||
H264_CONTEXT_LIBAVCODEC* sys = nullptr;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
sys = (H264_CONTEXT_LIBAVCODEC*)calloc(1, sizeof(H264_CONTEXT_LIBAVCODEC));
|
||||
|
||||
if (!sys)
|
||||
{
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
h264->pSystemData = (void*)sys;
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 10, 100)
|
||||
avcodec_register_all();
|
||||
#endif
|
||||
|
||||
if (!h264->Compressor)
|
||||
{
|
||||
sys->codecDecoder = avcodec_find_decoder(AV_CODEC_ID_H264);
|
||||
|
||||
if (!sys->codecDecoder)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to find libav H.264 codec");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
sys->codecDecoderContext = avcodec_alloc_context3(sys->codecDecoder);
|
||||
|
||||
if (!sys->codecDecoderContext)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav codec context");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100)
|
||||
if (sys->codecDecoder->capabilities & AV_CODEC_CAP_TRUNCATED)
|
||||
{
|
||||
sys->codecDecoderContext->flags |= AV_CODEC_FLAG_TRUNCATED;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_VAAPI
|
||||
|
||||
if (!sys->hwctx)
|
||||
{
|
||||
int ret = av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI, VAAPI_DEVICE,
|
||||
nullptr, 0);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Could not initialize hardware decoder, falling back to software: %s",
|
||||
av_err2str(ret));
|
||||
sys->hwctx = nullptr;
|
||||
goto fail_hwdevice_create;
|
||||
}
|
||||
}
|
||||
WLog_Print(h264->log, WLOG_INFO, "Using VAAPI for accelerated H264 decoding");
|
||||
|
||||
sys->codecDecoderContext->get_format = libavcodec_get_format;
|
||||
sys->hw_pix_fmt = AV_PIX_FMT_VAAPI;
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 80, 100)
|
||||
sys->codecDecoderContext->hw_device_ctx = av_buffer_ref(sys->hwctx);
|
||||
#endif
|
||||
sys->codecDecoderContext->opaque = (void*)h264;
|
||||
fail_hwdevice_create:
|
||||
#endif
|
||||
|
||||
if (avcodec_open2(sys->codecDecoderContext, sys->codecDecoder, nullptr) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to open libav codec");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
sys->codecParser = av_parser_init(AV_CODEC_ID_H264);
|
||||
|
||||
if (!sys->codecParser)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize libav parser");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef WITH_VAAPI_H264_ENCODING
|
||||
if (h264->hwAccel) /* user requested hw accel */
|
||||
{
|
||||
sys->codecEncoder = avcodec_find_encoder_by_name("h264_vaapi");
|
||||
if (!sys->codecEncoder)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "H264 VAAPI encoder not found");
|
||||
}
|
||||
else if (av_hwdevice_ctx_create(&sys->hwctx, AV_HWDEVICE_TYPE_VAAPI, VAAPI_DEVICE,
|
||||
nullptr, 0) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "av_hwdevice_ctx_create failed");
|
||||
sys->codecEncoder = nullptr;
|
||||
sys->hwctx = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_INFO, "Using VAAPI for accelerated H264 encoding");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!sys->codecEncoder)
|
||||
{
|
||||
sys->codecEncoder = avcodec_find_encoder(AV_CODEC_ID_H264);
|
||||
h264->hwAccel = FALSE; /* not supported */
|
||||
}
|
||||
|
||||
if (!sys->codecEncoder)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize H264 encoder");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 18, 102)
|
||||
sys->videoFrame = av_frame_alloc();
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
sys->hwVideoFrame = av_frame_alloc();
|
||||
#endif
|
||||
#else
|
||||
sys->videoFrame = avcodec_alloc_frame();
|
||||
#endif
|
||||
|
||||
if (!sys->videoFrame)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav frame");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
#if defined(WITH_VAAPI) || defined(WITH_VAAPI_H264_ENCODING)
|
||||
if (!sys->hwVideoFrame)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to allocate libav hw frame");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
#endif
|
||||
sys->videoFrame->pts = 0;
|
||||
return TRUE;
|
||||
EXCEPTION:
|
||||
libavcodec_uninit(h264);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec = { "libavcodec", libavcodec_init,
|
||||
libavcodec_uninit, libavcodec_decompress,
|
||||
libavcodec_compress };
|
||||
@@ -0,0 +1,527 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* H.264 Bitmap Compression
|
||||
*
|
||||
* Copyright 2022 Ely Ronnen <elyronnen@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 <winpr/wlog.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/library.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
|
||||
#include <media/NdkMediaCodec.h>
|
||||
#include <media/NdkMediaFormat.h>
|
||||
|
||||
#include "h264.h"
|
||||
|
||||
static const char* CODEC_NAME = "video/avc";
|
||||
|
||||
static const int COLOR_FormatYUV420Planar = 19;
|
||||
static const int COLOR_FormatYUV420Flexible = 0x7f420888;
|
||||
|
||||
/* https://developer.android.com/reference/android/media/MediaCodec#qualityFloor */
|
||||
static const int MEDIACODEC_MINIMUM_WIDTH = 320;
|
||||
static const int MEDIACODEC_MINIMUM_HEIGHT = 240;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AMediaCodec* decoder;
|
||||
AMediaFormat* inputFormat;
|
||||
AMediaFormat* outputFormat;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t outputWidth;
|
||||
int32_t outputHeight;
|
||||
ssize_t currentOutputBufferIndex;
|
||||
} H264_CONTEXT_MEDIACODEC;
|
||||
|
||||
static AMediaFormat* mediacodec_format_new(wLog* log, int width, int height)
|
||||
{
|
||||
const char* media_format;
|
||||
AMediaFormat* format = AMediaFormat_new();
|
||||
if (format == nullptr)
|
||||
{
|
||||
WLog_Print(log, WLOG_ERROR, "AMediaFormat_new failed");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, CODEC_NAME);
|
||||
AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, width);
|
||||
AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height);
|
||||
AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, COLOR_FormatYUV420Planar);
|
||||
|
||||
media_format = AMediaFormat_toString(format);
|
||||
if (media_format == nullptr)
|
||||
{
|
||||
WLog_Print(log, WLOG_ERROR, "AMediaFormat_toString failed");
|
||||
AMediaFormat_delete(format);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WLog_Print(log, WLOG_DEBUG, "MediaCodec configuring with desired output format [%s]",
|
||||
media_format);
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static void set_mediacodec_format(H264_CONTEXT* h264, AMediaFormat** formatVariable,
|
||||
AMediaFormat* newFormat)
|
||||
{
|
||||
media_status_t status = AMEDIA_OK;
|
||||
H264_CONTEXT_MEDIACODEC* sys;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
WINPR_ASSERT(formatVariable);
|
||||
|
||||
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
if (*formatVariable == newFormat)
|
||||
return;
|
||||
|
||||
if (*formatVariable != nullptr)
|
||||
{
|
||||
status = AMediaFormat_delete(*formatVariable);
|
||||
if (status != AMEDIA_OK)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaFormat_delete %d", status);
|
||||
}
|
||||
}
|
||||
|
||||
*formatVariable = newFormat;
|
||||
}
|
||||
|
||||
static int update_mediacodec_inputformat(H264_CONTEXT* h264)
|
||||
{
|
||||
H264_CONTEXT_MEDIACODEC* sys;
|
||||
AMediaFormat* inputFormat;
|
||||
const char* mediaFormatName;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
#if __ANDROID__ >= 21
|
||||
inputFormat = AMediaCodec_getInputFormat(sys->decoder);
|
||||
if (inputFormat == nullptr)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_getInputFormat failed");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
inputFormat = sys->inputFormat;
|
||||
#endif
|
||||
set_mediacodec_format(h264, &sys->inputFormat, inputFormat);
|
||||
|
||||
mediaFormatName = AMediaFormat_toString(sys->inputFormat);
|
||||
if (mediaFormatName == nullptr)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaFormat_toString failed");
|
||||
return -1;
|
||||
}
|
||||
WLog_Print(h264->log, WLOG_DEBUG, "Using MediaCodec with input MediaFormat [%s]",
|
||||
mediaFormatName);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int update_mediacodec_outputformat(H264_CONTEXT* h264)
|
||||
{
|
||||
H264_CONTEXT_MEDIACODEC* sys;
|
||||
AMediaFormat* outputFormat;
|
||||
const char* mediaFormatName;
|
||||
int32_t outputWidth, outputHeight;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
outputFormat = AMediaCodec_getOutputFormat(sys->decoder);
|
||||
if (outputFormat == nullptr)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_getOutputFormat failed");
|
||||
return -1;
|
||||
}
|
||||
set_mediacodec_format(h264, &sys->outputFormat, outputFormat);
|
||||
|
||||
mediaFormatName = AMediaFormat_toString(sys->outputFormat);
|
||||
if (mediaFormatName == nullptr)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaFormat_toString failed");
|
||||
return -1;
|
||||
}
|
||||
WLog_Print(h264->log, WLOG_DEBUG, "Using MediaCodec with output MediaFormat [%s]",
|
||||
mediaFormatName);
|
||||
|
||||
if (!AMediaFormat_getInt32(sys->outputFormat, AMEDIAFORMAT_KEY_WIDTH, &outputWidth))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "fnAMediaFormat_getInt32 failed getting width");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!AMediaFormat_getInt32(sys->outputFormat, AMEDIAFORMAT_KEY_HEIGHT, &outputHeight))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "fnAMediaFormat_getInt32 failed getting height");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sys->outputWidth = outputWidth;
|
||||
sys->outputHeight = outputHeight;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void release_current_outputbuffer(H264_CONTEXT* h264)
|
||||
{
|
||||
media_status_t status = AMEDIA_OK;
|
||||
H264_CONTEXT_MEDIACODEC* sys;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
if (sys->currentOutputBufferIndex < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
status = AMediaCodec_releaseOutputBuffer(sys->decoder, sys->currentOutputBufferIndex, FALSE);
|
||||
if (status != AMEDIA_OK)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaCodec_releaseOutputBuffer %d", status);
|
||||
}
|
||||
|
||||
sys->currentOutputBufferIndex = -1;
|
||||
}
|
||||
|
||||
static int mediacodec_compress(H264_CONTEXT* h264, const BYTE** pSrcYuv, const UINT32* pStride,
|
||||
BYTE** ppDstData, UINT32* pDstSize)
|
||||
{
|
||||
WINPR_ASSERT(h264);
|
||||
WINPR_ASSERT(pSrcYuv);
|
||||
WINPR_ASSERT(pStride);
|
||||
WINPR_ASSERT(ppDstData);
|
||||
WINPR_ASSERT(pDstSize);
|
||||
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MediaCodec is not supported as an encoder");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mediacodec_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize)
|
||||
{
|
||||
ssize_t inputBufferId = -1;
|
||||
size_t inputBufferSize, outputBufferSize;
|
||||
uint8_t* inputBuffer;
|
||||
media_status_t status;
|
||||
BYTE** pYUVData;
|
||||
UINT32* iStride;
|
||||
H264_CONTEXT_MEDIACODEC* sys;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
WINPR_ASSERT(pSrcData);
|
||||
|
||||
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
pYUVData = h264->pYUVData;
|
||||
WINPR_ASSERT(pYUVData);
|
||||
|
||||
iStride = h264->iStride;
|
||||
WINPR_ASSERT(iStride);
|
||||
|
||||
release_current_outputbuffer(h264);
|
||||
|
||||
if (sys->width != h264->width || sys->height != h264->height)
|
||||
{
|
||||
sys->width = h264->width;
|
||||
sys->height = h264->height;
|
||||
|
||||
if (sys->width < MEDIACODEC_MINIMUM_WIDTH || sys->height < MEDIACODEC_MINIMUM_HEIGHT)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"MediaCodec got width or height smaller than minimum [%d,%d]", sys->width,
|
||||
sys->height);
|
||||
return -1;
|
||||
}
|
||||
|
||||
WLog_Print(h264->log, WLOG_DEBUG, "MediaCodec setting new input width and height [%d,%d]",
|
||||
sys->width, sys->height);
|
||||
|
||||
#if __ANDROID__ >= 26
|
||||
AMediaFormat_setInt32(sys->inputFormat, AMEDIAFORMAT_KEY_WIDTH, sys->width);
|
||||
AMediaFormat_setInt32(sys->inputFormat, AMEDIAFORMAT_KEY_HEIGHT, sys->height);
|
||||
status = AMediaCodec_setParameters(sys->decoder, sys->inputFormat);
|
||||
if (status != AMEDIA_OK)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_setParameters failed: %d", status);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
set_mediacodec_format(h264, &sys->inputFormat,
|
||||
mediacodec_format_new(h264->log, sys->width, sys->height));
|
||||
#endif
|
||||
|
||||
// The codec can change output width and height
|
||||
if (update_mediacodec_outputformat(h264) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MediaCodec failed updating input format");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
UINT32 inputBufferCurrnetOffset = 0;
|
||||
while (inputBufferCurrnetOffset < SrcSize)
|
||||
{
|
||||
UINT32 numberOfBytesToCopy = SrcSize - inputBufferCurrnetOffset;
|
||||
inputBufferId = AMediaCodec_dequeueInputBuffer(sys->decoder, -1);
|
||||
if (inputBufferId < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_dequeueInputBuffer failed [%d]",
|
||||
inputBufferId);
|
||||
// TODO: sleep?
|
||||
continue;
|
||||
}
|
||||
|
||||
inputBuffer = AMediaCodec_getInputBuffer(sys->decoder, inputBufferId, &inputBufferSize);
|
||||
if (inputBuffer == nullptr)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_getInputBuffer failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (numberOfBytesToCopy > inputBufferSize)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_WARN,
|
||||
"MediaCodec inputBufferSize: got [%d] but wanted [%d]", inputBufferSize,
|
||||
numberOfBytesToCopy);
|
||||
numberOfBytesToCopy = inputBufferSize;
|
||||
}
|
||||
|
||||
memcpy(inputBuffer, pSrcData + inputBufferCurrnetOffset, numberOfBytesToCopy);
|
||||
inputBufferCurrnetOffset += numberOfBytesToCopy;
|
||||
|
||||
status = AMediaCodec_queueInputBuffer(sys->decoder, inputBufferId, 0,
|
||||
numberOfBytesToCopy, 0, 0);
|
||||
if (status != AMEDIA_OK)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaCodec_queueInputBuffer %d", status);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
AMediaCodecBufferInfo bufferInfo;
|
||||
ssize_t outputBufferId = AMediaCodec_dequeueOutputBuffer(sys->decoder, &bufferInfo, -1);
|
||||
if (outputBufferId >= 0)
|
||||
{
|
||||
sys->currentOutputBufferIndex = outputBufferId;
|
||||
|
||||
uint8_t* outputBuffer;
|
||||
outputBuffer =
|
||||
AMediaCodec_getOutputBuffer(sys->decoder, outputBufferId, &outputBufferSize);
|
||||
sys->currentOutputBufferIndex = outputBufferId;
|
||||
|
||||
if (outputBufferSize !=
|
||||
(sys->outputWidth * sys->outputHeight +
|
||||
((sys->outputWidth + 1) / 2) * ((sys->outputHeight + 1) / 2) * 2))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Error MediaCodec unexpected output buffer size %d",
|
||||
outputBufferSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: work with AImageReader and get AImage object instead of
|
||||
// COLOR_FormatYUV420Planar buffer.
|
||||
iStride[0] = sys->outputWidth;
|
||||
iStride[1] = (sys->outputWidth + 1) / 2;
|
||||
iStride[2] = (sys->outputWidth + 1) / 2;
|
||||
pYUVData[0] = outputBuffer;
|
||||
pYUVData[1] = outputBuffer + iStride[0] * sys->outputHeight;
|
||||
pYUVData[2] = outputBuffer + iStride[0] * sys->outputHeight +
|
||||
iStride[1] * ((sys->outputHeight + 1) / 2);
|
||||
break;
|
||||
}
|
||||
else if (outputBufferId == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED)
|
||||
{
|
||||
if (update_mediacodec_outputformat(h264) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"MediaCodec failed updating output format in decompress");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (outputBufferId == AMEDIACODEC_INFO_TRY_AGAIN_LATER)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_WARN,
|
||||
"AMediaCodec_dequeueOutputBuffer need to try again later");
|
||||
// TODO: sleep?
|
||||
}
|
||||
else if (outputBufferId == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_WARN,
|
||||
"AMediaCodec_dequeueOutputBuffer returned deprecated value "
|
||||
"AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED, ignoring");
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"AMediaCodec_dequeueOutputBuffer returned unknown value [%d]",
|
||||
outputBufferId);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void mediacodec_uninit(H264_CONTEXT* h264)
|
||||
{
|
||||
media_status_t status = AMEDIA_OK;
|
||||
H264_CONTEXT_MEDIACODEC* sys;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
sys = (H264_CONTEXT_MEDIACODEC*)h264->pSystemData;
|
||||
|
||||
WLog_Print(h264->log, WLOG_DEBUG, "Uninitializing MediaCodec");
|
||||
|
||||
if (!sys)
|
||||
return;
|
||||
|
||||
if (sys->decoder != nullptr)
|
||||
{
|
||||
release_current_outputbuffer(h264);
|
||||
status = AMediaCodec_stop(sys->decoder);
|
||||
if (status != AMEDIA_OK)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaCodec_stop %d", status);
|
||||
}
|
||||
|
||||
status = AMediaCodec_delete(sys->decoder);
|
||||
if (status != AMEDIA_OK)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Error AMediaCodec_delete %d", status);
|
||||
}
|
||||
|
||||
sys->decoder = nullptr;
|
||||
}
|
||||
|
||||
set_mediacodec_format(h264, &sys->inputFormat, nullptr);
|
||||
set_mediacodec_format(h264, &sys->outputFormat, nullptr);
|
||||
|
||||
free(sys);
|
||||
h264->pSystemData = nullptr;
|
||||
}
|
||||
|
||||
static BOOL mediacodec_init(H264_CONTEXT* h264)
|
||||
{
|
||||
H264_CONTEXT_MEDIACODEC* sys;
|
||||
media_status_t status;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
if (h264->Compressor)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MediaCodec is not supported as an encoder");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
WLog_Print(h264->log, WLOG_DEBUG, "Initializing MediaCodec");
|
||||
|
||||
sys = (H264_CONTEXT_MEDIACODEC*)calloc(1, sizeof(H264_CONTEXT_MEDIACODEC));
|
||||
|
||||
if (!sys)
|
||||
{
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
h264->pSystemData = (void*)sys;
|
||||
|
||||
sys->currentOutputBufferIndex = -1;
|
||||
|
||||
// updated when we're given the height and width for the first time
|
||||
sys->width = sys->outputWidth = MEDIACODEC_MINIMUM_WIDTH;
|
||||
sys->height = sys->outputHeight = MEDIACODEC_MINIMUM_HEIGHT;
|
||||
sys->decoder = AMediaCodec_createDecoderByType(CODEC_NAME);
|
||||
if (sys->decoder == nullptr)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_createCodecByName failed");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
#if __ANDROID_API__ >= 28
|
||||
char* codec_name;
|
||||
status = AMediaCodec_getName(sys->decoder, &codec_name);
|
||||
if (status != AMEDIA_OK)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_getName failed: %d", status);
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
WLog_Print(h264->log, WLOG_DEBUG, "MediaCodec using %s codec [%s]", CODEC_NAME, codec_name);
|
||||
AMediaCodec_releaseName(sys->decoder, codec_name);
|
||||
#endif
|
||||
|
||||
set_mediacodec_format(h264, &sys->inputFormat,
|
||||
mediacodec_format_new(h264->log, sys->width, sys->height));
|
||||
|
||||
status = AMediaCodec_configure(sys->decoder, sys->inputFormat, nullptr, nullptr, 0);
|
||||
if (status != AMEDIA_OK)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_configure failed: %d", status);
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
if (update_mediacodec_inputformat(h264) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MediaCodec failed updating input format");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
if (update_mediacodec_outputformat(h264) < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MediaCodec failed updating output format");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
WLog_Print(h264->log, WLOG_DEBUG, "Starting MediaCodec");
|
||||
status = AMediaCodec_start(sys->decoder);
|
||||
if (status != AMEDIA_OK)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AMediaCodec_start failed %d", status);
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
EXCEPTION:
|
||||
mediacodec_uninit(h264);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const H264_CONTEXT_SUBSYSTEM g_Subsystem_mediacodec = { "MediaCodec", mediacodec_init,
|
||||
mediacodec_uninit, mediacodec_decompress,
|
||||
mediacodec_compress };
|
||||
+597
@@ -0,0 +1,597 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* H.264 Bitmap Compression
|
||||
*
|
||||
* Copyright 2014 Mike McDonald <Mike.McDonald@software.dell.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 <winpr/winpr.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
|
||||
#include <ks.h>
|
||||
#include <codecapi.h>
|
||||
|
||||
#include <mfapi.h>
|
||||
#include <mferror.h>
|
||||
#include <wmcodecdsp.h>
|
||||
#include <mftransform.h>
|
||||
|
||||
#include "h264.h"
|
||||
|
||||
#define TAG FREERDP_TAG("codec")
|
||||
|
||||
static const GUID sCLSID_CMSH264DecoderMFT = {
|
||||
0x62CE7E72, 0x4C71, 0x4d20, { 0xB1, 0x5D, 0x45, 0x28, 0x31, 0xA8, 0x7D, 0x9D }
|
||||
};
|
||||
static const GUID sIID_IMFTransform = {
|
||||
0xbf94c121, 0x5b05, 0x4e6f, { 0x80, 0x00, 0xba, 0x59, 0x89, 0x61, 0x41, 0x4d }
|
||||
};
|
||||
static const GUID sMF_MT_MAJOR_TYPE = {
|
||||
0x48eba18e, 0xf8c9, 0x4687, { 0xbf, 0x11, 0x0a, 0x74, 0xc9, 0xf9, 0x6a, 0x8f }
|
||||
};
|
||||
static const GUID sMF_MT_FRAME_SIZE = {
|
||||
0x1652c33d, 0xd6b2, 0x4012, { 0xb8, 0x34, 0x72, 0x03, 0x08, 0x49, 0xa3, 0x7d }
|
||||
};
|
||||
static const GUID sMF_MT_DEFAULT_STRIDE = {
|
||||
0x644b4e48, 0x1e02, 0x4516, { 0xb0, 0xeb, 0xc0, 0x1c, 0xa9, 0xd4, 0x9a, 0xc6 }
|
||||
};
|
||||
static const GUID sMF_MT_SUBTYPE = {
|
||||
0xf7e34c9a, 0x42e8, 0x4714, { 0xb7, 0x4b, 0xcb, 0x29, 0xd7, 0x2c, 0x35, 0xe5 }
|
||||
};
|
||||
static const GUID sMFMediaType_Video = {
|
||||
0x73646976, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }
|
||||
};
|
||||
static const GUID sMFVideoFormat_H264 = {
|
||||
0x34363248, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
|
||||
};
|
||||
static const GUID sMFVideoFormat_IYUV = {
|
||||
0x56555949, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
|
||||
};
|
||||
static const GUID sIID_ICodecAPI = {
|
||||
0x901db4c7, 0x31ce, 0x41a2, { 0x85, 0xdc, 0x8f, 0xa0, 0xbf, 0x41, 0xb8, 0xda }
|
||||
};
|
||||
static const GUID sCODECAPI_AVLowLatencyMode = {
|
||||
0x9c27891a, 0xed7a, 0x40e1, { 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee }
|
||||
};
|
||||
|
||||
typedef HRESULT(__stdcall* pfnMFStartup)(ULONG Version, DWORD dwFlags);
|
||||
typedef HRESULT(__stdcall* pfnMFShutdown)(void);
|
||||
typedef HRESULT(__stdcall* pfnMFCreateSample)(IMFSample** ppIMFSample);
|
||||
typedef HRESULT(__stdcall* pfnMFCreateMemoryBuffer)(DWORD cbMaxLength, IMFMediaBuffer** ppBuffer);
|
||||
typedef HRESULT(__stdcall* pfnMFCreateMediaType)(IMFMediaType** ppMFType);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ICodecAPI* codecApi;
|
||||
IMFTransform* transform;
|
||||
IMFMediaType* inputType;
|
||||
IMFMediaType* outputType;
|
||||
IMFSample* sample;
|
||||
UINT32 frameWidth;
|
||||
UINT32 frameHeight;
|
||||
IMFSample* outputSample;
|
||||
IMFMediaBuffer* outputBuffer;
|
||||
HMODULE mfplat;
|
||||
pfnMFStartup MFStartup;
|
||||
pfnMFShutdown MFShutdown;
|
||||
pfnMFCreateSample MFCreateSample;
|
||||
pfnMFCreateMemoryBuffer MFCreateMemoryBuffer;
|
||||
pfnMFCreateMediaType MFCreateMediaType;
|
||||
} H264_CONTEXT_MF;
|
||||
|
||||
static HRESULT mf_find_output_type(H264_CONTEXT_MF* sys, const GUID* guid,
|
||||
IMFMediaType** ppMediaType)
|
||||
{
|
||||
DWORD idx = 0;
|
||||
GUID mediaGuid;
|
||||
HRESULT hr = S_OK;
|
||||
IMFMediaType* pMediaType = nullptr;
|
||||
|
||||
while (1)
|
||||
{
|
||||
hr = sys->transform->lpVtbl->GetOutputAvailableType(sys->transform, 0, idx, &pMediaType);
|
||||
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
pMediaType->lpVtbl->GetGUID(pMediaType, &sMF_MT_SUBTYPE, &mediaGuid);
|
||||
|
||||
if (IsEqualGUID(&mediaGuid, guid))
|
||||
{
|
||||
*ppMediaType = pMediaType;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
pMediaType->lpVtbl->Release(pMediaType);
|
||||
idx++;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT mf_create_output_sample(H264_CONTEXT* h264, H264_CONTEXT_MF* sys)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
MFT_OUTPUT_STREAM_INFO streamInfo;
|
||||
|
||||
if (sys->outputSample)
|
||||
{
|
||||
sys->outputSample->lpVtbl->Release(sys->outputSample);
|
||||
sys->outputSample = nullptr;
|
||||
}
|
||||
|
||||
hr = sys->MFCreateSample(&sys->outputSample);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MFCreateSample failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->GetOutputStreamInfo(sys->transform, 0, &streamInfo);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "GetOutputStreamInfo failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->MFCreateMemoryBuffer(streamInfo.cbSize, &sys->outputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MFCreateMemoryBuffer failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sys->outputSample->lpVtbl->AddBuffer(sys->outputSample, sys->outputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AddBuffer failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sys->outputBuffer->lpVtbl->Release(sys->outputBuffer);
|
||||
error:
|
||||
return hr;
|
||||
}
|
||||
|
||||
static int mf_decompress(H264_CONTEXT* h264, const BYTE* pSrcData, UINT32 SrcSize)
|
||||
{
|
||||
HRESULT hr;
|
||||
BYTE* pbBuffer = nullptr;
|
||||
DWORD cbMaxLength = 0;
|
||||
DWORD cbCurrentLength = 0;
|
||||
DWORD outputStatus = 0;
|
||||
IMFSample* inputSample = nullptr;
|
||||
IMFMediaBuffer* inputBuffer = nullptr;
|
||||
IMFMediaBuffer* outputBuffer = nullptr;
|
||||
MFT_OUTPUT_DATA_BUFFER outputDataBuffer;
|
||||
H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*)h264->pSystemData;
|
||||
UINT32* iStride = h264->iStride;
|
||||
BYTE** pYUVData = h264->pYUVData;
|
||||
hr = sys->MFCreateMemoryBuffer(SrcSize, &inputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MFCreateMemoryBuffer failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = inputBuffer->lpVtbl->Lock(inputBuffer, &pbBuffer, &cbMaxLength, &cbCurrentLength);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Lock failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
CopyMemory(pbBuffer, pSrcData, SrcSize);
|
||||
hr = inputBuffer->lpVtbl->SetCurrentLength(inputBuffer, SrcSize);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "SetCurrentLength failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = inputBuffer->lpVtbl->Unlock(inputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Unlock failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->MFCreateSample(&inputSample);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MFCreateSample failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
inputSample->lpVtbl->AddBuffer(inputSample, inputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "AddBuffer failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
inputBuffer->lpVtbl->Release(inputBuffer);
|
||||
hr = sys->transform->lpVtbl->ProcessInput(sys->transform, 0, inputSample, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "ProcessInput failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = mf_create_output_sample(h264, sys);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "mf_create_output_sample failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
outputDataBuffer.dwStreamID = 0;
|
||||
outputDataBuffer.dwStatus = 0;
|
||||
outputDataBuffer.pEvents = nullptr;
|
||||
outputDataBuffer.pSample = sys->outputSample;
|
||||
hr = sys->transform->lpVtbl->ProcessOutput(sys->transform, 0, 1, &outputDataBuffer,
|
||||
&outputStatus);
|
||||
|
||||
if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
|
||||
{
|
||||
UINT32 stride = 0;
|
||||
UINT64 frameSize = 0;
|
||||
|
||||
if (sys->outputType)
|
||||
{
|
||||
sys->outputType->lpVtbl->Release(sys->outputType);
|
||||
sys->outputType = nullptr;
|
||||
}
|
||||
|
||||
hr = mf_find_output_type(sys, &sMFVideoFormat_IYUV, &sys->outputType);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "mf_find_output_type failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->SetOutputType(sys->transform, 0, sys->outputType, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "SetOutputType failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = mf_create_output_sample(h264, sys);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "mf_create_output_sample failure: 0x%08" PRIX32 "",
|
||||
hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->outputType->lpVtbl->GetUINT64(sys->outputType, &sMF_MT_FRAME_SIZE, &frameSize);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"GetUINT64(MF_MT_FRAME_SIZE) failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
sys->frameWidth = (UINT32)(frameSize >> 32);
|
||||
sys->frameHeight = (UINT32)frameSize;
|
||||
hr = sys->outputType->lpVtbl->GetUINT32(sys->outputType, &sMF_MT_DEFAULT_STRIDE, &stride);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"GetUINT32(MF_MT_DEFAULT_STRIDE) failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!avc420_ensure_buffer(h264, stride, sys->frameWidth, sys->frameHeight))
|
||||
goto error;
|
||||
}
|
||||
else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
|
||||
{
|
||||
}
|
||||
else if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "ProcessOutput failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = 0;
|
||||
BYTE* buffer = nullptr;
|
||||
DWORD bufferCount = 0;
|
||||
DWORD cbMaxLength = 0;
|
||||
DWORD cbCurrentLength = 0;
|
||||
hr = sys->outputSample->lpVtbl->GetBufferCount(sys->outputSample, &bufferCount);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "GetBufferCount failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->outputSample->lpVtbl->GetBufferByIndex(sys->outputSample, 0, &outputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "GetBufferByIndex failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = outputBuffer->lpVtbl->Lock(outputBuffer, &buffer, &cbMaxLength, &cbCurrentLength);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Lock failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
CopyMemory(pYUVData[0], &buffer[offset], iStride[0] * sys->frameHeight);
|
||||
offset += iStride[0] * sys->frameHeight;
|
||||
CopyMemory(pYUVData[1], &buffer[offset], iStride[1] * (sys->frameHeight / 2));
|
||||
offset += iStride[1] * (sys->frameHeight / 2);
|
||||
CopyMemory(pYUVData[2], &buffer[offset], iStride[2] * (sys->frameHeight / 2));
|
||||
offset += iStride[2] * (sys->frameHeight / 2);
|
||||
hr = outputBuffer->lpVtbl->Unlock(outputBuffer);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Unlock failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
outputBuffer->lpVtbl->Release(outputBuffer);
|
||||
}
|
||||
|
||||
inputSample->lpVtbl->Release(inputSample);
|
||||
return 1;
|
||||
error:
|
||||
(void)fprintf(stderr, "mf_decompress error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mf_compress(H264_CONTEXT* h264, const BYTE** ppSrcYuv, const UINT32* pStride,
|
||||
BYTE** ppDstData, UINT32* pDstSize)
|
||||
{
|
||||
H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*)h264->pSystemData;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL mf_plat_loaded(H264_CONTEXT_MF* sys)
|
||||
{
|
||||
return sys->MFStartup && sys->MFShutdown && sys->MFCreateSample && sys->MFCreateMemoryBuffer &&
|
||||
sys->MFCreateMediaType;
|
||||
}
|
||||
|
||||
static void mf_uninit(H264_CONTEXT* h264)
|
||||
{
|
||||
H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*)h264->pSystemData;
|
||||
|
||||
if (sys)
|
||||
{
|
||||
if (sys->transform)
|
||||
{
|
||||
sys->transform->lpVtbl->Release(sys->transform);
|
||||
sys->transform = nullptr;
|
||||
}
|
||||
|
||||
if (sys->codecApi)
|
||||
{
|
||||
sys->codecApi->lpVtbl->Release(sys->codecApi);
|
||||
sys->codecApi = nullptr;
|
||||
}
|
||||
|
||||
if (sys->inputType)
|
||||
{
|
||||
sys->inputType->lpVtbl->Release(sys->inputType);
|
||||
sys->inputType = nullptr;
|
||||
}
|
||||
|
||||
if (sys->outputType)
|
||||
{
|
||||
sys->outputType->lpVtbl->Release(sys->outputType);
|
||||
sys->outputType = nullptr;
|
||||
}
|
||||
|
||||
if (sys->outputSample)
|
||||
{
|
||||
sys->outputSample->lpVtbl->Release(sys->outputSample);
|
||||
sys->outputSample = nullptr;
|
||||
}
|
||||
|
||||
if (sys->mfplat)
|
||||
{
|
||||
if (mf_plat_loaded(sys))
|
||||
sys->MFShutdown();
|
||||
|
||||
FreeLibrary(sys->mfplat);
|
||||
sys->mfplat = nullptr;
|
||||
|
||||
if (mf_plat_loaded(sys))
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
for (size_t x = 0; x < sizeof(h264->pYUVData) / sizeof(h264->pYUVData[0]); x++)
|
||||
winpr_aligned_free(h264->pYUVData[x]);
|
||||
|
||||
memset(h264->pYUVData, 0, sizeof(h264->pYUVData));
|
||||
memset(h264->iStride, 0, sizeof(h264->iStride));
|
||||
|
||||
free(sys);
|
||||
h264->pSystemData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL mf_init(H264_CONTEXT* h264)
|
||||
{
|
||||
HRESULT hr;
|
||||
H264_CONTEXT_MF* sys = (H264_CONTEXT_MF*)calloc(1, sizeof(H264_CONTEXT_MF));
|
||||
|
||||
if (!sys)
|
||||
goto error;
|
||||
|
||||
h264->pSystemData = (void*)sys;
|
||||
/* http://decklink-sdk-delphi.googlecode.com/svn/trunk/Blackmagic%20DeckLink%20SDK%209.7/Win/Samples/Streaming/StreamingPreview/DecoderMF.cpp
|
||||
*/
|
||||
sys->mfplat = LoadLibraryA("mfplat.dll");
|
||||
|
||||
if (!sys->mfplat)
|
||||
goto error;
|
||||
|
||||
sys->MFStartup = GetProcAddressAs(sys->mfplat, "MFStartup", pfnMFStartup);
|
||||
sys->MFShutdown = GetProcAddressAs(sys->mfplat, "MFShutdown", pfnMFShutdown);
|
||||
sys->MFCreateSample = GetProcAddressAs(sys->mfplat, "MFCreateSample", pfnMFCreateSample);
|
||||
sys->MFCreateMemoryBuffer =
|
||||
GetProcAddressAs(sys->mfplat, "MFCreateMemoryBuffer", pfnMFCreateMemoryBuffer);
|
||||
sys->MFCreateMediaType =
|
||||
GetProcAddressAs(sys->mfplat, "MFCreateMediaType", pfnMFCreateMediaType);
|
||||
|
||||
if (!mf_plat_loaded(sys))
|
||||
goto error;
|
||||
|
||||
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||
|
||||
if (h264->Compressor)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
VARIANT var = WINPR_C_ARRAY_INIT;
|
||||
hr = sys->MFStartup(MF_VERSION, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MFStartup failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = CoCreateInstance(&sCLSID_CMSH264DecoderMFT, nullptr, CLSCTX_INPROC_SERVER,
|
||||
&sIID_IMFTransform, (void**)&sys->transform);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"CoCreateInstance(CLSID_CMSH264DecoderMFT) failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->QueryInterface(sys->transform, &sIID_ICodecAPI,
|
||||
(void**)&sys->codecApi);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"QueryInterface(IID_ICodecAPI) failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
var.vt = VT_UI4;
|
||||
var.ulVal = 1;
|
||||
hr = sys->codecApi->lpVtbl->SetValue(sys->codecApi, &sCODECAPI_AVLowLatencyMode, &var);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"SetValue(CODECAPI_AVLowLatencyMode) failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->MFCreateMediaType(&sys->inputType);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "MFCreateMediaType failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->inputType->lpVtbl->SetGUID(sys->inputType, &sMF_MT_MAJOR_TYPE,
|
||||
&sMFMediaType_Video);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "SetGUID(MF_MT_MAJOR_TYPE) failure: 0x%08" PRIX32 "",
|
||||
hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->inputType->lpVtbl->SetGUID(sys->inputType, &sMF_MT_SUBTYPE, &sMFVideoFormat_H264);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "SetGUID(MF_MT_SUBTYPE) failure: 0x%08" PRIX32 "",
|
||||
hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->SetInputType(sys->transform, 0, sys->inputType, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "SetInputType failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = mf_find_output_type(sys, &sMFVideoFormat_IYUV, &sys->outputType);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "mf_find_output_type failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = sys->transform->lpVtbl->SetOutputType(sys->transform, 0, sys->outputType, 0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "SetOutputType failure: 0x%08" PRIX32 "", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
hr = mf_create_output_sample(h264, sys);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "mf_create_output_sample failure: 0x%08" PRIX32 "",
|
||||
hr);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
error:
|
||||
WLog_Print(h264->log, WLOG_ERROR, "mf_init failure");
|
||||
mf_uninit(h264);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const H264_CONTEXT_SUBSYSTEM g_Subsystem_MF = { "MediaFoundation", mf_init, mf_uninit,
|
||||
mf_decompress, mf_compress };
|
||||
@@ -0,0 +1,662 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* H.264 Bitmap Compression
|
||||
*
|
||||
* Copyright 2014 Mike McDonald <Mike.McDonald@software.dell.com>
|
||||
* Copyright 2015 Vic Lee <llyzs.vic@gmail.com>
|
||||
* Copyright 2014 Armin Novak <armin.novak@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 <freerdp/config.h>
|
||||
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/library.h>
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
|
||||
#include <wels/codec_def.h>
|
||||
#include <wels/codec_api.h>
|
||||
#include <wels/codec_ver.h>
|
||||
|
||||
#include "h264.h"
|
||||
|
||||
typedef void (*pWelsGetCodecVersionEx)(OpenH264Version* pVersion);
|
||||
|
||||
typedef long (*pWelsCreateDecoder)(ISVCDecoder** ppDecoder);
|
||||
typedef void (*pWelsDestroyDecoder)(ISVCDecoder* pDecoder);
|
||||
|
||||
typedef int (*pWelsCreateSVCEncoder)(ISVCEncoder** ppEncoder);
|
||||
typedef void (*pWelsDestroySVCEncoder)(ISVCEncoder* pEncoder);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#if defined(WITH_OPENH264_LOADING)
|
||||
HMODULE lib;
|
||||
OpenH264Version version;
|
||||
#endif
|
||||
WINPR_ATTR_NODISCARD pWelsGetCodecVersionEx WelsGetCodecVersionEx;
|
||||
WINPR_ATTR_NODISCARD pWelsCreateDecoder WelsCreateDecoder;
|
||||
pWelsDestroyDecoder WelsDestroyDecoder;
|
||||
WINPR_ATTR_NODISCARD pWelsCreateSVCEncoder WelsCreateSVCEncoder;
|
||||
pWelsDestroySVCEncoder WelsDestroySVCEncoder;
|
||||
ISVCDecoder* pDecoder;
|
||||
ISVCEncoder* pEncoder;
|
||||
SEncParamExt EncParamExt;
|
||||
} H264_CONTEXT_OPENH264;
|
||||
|
||||
#if defined(WITH_OPENH264_LOADING)
|
||||
static const char* openh264_library_names[] = {
|
||||
#if defined(_WIN32)
|
||||
"openh264.dll"
|
||||
#elif defined(__APPLE__)
|
||||
"libopenh264.dylib"
|
||||
#else
|
||||
"libopenh264.so.7", "libopenh264.so.2.5.0", "libopenh264.so.2.4.1", "libopenh264.so.2.4.0",
|
||||
"libopenh264.so.2.3.1", "libopenh264.so.2.3.0", "libopenh264.so",
|
||||
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
static void openh264_trace_callback(void* ctx, int level, const char* message)
|
||||
{
|
||||
H264_CONTEXT* h264 = ctx;
|
||||
if (h264)
|
||||
WLog_Print(h264->log, WLOG_TRACE, "%d - %s", level, message);
|
||||
}
|
||||
|
||||
static int openh264_decompress(H264_CONTEXT* WINPR_RESTRICT h264,
|
||||
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize)
|
||||
{
|
||||
DECODING_STATE state = dsInvalidArgument;
|
||||
SBufferInfo sBufferInfo = WINPR_C_ARRAY_INIT;
|
||||
SSysMEMBuffer* pSystemBuffer = nullptr;
|
||||
H264_CONTEXT_OPENH264* sys = nullptr;
|
||||
UINT32* iStride = nullptr;
|
||||
BYTE** pYUVData = nullptr;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
WINPR_ASSERT(pSrcData || (SrcSize == 0));
|
||||
|
||||
sys = (H264_CONTEXT_OPENH264*)h264->pSystemData;
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
iStride = h264->iStride;
|
||||
WINPR_ASSERT(iStride);
|
||||
|
||||
pYUVData = h264->pYUVData;
|
||||
WINPR_ASSERT(pYUVData);
|
||||
|
||||
if (!sys->pDecoder)
|
||||
return -2001;
|
||||
|
||||
/*
|
||||
* Decompress the image. The RDP host only seems to send I420 format.
|
||||
*/
|
||||
pYUVData[0] = nullptr;
|
||||
pYUVData[1] = nullptr;
|
||||
pYUVData[2] = nullptr;
|
||||
|
||||
WINPR_ASSERT(sys->pDecoder);
|
||||
state = (*sys->pDecoder)
|
||||
->DecodeFrame2(sys->pDecoder, pSrcData, WINPR_ASSERTING_INT_CAST(int, SrcSize),
|
||||
pYUVData, &sBufferInfo);
|
||||
|
||||
if (sBufferInfo.iBufferStatus != 1)
|
||||
{
|
||||
if (state == dsNoParamSets)
|
||||
{
|
||||
/* this happens on the first frame due to missing parameter sets */
|
||||
state =
|
||||
(*sys->pDecoder)->DecodeFrame2(sys->pDecoder, nullptr, 0, pYUVData, &sBufferInfo);
|
||||
}
|
||||
else if (state == dsErrorFree)
|
||||
{
|
||||
/* call DecodeFrame2 again to decode without delay */
|
||||
state =
|
||||
(*sys->pDecoder)->DecodeFrame2(sys->pDecoder, nullptr, 0, pYUVData, &sBufferInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_WARN, "DecodeFrame2 state: 0x%04X iBufferStatus: %d", state,
|
||||
sBufferInfo.iBufferStatus);
|
||||
return -2002;
|
||||
}
|
||||
}
|
||||
|
||||
if (state != dsErrorFree)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_WARN, "DecodeFrame2 state: 0x%02X", state);
|
||||
return -2003;
|
||||
}
|
||||
|
||||
#if OPENH264_MAJOR >= 2
|
||||
state = (*sys->pDecoder)->FlushFrame(sys->pDecoder, pYUVData, &sBufferInfo);
|
||||
if (state != dsErrorFree)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_WARN, "FlushFrame state: 0x%02X", state);
|
||||
return -2003;
|
||||
}
|
||||
#endif
|
||||
|
||||
pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer;
|
||||
iStride[0] = WINPR_ASSERTING_INT_CAST(uint32_t, pSystemBuffer->iStride[0]);
|
||||
iStride[1] = WINPR_ASSERTING_INT_CAST(uint32_t, pSystemBuffer->iStride[1]);
|
||||
iStride[2] = WINPR_ASSERTING_INT_CAST(uint32_t, pSystemBuffer->iStride[1]);
|
||||
|
||||
if (sBufferInfo.iBufferStatus != 1)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_WARN, "DecodeFrame2 iBufferStatus: %d",
|
||||
sBufferInfo.iBufferStatus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (state != dsErrorFree)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_WARN, "DecodeFrame2 state: 0x%02X", state);
|
||||
return -2003;
|
||||
}
|
||||
|
||||
if (pSystemBuffer->iFormat != videoFormatI420)
|
||||
return -2004;
|
||||
|
||||
if (!pYUVData[0] || !pYUVData[1] || !pYUVData[2])
|
||||
return -2005;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int openh264_compress(H264_CONTEXT* WINPR_RESTRICT h264,
|
||||
const BYTE** WINPR_RESTRICT pYUVData,
|
||||
const UINT32* WINPR_RESTRICT iStride, BYTE** WINPR_RESTRICT ppDstData,
|
||||
UINT32* WINPR_RESTRICT pDstSize)
|
||||
{
|
||||
int status = 0;
|
||||
SFrameBSInfo info = WINPR_C_ARRAY_INIT;
|
||||
SSourcePicture pic = WINPR_C_ARRAY_INIT;
|
||||
|
||||
H264_CONTEXT_OPENH264* sys = nullptr;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
WINPR_ASSERT(pYUVData);
|
||||
WINPR_ASSERT(iStride);
|
||||
WINPR_ASSERT(ppDstData);
|
||||
WINPR_ASSERT(pDstSize);
|
||||
|
||||
sys = &((H264_CONTEXT_OPENH264*)h264->pSystemData)[0];
|
||||
WINPR_ASSERT(sys);
|
||||
|
||||
if (!sys->pEncoder)
|
||||
return -1;
|
||||
|
||||
if (!pYUVData[0] || !pYUVData[1] || !pYUVData[2])
|
||||
return -1;
|
||||
|
||||
if ((h264->width > INT_MAX) || (h264->height > INT_MAX))
|
||||
return -1;
|
||||
|
||||
if ((h264->FrameRate > INT_MAX) || (h264->NumberOfThreads > INT_MAX) ||
|
||||
(h264->BitRate > INT_MAX) || (h264->QP > INT_MAX))
|
||||
return -1;
|
||||
|
||||
WINPR_ASSERT(sys->pEncoder);
|
||||
if ((sys->EncParamExt.iPicWidth != (int)h264->width) ||
|
||||
(sys->EncParamExt.iPicHeight != (int)h264->height))
|
||||
{
|
||||
WINPR_ASSERT((*sys->pEncoder)->GetDefaultParams);
|
||||
status = (*sys->pEncoder)->GetDefaultParams(sys->pEncoder, &sys->EncParamExt);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to get OpenH264 default parameters (status=%d)", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
EUsageType usageType = SCREEN_CONTENT_REAL_TIME;
|
||||
|
||||
switch (h264->UsageType)
|
||||
{
|
||||
case H264_CAMERA_VIDEO_NON_REAL_TIME:
|
||||
usageType = CAMERA_VIDEO_NON_REAL_TIME;
|
||||
break;
|
||||
case H264_CAMERA_VIDEO_REAL_TIME:
|
||||
usageType = CAMERA_VIDEO_REAL_TIME;
|
||||
break;
|
||||
case H264_SCREEN_CONTENT_NON_REAL_TIME:
|
||||
usageType = SCREEN_CONTENT_NON_REAL_TIME;
|
||||
break;
|
||||
case H264_SCREEN_CONTENT_REAL_TIME:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sys->EncParamExt.iUsageType = usageType;
|
||||
sys->EncParamExt.iPicWidth = WINPR_ASSERTING_INT_CAST(int, h264->width);
|
||||
sys->EncParamExt.iPicHeight = WINPR_ASSERTING_INT_CAST(int, h264->height);
|
||||
sys->EncParamExt.fMaxFrameRate = WINPR_ASSERTING_INT_CAST(short, h264->FrameRate);
|
||||
sys->EncParamExt.iMaxBitrate = UNSPECIFIED_BIT_RATE;
|
||||
sys->EncParamExt.bEnableDenoise = 0;
|
||||
sys->EncParamExt.bEnableLongTermReference = 0;
|
||||
sys->EncParamExt.iSpatialLayerNum = 1;
|
||||
sys->EncParamExt.iMultipleThreadIdc =
|
||||
WINPR_ASSERTING_INT_CAST(unsigned short, h264->NumberOfThreads);
|
||||
sys->EncParamExt.sSpatialLayers[0].fFrameRate =
|
||||
WINPR_ASSERTING_INT_CAST(short, h264->FrameRate);
|
||||
sys->EncParamExt.sSpatialLayers[0].iVideoWidth = sys->EncParamExt.iPicWidth;
|
||||
sys->EncParamExt.sSpatialLayers[0].iVideoHeight = sys->EncParamExt.iPicHeight;
|
||||
sys->EncParamExt.sSpatialLayers[0].iMaxSpatialBitrate = sys->EncParamExt.iMaxBitrate;
|
||||
|
||||
switch (h264->RateControlMode)
|
||||
{
|
||||
case H264_RATECONTROL_VBR:
|
||||
sys->EncParamExt.iRCMode = RC_BITRATE_MODE;
|
||||
sys->EncParamExt.iTargetBitrate = (int)h264->BitRate;
|
||||
sys->EncParamExt.sSpatialLayers[0].iSpatialBitrate =
|
||||
sys->EncParamExt.iTargetBitrate;
|
||||
sys->EncParamExt.bEnableFrameSkip = 1;
|
||||
break;
|
||||
|
||||
case H264_RATECONTROL_CQP:
|
||||
sys->EncParamExt.iRCMode = RC_OFF_MODE;
|
||||
sys->EncParamExt.sSpatialLayers[0].iDLayerQp = (int)h264->QP;
|
||||
sys->EncParamExt.bEnableFrameSkip = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (sys->EncParamExt.iMultipleThreadIdc > 1)
|
||||
{
|
||||
#if (OPENH264_MAJOR == 1) && (OPENH264_MINOR <= 5)
|
||||
sys->EncParamExt.sSpatialLayers[0].sSliceCfg.uiSliceMode = SM_AUTO_SLICE;
|
||||
#else
|
||||
sys->EncParamExt.sSpatialLayers[0].sSliceArgument.uiSliceMode = SM_FIXEDSLCNUM_SLICE;
|
||||
#endif
|
||||
}
|
||||
|
||||
WINPR_ASSERT((*sys->pEncoder)->InitializeExt);
|
||||
status = (*sys->pEncoder)->InitializeExt(sys->pEncoder, &sys->EncParamExt);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to initialize OpenH264 encoder (status=%d)",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
WINPR_ASSERT((*sys->pEncoder)->GetOption);
|
||||
status =
|
||||
(*sys->pEncoder)
|
||||
->GetOption(sys->pEncoder, ENCODER_OPTION_SVC_ENCODE_PARAM_EXT, &sys->EncParamExt);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to get initial OpenH264 encoder parameters (status=%d)", status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (h264->RateControlMode)
|
||||
{
|
||||
case H264_RATECONTROL_VBR:
|
||||
if (sys->EncParamExt.iTargetBitrate != (int)h264->BitRate)
|
||||
{
|
||||
SBitrateInfo bitrate = WINPR_C_ARRAY_INIT;
|
||||
|
||||
sys->EncParamExt.iTargetBitrate = (int)h264->BitRate;
|
||||
bitrate.iLayer = SPATIAL_LAYER_ALL;
|
||||
bitrate.iBitrate = (int)h264->BitRate;
|
||||
|
||||
WINPR_ASSERT((*sys->pEncoder)->SetOption);
|
||||
status = (*sys->pEncoder)
|
||||
->SetOption(sys->pEncoder, ENCODER_OPTION_BITRATE, &bitrate);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to set encoder bitrate (status=%d)", status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if ((uint32_t)sys->EncParamExt.fMaxFrameRate != h264->FrameRate)
|
||||
{
|
||||
sys->EncParamExt.fMaxFrameRate = WINPR_ASSERTING_INT_CAST(int, h264->FrameRate);
|
||||
|
||||
WINPR_ASSERT((*sys->pEncoder)->SetOption);
|
||||
status = (*sys->pEncoder)
|
||||
->SetOption(sys->pEncoder, ENCODER_OPTION_FRAME_RATE,
|
||||
&sys->EncParamExt.fMaxFrameRate);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to set encoder framerate (status=%d)", status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case H264_RATECONTROL_CQP:
|
||||
if (sys->EncParamExt.sSpatialLayers[0].iDLayerQp != (int)h264->QP)
|
||||
{
|
||||
sys->EncParamExt.sSpatialLayers[0].iDLayerQp = (int)h264->QP;
|
||||
|
||||
WINPR_ASSERT((*sys->pEncoder)->SetOption);
|
||||
status = (*sys->pEncoder)
|
||||
->SetOption(sys->pEncoder, ENCODER_OPTION_SVC_ENCODE_PARAM_EXT,
|
||||
&sys->EncParamExt);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to set encoder parameters (status=%d)", status);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pic.iPicWidth = (int)h264->width;
|
||||
pic.iPicHeight = (int)h264->height;
|
||||
pic.iColorFormat = videoFormatI420;
|
||||
pic.iStride[0] = (int)iStride[0];
|
||||
pic.iStride[1] = (int)iStride[1];
|
||||
pic.iStride[2] = (int)iStride[2];
|
||||
pic.pData[0] = WINPR_CAST_CONST_PTR_AWAY(pYUVData[0], BYTE*);
|
||||
pic.pData[1] = WINPR_CAST_CONST_PTR_AWAY(pYUVData[1], BYTE*);
|
||||
pic.pData[2] = WINPR_CAST_CONST_PTR_AWAY(pYUVData[2], BYTE*);
|
||||
|
||||
WINPR_ASSERT((*sys->pEncoder)->EncodeFrame);
|
||||
status = (*sys->pEncoder)->EncodeFrame(sys->pEncoder, &pic, &info);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to encode frame (status=%d)", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
*ppDstData = info.sLayerInfo[0].pBsBuf;
|
||||
*pDstSize = 0;
|
||||
|
||||
for (int i = 0; i < info.iLayerNum; i++)
|
||||
{
|
||||
for (int j = 0; j < info.sLayerInfo[i].iNalCount; j++)
|
||||
{
|
||||
const int val = info.sLayerInfo[i].pNalLengthInByte[j];
|
||||
*pDstSize += WINPR_ASSERTING_INT_CAST(uint32_t, val);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void openh264_uninit(H264_CONTEXT* h264)
|
||||
{
|
||||
H264_CONTEXT_OPENH264* sysContexts = nullptr;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
sysContexts = (H264_CONTEXT_OPENH264*)h264->pSystemData;
|
||||
|
||||
if (sysContexts)
|
||||
{
|
||||
for (UINT32 x = 0; x < h264->numSystemData; x++)
|
||||
{
|
||||
H264_CONTEXT_OPENH264* sys = &sysContexts[x];
|
||||
|
||||
if (sys->pDecoder)
|
||||
{
|
||||
(*sys->pDecoder)->Uninitialize(sys->pDecoder);
|
||||
sysContexts->WelsDestroyDecoder(sys->pDecoder);
|
||||
sys->pDecoder = nullptr;
|
||||
}
|
||||
|
||||
if (sys->pEncoder)
|
||||
{
|
||||
(*sys->pEncoder)->Uninitialize(sys->pEncoder);
|
||||
sysContexts->WelsDestroySVCEncoder(sys->pEncoder);
|
||||
sys->pEncoder = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENH264_LOADING)
|
||||
if (sysContexts->lib)
|
||||
FreeLibrary(sysContexts->lib);
|
||||
#endif
|
||||
free(h264->pSystemData);
|
||||
h264->pSystemData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(WITH_OPENH264_LOADING)
|
||||
static BOOL openh264_load_functionpointers(H264_CONTEXT* h264, const char* name)
|
||||
{
|
||||
H264_CONTEXT_OPENH264* sysContexts;
|
||||
|
||||
WINPR_ASSERT(name);
|
||||
|
||||
if (!h264)
|
||||
return FALSE;
|
||||
|
||||
sysContexts = h264->pSystemData;
|
||||
|
||||
if (!sysContexts)
|
||||
return FALSE;
|
||||
|
||||
sysContexts->lib = LoadLibraryA(name);
|
||||
|
||||
if (!sysContexts->lib)
|
||||
return FALSE;
|
||||
|
||||
sysContexts->WelsGetCodecVersionEx =
|
||||
GetProcAddressAs(sysContexts->lib, "WelsGetCodecVersionEx", pWelsGetCodecVersionEx);
|
||||
sysContexts->WelsCreateDecoder =
|
||||
GetProcAddressAs(sysContexts->lib, "WelsCreateDecoder", pWelsCreateDecoder);
|
||||
sysContexts->WelsDestroyDecoder =
|
||||
GetProcAddressAs(sysContexts->lib, "WelsDestroyDecoder", pWelsDestroyDecoder);
|
||||
sysContexts->WelsCreateSVCEncoder =
|
||||
GetProcAddressAs(sysContexts->lib, "WelsCreateSVCEncoder", pWelsCreateSVCEncoder);
|
||||
sysContexts->WelsDestroySVCEncoder =
|
||||
GetProcAddressAs(sysContexts->lib, "WelsDestroySVCEncoder", pWelsDestroySVCEncoder);
|
||||
|
||||
if (!sysContexts->WelsCreateDecoder || !sysContexts->WelsDestroyDecoder ||
|
||||
!sysContexts->WelsCreateSVCEncoder || !sysContexts->WelsDestroySVCEncoder ||
|
||||
!sysContexts->WelsGetCodecVersionEx)
|
||||
{
|
||||
FreeLibrary(sysContexts->lib);
|
||||
sysContexts->lib = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sysContexts->WelsGetCodecVersionEx(&sysContexts->version);
|
||||
WLog_Print(h264->log, WLOG_INFO, "loaded %s %d.%d.%d", name, sysContexts->version.uMajor,
|
||||
sysContexts->version.uMinor, sysContexts->version.uRevision);
|
||||
|
||||
if ((sysContexts->version.uMajor < 1) ||
|
||||
((sysContexts->version.uMajor == 1) && (sysContexts->version.uMinor < 6)))
|
||||
{
|
||||
WLog_Print(
|
||||
h264->log, WLOG_ERROR,
|
||||
"OpenH264 %s %d.%d.%d is too old, need at least version 1.6.0 for dynamic loading",
|
||||
name, sysContexts->version.uMajor, sysContexts->version.uMinor,
|
||||
sysContexts->version.uRevision);
|
||||
FreeLibrary(sysContexts->lib);
|
||||
sysContexts->lib = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BOOL openh264_init(H264_CONTEXT* h264)
|
||||
{
|
||||
#if defined(WITH_OPENH264_LOADING)
|
||||
BOOL success = FALSE;
|
||||
#endif
|
||||
long status = 0;
|
||||
H264_CONTEXT_OPENH264* sysContexts = nullptr;
|
||||
static int traceLevel = WELS_LOG_DEBUG;
|
||||
#if (OPENH264_MAJOR == 1) && (OPENH264_MINOR <= 5)
|
||||
static EVideoFormatType videoFormat = videoFormatI420;
|
||||
#endif
|
||||
static WelsTraceCallback traceCallback = openh264_trace_callback;
|
||||
|
||||
WINPR_ASSERT(h264);
|
||||
|
||||
h264->numSystemData = 1;
|
||||
sysContexts =
|
||||
(H264_CONTEXT_OPENH264*)calloc(h264->numSystemData, sizeof(H264_CONTEXT_OPENH264));
|
||||
|
||||
if (!sysContexts)
|
||||
goto EXCEPTION;
|
||||
|
||||
h264->pSystemData = (void*)sysContexts;
|
||||
#if defined(WITH_OPENH264_LOADING)
|
||||
|
||||
for (size_t i = 0; i < ARRAYSIZE(openh264_library_names); i++)
|
||||
{
|
||||
const char* current = openh264_library_names[i];
|
||||
success = openh264_load_functionpointers(h264, current);
|
||||
|
||||
if (success)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!success)
|
||||
goto EXCEPTION;
|
||||
|
||||
#else
|
||||
sysContexts->WelsGetCodecVersionEx = WelsGetCodecVersionEx;
|
||||
sysContexts->WelsCreateDecoder = WelsCreateDecoder;
|
||||
sysContexts->WelsDestroyDecoder = WelsDestroyDecoder;
|
||||
sysContexts->WelsCreateSVCEncoder = WelsCreateSVCEncoder;
|
||||
sysContexts->WelsDestroySVCEncoder = WelsDestroySVCEncoder;
|
||||
#endif
|
||||
|
||||
for (UINT32 x = 0; x < h264->numSystemData; x++)
|
||||
{
|
||||
SDecodingParam sDecParam = WINPR_C_ARRAY_INIT;
|
||||
H264_CONTEXT_OPENH264* sys = &sysContexts[x];
|
||||
|
||||
if (h264->Compressor)
|
||||
{
|
||||
sysContexts->WelsCreateSVCEncoder(&sys->pEncoder);
|
||||
|
||||
if (!sys->pEncoder)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to create OpenH264 encoder");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sysContexts->WelsCreateDecoder(&sys->pDecoder);
|
||||
|
||||
if (!sys->pDecoder)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR, "Failed to create OpenH264 decoder");
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
#if (OPENH264_MAJOR == 1) && (OPENH264_MINOR <= 5)
|
||||
sDecParam.eOutputColorFormat = videoFormatI420;
|
||||
#endif
|
||||
sDecParam.eEcActiveIdc = ERROR_CON_FRAME_COPY;
|
||||
sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
|
||||
status = (*sys->pDecoder)->Initialize(sys->pDecoder, &sDecParam);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to initialize OpenH264 decoder (status=%ld)", status);
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
#if (OPENH264_MAJOR == 1) && (OPENH264_MINOR <= 5)
|
||||
status =
|
||||
(*sys->pDecoder)->SetOption(sys->pDecoder, DECODER_OPTION_DATAFORMAT, &videoFormat);
|
||||
#endif
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to set data format option on OpenH264 decoder (status=%ld)",
|
||||
status);
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
if (WLog_GetLogLevel(h264->log) == WLOG_TRACE)
|
||||
{
|
||||
status = (*sys->pDecoder)
|
||||
->SetOption(sys->pDecoder, DECODER_OPTION_TRACE_LEVEL, &traceLevel);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to set trace level option on OpenH264 decoder (status=%ld)",
|
||||
status);
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
status = (*sys->pDecoder)
|
||||
->SetOption(sys->pDecoder, DECODER_OPTION_TRACE_CALLBACK_CONTEXT,
|
||||
(void*)&h264);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_Print(h264->log, WLOG_ERROR,
|
||||
"Failed to set trace callback context option on OpenH264 decoder "
|
||||
"(status=%ld)",
|
||||
status);
|
||||
goto EXCEPTION;
|
||||
}
|
||||
|
||||
status = (*sys->pDecoder)
|
||||
->SetOption(sys->pDecoder, DECODER_OPTION_TRACE_CALLBACK,
|
||||
(void*)&traceCallback);
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
WLog_Print(
|
||||
h264->log, WLOG_ERROR,
|
||||
"Failed to set trace callback option on OpenH264 decoder (status=%ld)",
|
||||
status);
|
||||
goto EXCEPTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h264->hwAccel = FALSE; /* not supported */
|
||||
return TRUE;
|
||||
EXCEPTION:
|
||||
openh264_uninit(h264);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const H264_CONTEXT_SUBSYSTEM g_Subsystem_OpenH264 = { "OpenH264", openh264_init, openh264_uninit,
|
||||
openh264_decompress, openh264_compress };
|
||||
@@ -0,0 +1,457 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RLE Compressed Bitmap Stream
|
||||
*
|
||||
* Copyright 2011 Jay Sorg <jay.sorg@gmail.com>
|
||||
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2016 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
/* do not compile the file directly */
|
||||
|
||||
/**
|
||||
* Write a foreground/background image to a destination buffer.
|
||||
*/
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline BYTE* WRITEFGBGIMAGE(BYTE* WINPR_RESTRICT pbDest,
|
||||
const BYTE* WINPR_RESTRICT pbDestEnd, UINT32 rowDelta,
|
||||
BYTE bitmask, PIXEL fgPel, UINT32 cBits)
|
||||
{
|
||||
PIXEL xorPixel = 0;
|
||||
BYTE mask = 0x01;
|
||||
|
||||
if (cBits > 8)
|
||||
{
|
||||
WLog_ERR(TAG, "cBits %" PRIu32 " > 8", cBits);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
|
||||
return nullptr;
|
||||
|
||||
UNROLL(cBits, {
|
||||
PIXEL data = 0;
|
||||
DESTREADPIXEL(xorPixel, pbDest - rowDelta);
|
||||
|
||||
if (bitmask & mask)
|
||||
data = xorPixel ^ fgPel;
|
||||
else
|
||||
data = xorPixel;
|
||||
|
||||
DESTWRITEPIXEL(pbDest, data);
|
||||
mask = WINPR_ASSERTING_INT_CAST(BYTE, (mask << 1) & 0xFF);
|
||||
});
|
||||
return pbDest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a foreground/background image to a destination buffer
|
||||
* for the first line of compressed data.
|
||||
*/
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* WINPR_RESTRICT pbDest,
|
||||
const BYTE* WINPR_RESTRICT pbDestEnd, BYTE bitmask,
|
||||
PIXEL fgPel, UINT32 cBits)
|
||||
{
|
||||
BYTE mask = 0x01;
|
||||
|
||||
if (cBits > 8)
|
||||
{
|
||||
WLog_ERR(TAG, "cBits %" PRIu32 " > 8", cBits);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
|
||||
return nullptr;
|
||||
|
||||
UNROLL(cBits, {
|
||||
PIXEL data;
|
||||
|
||||
if (bitmask & mask)
|
||||
data = fgPel;
|
||||
else
|
||||
data = BLACK_PIXEL;
|
||||
|
||||
DESTWRITEPIXEL(pbDest, data);
|
||||
mask = WINPR_ASSERTING_INT_CAST(BYTE, (mask << 1) & 0xFF);
|
||||
});
|
||||
return pbDest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress an RLE compressed bitmap.
|
||||
*/
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline BOOL RLEDECOMPRESS(const BYTE* WINPR_RESTRICT pbSrcBuffer, UINT32 cbSrcBuffer,
|
||||
BYTE* WINPR_RESTRICT pbDestBuffer, UINT32 rowDelta, UINT32 width,
|
||||
UINT32 height)
|
||||
{
|
||||
const BYTE* pbSrc = pbSrcBuffer;
|
||||
BYTE* pbDest = pbDestBuffer;
|
||||
PIXEL temp = 0;
|
||||
PIXEL fgPel = WHITE_PIXEL;
|
||||
BOOL fInsertFgPel = FALSE;
|
||||
BOOL fFirstLine = TRUE;
|
||||
BYTE bitmask = 0;
|
||||
PIXEL pixelA = 0;
|
||||
PIXEL pixelB = 0;
|
||||
UINT32 runLength = 0;
|
||||
UINT32 code = 0;
|
||||
UINT32 advance = 0;
|
||||
RLEEXTRA
|
||||
|
||||
if ((rowDelta == 0) || (rowDelta < width))
|
||||
{
|
||||
WLog_ERR(TAG, "Invalid arguments: rowDelta=%" PRIu32 " == 0 || < width=%" PRIu32, rowDelta,
|
||||
width);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!pbSrcBuffer || !pbDestBuffer)
|
||||
{
|
||||
WLog_ERR(TAG, "Invalid arguments: pbSrcBuffer=%p, pbDestBuffer=%p",
|
||||
WINPR_CXX_COMPAT_CAST(const void*, pbSrcBuffer),
|
||||
WINPR_CXX_COMPAT_CAST(const void*, pbDestBuffer));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const BYTE* pbEnd = &pbSrcBuffer[cbSrcBuffer];
|
||||
const BYTE* pbDestEnd = &pbDestBuffer[1ULL * rowDelta * height];
|
||||
|
||||
while (pbSrc < pbEnd)
|
||||
{
|
||||
/* Watch out for the end of the first scanline. */
|
||||
if (fFirstLine)
|
||||
{
|
||||
if ((UINT32)(pbDest - pbDestBuffer) >= rowDelta)
|
||||
{
|
||||
fFirstLine = FALSE;
|
||||
fInsertFgPel = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Extract the compression order code ID from the compression
|
||||
order header.
|
||||
*/
|
||||
code = ExtractCodeId(*pbSrc);
|
||||
|
||||
#if defined(WITH_DEBUG_CODECS)
|
||||
WLog_VRB(TAG, "pbSrc=%p code=%s, rem=%" PRIuz, pbSrc, rle_code_str(code), pbEnd - pbSrc);
|
||||
#endif
|
||||
|
||||
/* Handle Background Run Orders. */
|
||||
if ((code == REGULAR_BG_RUN) || (code == MEGA_MEGA_BG_RUN))
|
||||
{
|
||||
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
|
||||
if (advance == 0)
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + advance;
|
||||
|
||||
if (fFirstLine)
|
||||
{
|
||||
if (fInsertFgPel)
|
||||
{
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
|
||||
return FALSE;
|
||||
|
||||
DESTWRITEPIXEL(pbDest, fgPel);
|
||||
runLength = runLength - 1;
|
||||
}
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
|
||||
return FALSE;
|
||||
|
||||
UNROLL(runLength, { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); });
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fInsertFgPel)
|
||||
{
|
||||
DESTREADPIXEL(temp, pbDest - rowDelta);
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
|
||||
return FALSE;
|
||||
|
||||
DESTWRITEPIXEL(pbDest, temp ^ fgPel);
|
||||
runLength--;
|
||||
}
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
|
||||
return FALSE;
|
||||
|
||||
UNROLL(runLength, {
|
||||
DESTREADPIXEL(temp, pbDest - rowDelta);
|
||||
DESTWRITEPIXEL(pbDest, temp);
|
||||
});
|
||||
}
|
||||
|
||||
/* A follow-on background run order will need a foreground pel inserted. */
|
||||
fInsertFgPel = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* For any of the other run-types a follow-on background run
|
||||
order does not need a foreground pel inserted. */
|
||||
fInsertFgPel = FALSE;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
/* Handle Foreground Run Orders. */
|
||||
case REGULAR_FG_RUN:
|
||||
case MEGA_MEGA_FG_RUN:
|
||||
case LITE_SET_FG_FG_RUN:
|
||||
case MEGA_MEGA_SET_FG_RUN:
|
||||
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
|
||||
if (advance == 0)
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + advance;
|
||||
|
||||
if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
|
||||
{
|
||||
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
|
||||
return FALSE;
|
||||
SRCREADPIXEL(fgPel, pbSrc);
|
||||
}
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
|
||||
return FALSE;
|
||||
|
||||
if (fFirstLine)
|
||||
{
|
||||
UNROLL(runLength, { DESTWRITEPIXEL(pbDest, fgPel); });
|
||||
}
|
||||
else
|
||||
{
|
||||
UNROLL(runLength, {
|
||||
DESTREADPIXEL(temp, pbDest - rowDelta);
|
||||
DESTWRITEPIXEL(pbDest, temp ^ fgPel);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* Handle Dithered Run Orders. */
|
||||
case LITE_DITHERED_RUN:
|
||||
case MEGA_MEGA_DITHERED_RUN:
|
||||
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
|
||||
if (advance == 0)
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + advance;
|
||||
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
|
||||
return FALSE;
|
||||
SRCREADPIXEL(pixelA, pbSrc);
|
||||
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
|
||||
return FALSE;
|
||||
SRCREADPIXEL(pixelB, pbSrc);
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength * 2))
|
||||
return FALSE;
|
||||
|
||||
UNROLL(runLength, {
|
||||
DESTWRITEPIXEL(pbDest, pixelA);
|
||||
DESTWRITEPIXEL(pbDest, pixelB);
|
||||
});
|
||||
break;
|
||||
|
||||
/* Handle Color Run Orders. */
|
||||
case REGULAR_COLOR_RUN:
|
||||
case MEGA_MEGA_COLOR_RUN:
|
||||
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
|
||||
if (advance == 0)
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + advance;
|
||||
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
|
||||
return FALSE;
|
||||
SRCREADPIXEL(pixelA, pbSrc);
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
|
||||
return FALSE;
|
||||
|
||||
UNROLL(runLength, { DESTWRITEPIXEL(pbDest, pixelA); });
|
||||
break;
|
||||
|
||||
/* Handle Foreground/Background Image Orders. */
|
||||
case REGULAR_FGBG_IMAGE:
|
||||
case MEGA_MEGA_FGBG_IMAGE:
|
||||
case LITE_SET_FG_FGBG_IMAGE:
|
||||
case MEGA_MEGA_SET_FGBG_IMAGE:
|
||||
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
|
||||
if (advance == 0)
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + advance;
|
||||
|
||||
if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
|
||||
{
|
||||
if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
|
||||
return FALSE;
|
||||
SRCREADPIXEL(fgPel, pbSrc);
|
||||
}
|
||||
|
||||
if (!buffer_within_range(pbSrc, runLength / 8, pbEnd))
|
||||
return FALSE;
|
||||
if (fFirstLine)
|
||||
{
|
||||
while (runLength > 8)
|
||||
{
|
||||
bitmask = *pbSrc;
|
||||
pbSrc = pbSrc + 1;
|
||||
pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, bitmask, fgPel, 8);
|
||||
|
||||
if (!pbDest)
|
||||
return FALSE;
|
||||
|
||||
runLength = runLength - 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (runLength > 8)
|
||||
{
|
||||
bitmask = *pbSrc++;
|
||||
|
||||
pbDest = WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, 8);
|
||||
|
||||
if (!pbDest)
|
||||
return FALSE;
|
||||
|
||||
runLength = runLength - 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (runLength > 0)
|
||||
{
|
||||
if (!buffer_within_range(pbSrc, 1, pbEnd))
|
||||
return FALSE;
|
||||
bitmask = *pbSrc++;
|
||||
|
||||
if (fFirstLine)
|
||||
{
|
||||
pbDest =
|
||||
WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, bitmask, fgPel, runLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
pbDest =
|
||||
WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, runLength);
|
||||
}
|
||||
|
||||
if (!pbDest)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/* Handle Color Image Orders. */
|
||||
case REGULAR_COLOR_IMAGE:
|
||||
case MEGA_MEGA_COLOR_IMAGE:
|
||||
runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
|
||||
if (advance == 0)
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + advance;
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
|
||||
return FALSE;
|
||||
if (!ENSURE_CAPACITY(pbSrc, pbEnd, runLength))
|
||||
return FALSE;
|
||||
|
||||
UNROLL(runLength, {
|
||||
SRCREADPIXEL(temp, pbSrc);
|
||||
DESTWRITEPIXEL(pbDest, temp);
|
||||
});
|
||||
break;
|
||||
|
||||
/* Handle Special Order 1. */
|
||||
case SPECIAL_FGBG_1:
|
||||
if (!buffer_within_range(pbSrc, 1, pbEnd))
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + 1;
|
||||
|
||||
if (fFirstLine)
|
||||
{
|
||||
pbDest =
|
||||
WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, g_MaskSpecialFgBg1, fgPel, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
pbDest =
|
||||
WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, g_MaskSpecialFgBg1, fgPel, 8);
|
||||
}
|
||||
|
||||
if (!pbDest)
|
||||
return FALSE;
|
||||
|
||||
break;
|
||||
|
||||
/* Handle Special Order 2. */
|
||||
case SPECIAL_FGBG_2:
|
||||
if (!buffer_within_range(pbSrc, 1, pbEnd))
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + 1;
|
||||
|
||||
if (fFirstLine)
|
||||
{
|
||||
pbDest =
|
||||
WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, g_MaskSpecialFgBg2, fgPel, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
pbDest =
|
||||
WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, g_MaskSpecialFgBg2, fgPel, 8);
|
||||
}
|
||||
|
||||
if (!pbDest)
|
||||
return FALSE;
|
||||
|
||||
break;
|
||||
|
||||
/* Handle White Order. */
|
||||
case SPECIAL_WHITE:
|
||||
if (!buffer_within_range(pbSrc, 1, pbEnd))
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + 1;
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
|
||||
return FALSE;
|
||||
|
||||
DESTWRITEPIXEL(pbDest, WHITE_PIXEL);
|
||||
break;
|
||||
|
||||
/* Handle Black Order. */
|
||||
case SPECIAL_BLACK:
|
||||
if (!buffer_within_range(pbSrc, 1, pbEnd))
|
||||
return FALSE;
|
||||
pbSrc = pbSrc + 1;
|
||||
|
||||
if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
|
||||
return FALSE;
|
||||
|
||||
DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "invalid code 0x%08" PRIx32 ", pbSrcBuffer=%p, pbSrc=%p, pbEnd=%p",
|
||||
code, WINPR_CXX_COMPAT_CAST(const void*, pbSrcBuffer),
|
||||
WINPR_CXX_COMPAT_CAST(const void*, pbSrc),
|
||||
WINPR_CXX_COMPAT_CAST(const void*, pbEnd));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
+755
@@ -0,0 +1,755 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Interleaved RLE Bitmap Codec
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2016 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <freerdp/codec/interleaved.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#define TAG FREERDP_TAG("codec")
|
||||
|
||||
#define UNROLL_BODY(_exp, _count) \
|
||||
do \
|
||||
{ \
|
||||
for (size_t x = 0; x < (_count); x++) \
|
||||
{ \
|
||||
do \
|
||||
{ \
|
||||
_exp \
|
||||
} while (FALSE); \
|
||||
} \
|
||||
} while (FALSE)
|
||||
|
||||
#define UNROLL_MULTIPLE(_condition, _exp, _count) \
|
||||
do \
|
||||
{ \
|
||||
while ((_condition) >= (_count)) \
|
||||
{ \
|
||||
UNROLL_BODY(_exp, _count); \
|
||||
(_condition) -= (_count); \
|
||||
} \
|
||||
} while (FALSE)
|
||||
|
||||
#define UNROLL(_condition, _exp) \
|
||||
do \
|
||||
{ \
|
||||
UNROLL_MULTIPLE(_condition, _exp, 16); \
|
||||
UNROLL_MULTIPLE(_condition, _exp, 4); \
|
||||
UNROLL_MULTIPLE(_condition, _exp, 1); \
|
||||
} while (FALSE)
|
||||
|
||||
/*
|
||||
RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM)
|
||||
http://msdn.microsoft.com/en-us/library/cc240895%28v=prot.10%29.aspx
|
||||
pseudo-code
|
||||
http://msdn.microsoft.com/en-us/library/dd240593%28v=prot.10%29.aspx
|
||||
*/
|
||||
|
||||
#define REGULAR_BG_RUN 0x00
|
||||
#define MEGA_MEGA_BG_RUN 0xF0
|
||||
#define REGULAR_FG_RUN 0x01
|
||||
#define MEGA_MEGA_FG_RUN 0xF1
|
||||
#define LITE_SET_FG_FG_RUN 0x0C
|
||||
#define MEGA_MEGA_SET_FG_RUN 0xF6
|
||||
#define LITE_DITHERED_RUN 0x0E
|
||||
#define MEGA_MEGA_DITHERED_RUN 0xF8
|
||||
#define REGULAR_COLOR_RUN 0x03
|
||||
#define MEGA_MEGA_COLOR_RUN 0xF3
|
||||
#define REGULAR_FGBG_IMAGE 0x02
|
||||
#define MEGA_MEGA_FGBG_IMAGE 0xF2
|
||||
#define LITE_SET_FG_FGBG_IMAGE 0x0D
|
||||
#define MEGA_MEGA_SET_FGBG_IMAGE 0xF7
|
||||
#define REGULAR_COLOR_IMAGE 0x04
|
||||
#define MEGA_MEGA_COLOR_IMAGE 0xF4
|
||||
#define SPECIAL_FGBG_1 0xF9
|
||||
#define SPECIAL_FGBG_2 0xFA
|
||||
#define SPECIAL_WHITE 0xFD
|
||||
#define SPECIAL_BLACK 0xFE
|
||||
|
||||
#define BLACK_PIXEL 0x000000
|
||||
|
||||
typedef UINT32 PIXEL;
|
||||
|
||||
static const BYTE g_MaskSpecialFgBg1 = 0x03;
|
||||
static const BYTE g_MaskSpecialFgBg2 = 0x05;
|
||||
|
||||
static const BYTE g_MaskRegularRunLength = 0x1F;
|
||||
static const BYTE g_MaskLiteRunLength = 0x0F;
|
||||
|
||||
#if defined(WITH_DEBUG_CODECS)
|
||||
static const char* rle_code_str(UINT32 code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case REGULAR_BG_RUN:
|
||||
return "REGULAR_BG_RUN";
|
||||
case MEGA_MEGA_BG_RUN:
|
||||
return "MEGA_MEGA_BG_RUN";
|
||||
case REGULAR_FG_RUN:
|
||||
return "REGULAR_FG_RUN";
|
||||
case MEGA_MEGA_FG_RUN:
|
||||
return "MEGA_MEGA_FG_RUN";
|
||||
case LITE_SET_FG_FG_RUN:
|
||||
return "LITE_SET_FG_FG_RUN";
|
||||
case MEGA_MEGA_SET_FG_RUN:
|
||||
return "MEGA_MEGA_SET_FG_RUN";
|
||||
case LITE_DITHERED_RUN:
|
||||
return "LITE_DITHERED_RUN";
|
||||
case MEGA_MEGA_DITHERED_RUN:
|
||||
return "MEGA_MEGA_DITHERED_RUN";
|
||||
case REGULAR_COLOR_RUN:
|
||||
return "REGULAR_COLOR_RUN";
|
||||
case MEGA_MEGA_COLOR_RUN:
|
||||
return "MEGA_MEGA_COLOR_RUN";
|
||||
case REGULAR_FGBG_IMAGE:
|
||||
return "REGULAR_FGBG_IMAGE";
|
||||
case MEGA_MEGA_FGBG_IMAGE:
|
||||
return "MEGA_MEGA_FGBG_IMAGE";
|
||||
case LITE_SET_FG_FGBG_IMAGE:
|
||||
return "LITE_SET_FG_FGBG_IMAGE";
|
||||
case MEGA_MEGA_SET_FGBG_IMAGE:
|
||||
return "MEGA_MEGA_SET_FGBG_IMAGE";
|
||||
case REGULAR_COLOR_IMAGE:
|
||||
return "REGULAR_COLOR_IMAGE";
|
||||
case MEGA_MEGA_COLOR_IMAGE:
|
||||
return "MEGA_MEGA_COLOR_IMAGE";
|
||||
case SPECIAL_FGBG_1:
|
||||
return "SPECIAL_FGBG_1";
|
||||
case SPECIAL_FGBG_2:
|
||||
return "SPECIAL_FGBG_2";
|
||||
case SPECIAL_WHITE:
|
||||
return "SPECIAL_WHITE";
|
||||
case SPECIAL_BLACK:
|
||||
return "SPECIAL_BLACK";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define buffer_within_range(pbSrc, size, pbEnd) \
|
||||
buffer_within_range_((pbSrc), (size), (pbEnd), __func__, __FILE__, __LINE__)
|
||||
static inline BOOL buffer_within_range_(const void* pbSrc, size_t size, const void* pbEnd,
|
||||
const char* fkt, const char* file, size_t line)
|
||||
{
|
||||
WINPR_UNUSED(file);
|
||||
WINPR_ASSERT(pbSrc);
|
||||
WINPR_ASSERT(pbEnd);
|
||||
|
||||
if ((const char*)pbSrc + size > (const char*)pbEnd)
|
||||
{
|
||||
WLog_ERR(TAG, "[%s:%" PRIuz "] pbSrc=%p + %" PRIuz " > pbEnd=%p", fkt, line, pbSrc, size,
|
||||
pbEnd);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the supplied order header and extracts the compression
|
||||
* order code ID.
|
||||
*/
|
||||
static inline UINT32 ExtractCodeId(BYTE bOrderHdr)
|
||||
{
|
||||
if ((bOrderHdr & 0xC0U) != 0xC0U)
|
||||
{
|
||||
/* REGULAR orders
|
||||
* (000x xxxx, 001x xxxx, 010x xxxx, 011x xxxx, 100x xxxx)
|
||||
*/
|
||||
return bOrderHdr >> 5;
|
||||
}
|
||||
else if ((bOrderHdr & 0xF0U) == 0xF0U)
|
||||
{
|
||||
/* MEGA and SPECIAL orders (0xF*) */
|
||||
return bOrderHdr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* LITE orders
|
||||
* 1100 xxxx, 1101 xxxx, 1110 xxxx)
|
||||
*/
|
||||
return bOrderHdr >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the run length of a compression order.
|
||||
*/
|
||||
static UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
|
||||
{
|
||||
UINT runLength = 0;
|
||||
|
||||
WINPR_ASSERT(pbOrderHdr);
|
||||
WINPR_ASSERT(pbEnd);
|
||||
WINPR_ASSERT(advance);
|
||||
|
||||
runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
|
||||
if (runLength == 0)
|
||||
{
|
||||
if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
|
||||
{
|
||||
*advance = 0;
|
||||
return 0;
|
||||
}
|
||||
runLength = *(pbOrderHdr + 1) + 1;
|
||||
(*advance)++;
|
||||
}
|
||||
else
|
||||
runLength = runLength * 8;
|
||||
|
||||
return runLength;
|
||||
}
|
||||
|
||||
static UINT ExtractRunLengthLiteFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
|
||||
{
|
||||
UINT runLength = 0;
|
||||
|
||||
WINPR_ASSERT(pbOrderHdr);
|
||||
WINPR_ASSERT(pbEnd);
|
||||
WINPR_ASSERT(advance);
|
||||
|
||||
runLength = *pbOrderHdr & g_MaskLiteRunLength;
|
||||
if (runLength == 0)
|
||||
{
|
||||
if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
|
||||
{
|
||||
*advance = 0;
|
||||
return 0;
|
||||
}
|
||||
runLength = *(pbOrderHdr + 1) + 1;
|
||||
(*advance)++;
|
||||
}
|
||||
else
|
||||
runLength = runLength * 8;
|
||||
|
||||
return runLength;
|
||||
}
|
||||
|
||||
static UINT ExtractRunLengthRegular(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
|
||||
{
|
||||
UINT runLength = 0;
|
||||
|
||||
WINPR_ASSERT(pbOrderHdr);
|
||||
WINPR_ASSERT(pbEnd);
|
||||
WINPR_ASSERT(advance);
|
||||
|
||||
runLength = *pbOrderHdr & g_MaskRegularRunLength;
|
||||
if (runLength == 0)
|
||||
{
|
||||
if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
|
||||
{
|
||||
*advance = 0;
|
||||
return 0;
|
||||
}
|
||||
runLength = *(pbOrderHdr + 1) + 32;
|
||||
(*advance)++;
|
||||
}
|
||||
|
||||
return runLength;
|
||||
}
|
||||
|
||||
static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
|
||||
{
|
||||
UINT runLength = 0;
|
||||
|
||||
WINPR_ASSERT(pbOrderHdr);
|
||||
WINPR_ASSERT(pbEnd);
|
||||
WINPR_ASSERT(advance);
|
||||
|
||||
if (!buffer_within_range(pbOrderHdr, 3, pbEnd))
|
||||
{
|
||||
*advance = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
runLength = ((UINT16)pbOrderHdr[1]) | ((((UINT16)pbOrderHdr[2]) << 8) & 0xFF00);
|
||||
(*advance) += 2;
|
||||
|
||||
return runLength;
|
||||
}
|
||||
|
||||
static UINT ExtractRunLengthLite(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
|
||||
{
|
||||
UINT runLength = 0;
|
||||
|
||||
WINPR_ASSERT(pbOrderHdr);
|
||||
WINPR_ASSERT(pbEnd);
|
||||
WINPR_ASSERT(advance);
|
||||
|
||||
runLength = *pbOrderHdr & g_MaskLiteRunLength;
|
||||
if (runLength == 0)
|
||||
{
|
||||
if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
|
||||
{
|
||||
*advance = 0;
|
||||
return 0;
|
||||
}
|
||||
runLength = *(pbOrderHdr + 1) + 16;
|
||||
(*advance)++;
|
||||
}
|
||||
return runLength;
|
||||
}
|
||||
|
||||
static inline UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const BYTE* pbEnd,
|
||||
UINT32* advance)
|
||||
{
|
||||
UINT32 runLength = 0;
|
||||
UINT32 ladvance = 1;
|
||||
|
||||
WINPR_ASSERT(pbOrderHdr);
|
||||
WINPR_ASSERT(pbEnd);
|
||||
WINPR_ASSERT(advance);
|
||||
|
||||
#if defined(WITH_DEBUG_CODECS)
|
||||
WLog_VRB(TAG, "extracting %s", rle_code_str(code));
|
||||
#endif
|
||||
|
||||
*advance = 0;
|
||||
if (!buffer_within_range(pbOrderHdr, 0, pbEnd))
|
||||
return 0;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case REGULAR_FGBG_IMAGE:
|
||||
runLength = ExtractRunLengthRegularFgBg(pbOrderHdr, pbEnd, &ladvance);
|
||||
break;
|
||||
|
||||
case LITE_SET_FG_FGBG_IMAGE:
|
||||
runLength = ExtractRunLengthLiteFgBg(pbOrderHdr, pbEnd, &ladvance);
|
||||
break;
|
||||
|
||||
case REGULAR_BG_RUN:
|
||||
case REGULAR_FG_RUN:
|
||||
case REGULAR_COLOR_RUN:
|
||||
case REGULAR_COLOR_IMAGE:
|
||||
runLength = ExtractRunLengthRegular(pbOrderHdr, pbEnd, &ladvance);
|
||||
break;
|
||||
|
||||
case LITE_SET_FG_FG_RUN:
|
||||
case LITE_DITHERED_RUN:
|
||||
runLength = ExtractRunLengthLite(pbOrderHdr, pbEnd, &ladvance);
|
||||
break;
|
||||
|
||||
case MEGA_MEGA_BG_RUN:
|
||||
case MEGA_MEGA_FG_RUN:
|
||||
case MEGA_MEGA_SET_FG_RUN:
|
||||
case MEGA_MEGA_DITHERED_RUN:
|
||||
case MEGA_MEGA_COLOR_RUN:
|
||||
case MEGA_MEGA_FGBG_IMAGE:
|
||||
case MEGA_MEGA_SET_FGBG_IMAGE:
|
||||
case MEGA_MEGA_COLOR_IMAGE:
|
||||
runLength = ExtractRunLengthMegaMega(pbOrderHdr, pbEnd, &ladvance);
|
||||
break;
|
||||
|
||||
default:
|
||||
runLength = 0;
|
||||
ladvance = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
*advance = ladvance;
|
||||
return runLength;
|
||||
}
|
||||
|
||||
#define ensure_capacity(start, end, size, base) \
|
||||
ensure_capacity_((start), (end), (size), (base), __func__, __FILE__, __LINE__)
|
||||
static inline BOOL ensure_capacity_(const BYTE* start, const BYTE* end, size_t size, size_t base,
|
||||
const char* fkt, WINPR_ATTR_UNUSED const char* file,
|
||||
size_t line)
|
||||
{
|
||||
const size_t available = (uintptr_t)end - (uintptr_t)start;
|
||||
const BOOL rc = available >= size * base;
|
||||
const BOOL res = rc && (start <= end);
|
||||
|
||||
if (!res)
|
||||
WLog_ERR(TAG,
|
||||
"[%s:%" PRIuz "] failed: start=%p <= end=%p, available=%" PRIuz " >= size=%" PRIuz
|
||||
" * base=%" PRIuz,
|
||||
fkt, line, WINPR_CXX_COMPAT_CAST(const void*, start),
|
||||
WINPR_CXX_COMPAT_CAST(const void*, end), available, size, base);
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline void write_pixel_8(BYTE* _buf, BYTE _pix)
|
||||
{
|
||||
WINPR_ASSERT(_buf);
|
||||
*_buf = _pix;
|
||||
}
|
||||
|
||||
static inline void write_pixel_24(BYTE* _buf, UINT32 _pix)
|
||||
{
|
||||
WINPR_ASSERT(_buf);
|
||||
(_buf)[0] = (BYTE)(_pix);
|
||||
(_buf)[1] = (BYTE)((_pix) >> 8);
|
||||
(_buf)[2] = (BYTE)((_pix) >> 16);
|
||||
}
|
||||
|
||||
static inline void write_pixel_16(BYTE* _buf, UINT16 _pix)
|
||||
{
|
||||
WINPR_ASSERT(_buf);
|
||||
_buf[0] = _pix & 0xFF;
|
||||
_buf[1] = (_pix >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
#undef DESTWRITEPIXEL
|
||||
#undef DESTREADPIXEL
|
||||
#undef SRCREADPIXEL
|
||||
#undef WRITEFGBGIMAGE
|
||||
#undef WRITEFIRSTLINEFGBGIMAGE
|
||||
#undef RLEDECOMPRESS
|
||||
#undef RLEEXTRA
|
||||
#undef WHITE_PIXEL
|
||||
#undef PIXEL_SIZE
|
||||
#undef PIXEL
|
||||
#define PIXEL_SIZE 1
|
||||
#define PIXEL BYTE
|
||||
#define WHITE_PIXEL 0xFF
|
||||
#define DESTWRITEPIXEL(_buf, _pix) \
|
||||
do \
|
||||
{ \
|
||||
write_pixel_8(_buf, _pix); \
|
||||
(_buf) += 1; \
|
||||
} while (0)
|
||||
#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0]
|
||||
#define SRCREADPIXEL(_pix, _buf) \
|
||||
do \
|
||||
{ \
|
||||
(_pix) = (_buf)[0]; \
|
||||
(_buf) += 1; \
|
||||
} while (0)
|
||||
|
||||
#define WRITEFGBGIMAGE WriteFgBgImage8to8
|
||||
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage8to8
|
||||
#define RLEDECOMPRESS RleDecompress8to8
|
||||
#define RLEEXTRA
|
||||
#undef ENSURE_CAPACITY
|
||||
#define ENSURE_CAPACITY(_start, _end, _size) ensure_capacity(_start, _end, _size, 1)
|
||||
#include "include/bitmap.h"
|
||||
|
||||
#undef DESTWRITEPIXEL
|
||||
#undef DESTREADPIXEL
|
||||
#undef SRCREADPIXEL
|
||||
#undef WRITEFGBGIMAGE
|
||||
#undef WRITEFIRSTLINEFGBGIMAGE
|
||||
#undef RLEDECOMPRESS
|
||||
#undef RLEEXTRA
|
||||
#undef WHITE_PIXEL
|
||||
#undef PIXEL_SIZE
|
||||
#undef PIXEL
|
||||
#define PIXEL_SIZE 2
|
||||
#define PIXEL UINT16
|
||||
#define WHITE_PIXEL 0xFFFF
|
||||
#define DESTWRITEPIXEL(_buf, _pix) \
|
||||
do \
|
||||
{ \
|
||||
write_pixel_16(_buf, _pix); \
|
||||
(_buf) += 2; \
|
||||
} while (0)
|
||||
#define DESTREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0]
|
||||
#define SRCREADPIXEL(_pix, _buf) \
|
||||
do \
|
||||
{ \
|
||||
(_pix) = WINPR_ASSERTING_INT_CAST(UINT16, (_buf)[0] | (((_buf)[1] << 8) & 0xFF00)); \
|
||||
(_buf) += 2; \
|
||||
} while (0)
|
||||
#define WRITEFGBGIMAGE WriteFgBgImage16to16
|
||||
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage16to16
|
||||
#define RLEDECOMPRESS RleDecompress16to16
|
||||
#define RLEEXTRA
|
||||
#undef ENSURE_CAPACITY
|
||||
#define ENSURE_CAPACITY(_start, _end, _size) ensure_capacity(_start, _end, _size, 2)
|
||||
#include "include/bitmap.h"
|
||||
|
||||
#undef DESTWRITEPIXEL
|
||||
#undef DESTREADPIXEL
|
||||
#undef SRCREADPIXEL
|
||||
#undef WRITEFGBGIMAGE
|
||||
#undef WRITEFIRSTLINEFGBGIMAGE
|
||||
#undef RLEDECOMPRESS
|
||||
#undef RLEEXTRA
|
||||
#undef WHITE_PIXEL
|
||||
#undef PIXEL_SIZE
|
||||
#undef PIXEL
|
||||
#define PIXEL_SIZE 3
|
||||
#define PIXEL UINT32
|
||||
#define WHITE_PIXEL 0xffffff
|
||||
#define DESTWRITEPIXEL(_buf, _pix) \
|
||||
do \
|
||||
{ \
|
||||
write_pixel_24(_buf, _pix); \
|
||||
(_buf) += 3; \
|
||||
} while (0)
|
||||
#define DESTREADPIXEL(_pix, _buf) \
|
||||
_pix = (_buf)[0] | (((_buf)[1] << 8) & 0xFF00) | (((_buf)[2] << 16) & 0xFF0000)
|
||||
#define SRCREADPIXEL(_pix, _buf) \
|
||||
do \
|
||||
{ \
|
||||
(_pix) = (_buf)[0] | (((_buf)[1] << 8) & 0xFF00) | (((_buf)[2] << 16) & 0xFF0000); \
|
||||
(_buf) += 3; \
|
||||
} while (0)
|
||||
|
||||
#define WRITEFGBGIMAGE WriteFgBgImage24to24
|
||||
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage24to24
|
||||
#define RLEDECOMPRESS RleDecompress24to24
|
||||
#define RLEEXTRA
|
||||
#undef ENSURE_CAPACITY
|
||||
#define ENSURE_CAPACITY(_start, _end, _size) ensure_capacity(_start, _end, _size, 3)
|
||||
#include "include/bitmap.h"
|
||||
|
||||
struct S_BITMAP_INTERLEAVED_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
|
||||
UINT32 TempSize;
|
||||
BYTE* TempBuffer;
|
||||
|
||||
wStream* bts;
|
||||
};
|
||||
|
||||
BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* WINPR_RESTRICT interleaved,
|
||||
const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize, UINT32 nSrcWidth,
|
||||
UINT32 nSrcHeight, UINT32 bpp, BYTE* WINPR_RESTRICT pDstData,
|
||||
UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
|
||||
UINT32 nDstWidth, UINT32 nDstHeight,
|
||||
const gdiPalette* WINPR_RESTRICT palette)
|
||||
{
|
||||
UINT32 scanline = 0;
|
||||
UINT32 SrcFormat = 0;
|
||||
UINT32 BufferSize = 0;
|
||||
|
||||
if (!interleaved || !pSrcData || !pDstData)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid arguments: interleaved=%p, pSrcData=%p, pDstData=%p",
|
||||
WINPR_CXX_COMPAT_CAST(const void*, interleaved),
|
||||
WINPR_CXX_COMPAT_CAST(const void*, pSrcData),
|
||||
WINPR_CXX_COMPAT_CAST(const void*, pDstData));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 24:
|
||||
scanline = nSrcWidth * 3;
|
||||
SrcFormat = PIXEL_FORMAT_BGR24;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
scanline = nSrcWidth * 2;
|
||||
SrcFormat = PIXEL_FORMAT_RGB16;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
scanline = nSrcWidth * 2;
|
||||
SrcFormat = PIXEL_FORMAT_RGB15;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
scanline = nSrcWidth;
|
||||
SrcFormat = PIXEL_FORMAT_RGB8;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Invalid color depth %" PRIu32 "", bpp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BufferSize = scanline * nSrcHeight;
|
||||
|
||||
if (BufferSize > interleaved->TempSize)
|
||||
{
|
||||
interleaved->TempBuffer =
|
||||
winpr_aligned_recalloc(interleaved->TempBuffer, BufferSize, sizeof(BYTE), 16);
|
||||
interleaved->TempSize = BufferSize;
|
||||
}
|
||||
|
||||
if (!interleaved->TempBuffer)
|
||||
{
|
||||
WLog_ERR(TAG, "interleaved->TempBuffer=nullptr");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 24:
|
||||
if (!RleDecompress24to24(pSrcData, SrcSize, interleaved->TempBuffer, scanline,
|
||||
nSrcWidth, nSrcHeight))
|
||||
{
|
||||
WLog_ERR(TAG, "RleDecompress24to24 failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 16:
|
||||
case 15:
|
||||
if (!RleDecompress16to16(pSrcData, SrcSize, interleaved->TempBuffer, scanline,
|
||||
nSrcWidth, nSrcHeight))
|
||||
{
|
||||
WLog_ERR(TAG, "RleDecompress16to16 failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (!RleDecompress8to8(pSrcData, SrcSize, interleaved->TempBuffer, scanline, nSrcWidth,
|
||||
nSrcHeight))
|
||||
{
|
||||
WLog_ERR(TAG, "RleDecompress8to8 failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Invalid color depth %" PRIu32 "", bpp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
|
||||
nDstHeight, interleaved->TempBuffer, SrcFormat, scanline, 0,
|
||||
0, palette, FREERDP_FLIP_VERTICAL | FREERDP_KEEP_DST_ALPHA))
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_image_copy failed");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* WINPR_RESTRICT interleaved,
|
||||
BYTE* WINPR_RESTRICT pDstData, UINT32* WINPR_RESTRICT pDstSize,
|
||||
UINT32 nWidth, UINT32 nHeight, const BYTE* WINPR_RESTRICT pSrcData,
|
||||
UINT32 SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
|
||||
const gdiPalette* WINPR_RESTRICT palette, UINT32 bpp)
|
||||
{
|
||||
BOOL status = 0;
|
||||
wStream* s = nullptr;
|
||||
UINT32 DstFormat = 0;
|
||||
const UINT32 maxSize = 64 * 64 * 4;
|
||||
|
||||
if (!interleaved || !pDstData || !pSrcData)
|
||||
return FALSE;
|
||||
|
||||
if ((nWidth == 0) || (nHeight == 0))
|
||||
return FALSE;
|
||||
|
||||
if (nWidth % 4)
|
||||
{
|
||||
WLog_ERR(TAG, "interleaved_compress: width is not a multiple of 4");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((nWidth > 64) || (nHeight > 64))
|
||||
{
|
||||
WLog_ERR(TAG,
|
||||
"interleaved_compress: width (%" PRIu32 ") or height (%" PRIu32
|
||||
") is greater than 64",
|
||||
nWidth, nHeight);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 24:
|
||||
DstFormat = PIXEL_FORMAT_BGRX32;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
DstFormat = PIXEL_FORMAT_RGB16;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
DstFormat = PIXEL_FORMAT_RGB15;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!freerdp_image_copy_no_overlap(interleaved->TempBuffer, DstFormat, 0, 0, 0, nWidth, nHeight,
|
||||
pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
|
||||
FREERDP_KEEP_DST_ALPHA))
|
||||
return FALSE;
|
||||
|
||||
s = Stream_New(pDstData, *pDstSize);
|
||||
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
Stream_ResetPosition(interleaved->bts);
|
||||
|
||||
status = (freerdp_bitmap_compress(interleaved->TempBuffer, nWidth, nHeight, s, bpp, maxSize,
|
||||
nHeight - 1, interleaved->bts, 0) >= 0);
|
||||
|
||||
Stream_SealLength(s);
|
||||
*pDstSize = (UINT32)Stream_Length(s);
|
||||
Stream_Free(s, FALSE);
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOL bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* WINPR_RESTRICT interleaved)
|
||||
{
|
||||
return (interleaved != nullptr);
|
||||
}
|
||||
|
||||
BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(WINPR_ATTR_UNUSED BOOL Compressor)
|
||||
{
|
||||
BITMAP_INTERLEAVED_CONTEXT* interleaved = nullptr;
|
||||
interleaved = (BITMAP_INTERLEAVED_CONTEXT*)winpr_aligned_recalloc(
|
||||
nullptr, 1, sizeof(BITMAP_INTERLEAVED_CONTEXT), 32);
|
||||
|
||||
if (interleaved)
|
||||
{
|
||||
interleaved->TempSize = 64 * 64 * 4;
|
||||
interleaved->TempBuffer = winpr_aligned_calloc(interleaved->TempSize, sizeof(BYTE), 16);
|
||||
|
||||
if (!interleaved->TempBuffer)
|
||||
goto fail;
|
||||
|
||||
interleaved->bts = Stream_New(nullptr, interleaved->TempSize);
|
||||
|
||||
if (!interleaved->bts)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return interleaved;
|
||||
|
||||
fail:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
bitmap_interleaved_context_free(interleaved);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* WINPR_RESTRICT interleaved)
|
||||
{
|
||||
if (!interleaved)
|
||||
return;
|
||||
|
||||
winpr_aligned_free(interleaved->TempBuffer);
|
||||
Stream_Free(interleaved->bts, TRUE);
|
||||
winpr_aligned_free(interleaved);
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Compressed jpeg
|
||||
*
|
||||
* Copyright 2012 Jay Sorg <jay.sorg@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 <freerdp/config.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/image.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include <freerdp/codec/jpeg.h>
|
||||
|
||||
#ifdef WITH_JPEG
|
||||
|
||||
/* jpeg decompress */
|
||||
BOOL jpeg_decompress(const BYTE* input, BYTE* output, int width, int height, int size, int bpp)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
|
||||
if (bpp != 24)
|
||||
return FALSE;
|
||||
|
||||
wImage* image = winpr_image_new();
|
||||
if (!image)
|
||||
goto fail;
|
||||
|
||||
if (winpr_image_read_buffer(image, input, size) <= 0)
|
||||
goto fail;
|
||||
|
||||
if ((image->width != width) || (image->height != height) || (image->bitsPerPixel != bpp))
|
||||
goto fail;
|
||||
|
||||
memcpy(output, image->data, 1ull * image->scanline * image->height);
|
||||
rc = TRUE;
|
||||
|
||||
fail:
|
||||
winpr_image_free(image, TRUE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BOOL jpeg_decompress(WINPR_ATTR_UNUSED const BYTE* input, WINPR_ATTR_UNUSED BYTE* output,
|
||||
WINPR_ATTR_UNUSED int width, WINPR_ATTR_UNUSED int height,
|
||||
WINPR_ATTR_UNUSED int size, WINPR_ATTR_UNUSED int bpp)
|
||||
{
|
||||
WLog_ERR("TODO", "TODO: implement");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
+860
@@ -0,0 +1,860 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* MPPC Bulk Data Compression
|
||||
*
|
||||
* Copyright 2014 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 <winpr/assert.h>
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include "mppc.h"
|
||||
|
||||
#define TAG FREERDP_TAG("codec.mppc")
|
||||
|
||||
//#define DEBUG_MPPC 1
|
||||
|
||||
#define MPPC_MATCH_INDEX(_sym1, _sym2, _sym3) \
|
||||
((((MPPC_MATCH_TABLE[_sym3] << 16) + (MPPC_MATCH_TABLE[_sym2] << 8) + \
|
||||
MPPC_MATCH_TABLE[_sym1]) & \
|
||||
0x07FFF000) >> \
|
||||
12)
|
||||
|
||||
struct s_MPPC_CONTEXT
|
||||
{
|
||||
ALIGN64 wBitStream* bs;
|
||||
ALIGN64 BOOL Compressor;
|
||||
ALIGN64 BYTE* HistoryPtr;
|
||||
ALIGN64 UINT32 HistoryOffset;
|
||||
ALIGN64 UINT32 HistoryBufferSize;
|
||||
ALIGN64 BYTE HistoryBuffer[65536];
|
||||
ALIGN64 UINT16 MatchBuffer[32768];
|
||||
ALIGN64 UINT32 CompressionLevel;
|
||||
};
|
||||
|
||||
static const UINT32 MPPC_MATCH_TABLE[256] = {
|
||||
0x00000000, 0x009CCF93, 0x01399F26, 0x01D66EB9, 0x02733E4C, 0x03100DDF, 0x03ACDD72, 0x0449AD05,
|
||||
0x04E67C98, 0x05834C2B, 0x06201BBE, 0x06BCEB51, 0x0759BAE4, 0x07F68A77, 0x08935A0A, 0x0930299D,
|
||||
0x09CCF930, 0x0A69C8C3, 0x0B069856, 0x0BA367E9, 0x0C40377C, 0x0CDD070F, 0x0D79D6A2, 0x0E16A635,
|
||||
0x0EB375C8, 0x0F50455B, 0x0FED14EE, 0x1089E481, 0x1126B414, 0x11C383A7, 0x1260533A, 0x12FD22CD,
|
||||
0x1399F260, 0x1436C1F3, 0x14D39186, 0x15706119, 0x160D30AC, 0x16AA003F, 0x1746CFD2, 0x17E39F65,
|
||||
0x18806EF8, 0x191D3E8B, 0x19BA0E1E, 0x1A56DDB1, 0x1AF3AD44, 0x1B907CD7, 0x1C2D4C6A, 0x1CCA1BFD,
|
||||
0x1D66EB90, 0x1E03BB23, 0x1EA08AB6, 0x1F3D5A49, 0x1FDA29DC, 0x2076F96F, 0x2113C902, 0x21B09895,
|
||||
0x224D6828, 0x22EA37BB, 0x2387074E, 0x2423D6E1, 0x24C0A674, 0x255D7607, 0x25FA459A, 0x2697152D,
|
||||
0x2733E4C0, 0x27D0B453, 0x286D83E6, 0x290A5379, 0x29A7230C, 0x2A43F29F, 0x2AE0C232, 0x2B7D91C5,
|
||||
0x2C1A6158, 0x2CB730EB, 0x2D54007E, 0x2DF0D011, 0x2E8D9FA4, 0x2F2A6F37, 0x2FC73ECA, 0x30640E5D,
|
||||
0x3100DDF0, 0x319DAD83, 0x323A7D16, 0x32D74CA9, 0x33741C3C, 0x3410EBCF, 0x34ADBB62, 0x354A8AF5,
|
||||
0x35E75A88, 0x36842A1B, 0x3720F9AE, 0x37BDC941, 0x385A98D4, 0x38F76867, 0x399437FA, 0x3A31078D,
|
||||
0x3ACDD720, 0x3B6AA6B3, 0x3C077646, 0x3CA445D9, 0x3D41156C, 0x3DDDE4FF, 0x3E7AB492, 0x3F178425,
|
||||
0x3FB453B8, 0x4051234B, 0x40EDF2DE, 0x418AC271, 0x42279204, 0x42C46197, 0x4361312A, 0x43FE00BD,
|
||||
0x449AD050, 0x45379FE3, 0x45D46F76, 0x46713F09, 0x470E0E9C, 0x47AADE2F, 0x4847ADC2, 0x48E47D55,
|
||||
0x49814CE8, 0x4A1E1C7B, 0x4ABAEC0E, 0x4B57BBA1, 0x4BF48B34, 0x4C915AC7, 0x4D2E2A5A, 0x4DCAF9ED,
|
||||
0x4E67C980, 0x4F049913, 0x4FA168A6, 0x503E3839, 0x50DB07CC, 0x5177D75F, 0x5214A6F2, 0x52B17685,
|
||||
0x534E4618, 0x53EB15AB, 0x5487E53E, 0x5524B4D1, 0x55C18464, 0x565E53F7, 0x56FB238A, 0x5797F31D,
|
||||
0x5834C2B0, 0x58D19243, 0x596E61D6, 0x5A0B3169, 0x5AA800FC, 0x5B44D08F, 0x5BE1A022, 0x5C7E6FB5,
|
||||
0x5D1B3F48, 0x5DB80EDB, 0x5E54DE6E, 0x5EF1AE01, 0x5F8E7D94, 0x602B4D27, 0x60C81CBA, 0x6164EC4D,
|
||||
0x6201BBE0, 0x629E8B73, 0x633B5B06, 0x63D82A99, 0x6474FA2C, 0x6511C9BF, 0x65AE9952, 0x664B68E5,
|
||||
0x66E83878, 0x6785080B, 0x6821D79E, 0x68BEA731, 0x695B76C4, 0x69F84657, 0x6A9515EA, 0x6B31E57D,
|
||||
0x6BCEB510, 0x6C6B84A3, 0x6D085436, 0x6DA523C9, 0x6E41F35C, 0x6EDEC2EF, 0x6F7B9282, 0x70186215,
|
||||
0x70B531A8, 0x7152013B, 0x71EED0CE, 0x728BA061, 0x73286FF4, 0x73C53F87, 0x74620F1A, 0x74FEDEAD,
|
||||
0x759BAE40, 0x76387DD3, 0x76D54D66, 0x77721CF9, 0x780EEC8C, 0x78ABBC1F, 0x79488BB2, 0x79E55B45,
|
||||
0x7A822AD8, 0x7B1EFA6B, 0x7BBBC9FE, 0x7C589991, 0x7CF56924, 0x7D9238B7, 0x7E2F084A, 0x7ECBD7DD,
|
||||
0x7F68A770, 0x80057703, 0x80A24696, 0x813F1629, 0x81DBE5BC, 0x8278B54F, 0x831584E2, 0x83B25475,
|
||||
0x844F2408, 0x84EBF39B, 0x8588C32E, 0x862592C1, 0x86C26254, 0x875F31E7, 0x87FC017A, 0x8898D10D,
|
||||
0x8935A0A0, 0x89D27033, 0x8A6F3FC6, 0x8B0C0F59, 0x8BA8DEEC, 0x8C45AE7F, 0x8CE27E12, 0x8D7F4DA5,
|
||||
0x8E1C1D38, 0x8EB8ECCB, 0x8F55BC5E, 0x8FF28BF1, 0x908F5B84, 0x912C2B17, 0x91C8FAAA, 0x9265CA3D,
|
||||
0x930299D0, 0x939F6963, 0x943C38F6, 0x94D90889, 0x9575D81C, 0x9612A7AF, 0x96AF7742, 0x974C46D5,
|
||||
0x97E91668, 0x9885E5FB, 0x9922B58E, 0x99BF8521, 0x9A5C54B4, 0x9AF92447, 0x9B95F3DA, 0x9C32C36D
|
||||
};
|
||||
|
||||
int mppc_decompress(MPPC_CONTEXT* mppc, const BYTE* pSrcData, UINT32 SrcSize,
|
||||
const BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
|
||||
{
|
||||
BYTE Literal = 0;
|
||||
BYTE* SrcPtr = nullptr;
|
||||
UINT32 CopyOffset = 0;
|
||||
UINT32 LengthOfMatch = 0;
|
||||
UINT32 accumulator = 0;
|
||||
BYTE* HistoryPtr = nullptr;
|
||||
BYTE* HistoryBuffer = nullptr;
|
||||
BYTE* HistoryBufferEnd = nullptr;
|
||||
UINT32 HistoryBufferSize = 0;
|
||||
UINT32 CompressionLevel = 0;
|
||||
wBitStream* bs = nullptr;
|
||||
|
||||
WINPR_ASSERT(mppc);
|
||||
WINPR_ASSERT(pSrcData);
|
||||
WINPR_ASSERT(ppDstData);
|
||||
WINPR_ASSERT(pDstSize);
|
||||
|
||||
bs = mppc->bs;
|
||||
WINPR_ASSERT(bs);
|
||||
|
||||
HistoryBuffer = mppc->HistoryBuffer;
|
||||
WINPR_ASSERT(HistoryBuffer);
|
||||
|
||||
HistoryBufferSize = mppc->HistoryBufferSize;
|
||||
HistoryBufferEnd = &HistoryBuffer[HistoryBufferSize - 1];
|
||||
CompressionLevel = mppc->CompressionLevel;
|
||||
BitStream_Attach(bs, pSrcData, SrcSize);
|
||||
BitStream_Fetch(bs);
|
||||
|
||||
if (flags & PACKET_AT_FRONT)
|
||||
{
|
||||
mppc->HistoryOffset = 0;
|
||||
mppc->HistoryPtr = HistoryBuffer;
|
||||
}
|
||||
|
||||
if (flags & PACKET_FLUSHED)
|
||||
{
|
||||
mppc->HistoryOffset = 0;
|
||||
mppc->HistoryPtr = HistoryBuffer;
|
||||
ZeroMemory(HistoryBuffer, mppc->HistoryBufferSize);
|
||||
}
|
||||
|
||||
HistoryPtr = mppc->HistoryPtr;
|
||||
|
||||
if (!(flags & PACKET_COMPRESSED))
|
||||
{
|
||||
*pDstSize = SrcSize;
|
||||
*ppDstData = pSrcData;
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((bs->length - bs->position) >= 8)
|
||||
{
|
||||
accumulator = bs->accumulator;
|
||||
|
||||
/**
|
||||
* Literal Encoding
|
||||
*/
|
||||
|
||||
if (HistoryPtr > HistoryBufferEnd)
|
||||
{
|
||||
WLog_ERR(TAG, "history buffer index out of range");
|
||||
return -1004;
|
||||
}
|
||||
|
||||
if ((accumulator & 0x80000000) == 0x00000000)
|
||||
{
|
||||
/**
|
||||
* Literal, less than 0x80
|
||||
* bit 0 followed by the lower 7 bits of the literal
|
||||
*/
|
||||
Literal = ((accumulator & 0x7F000000) >> 24);
|
||||
*(HistoryPtr) = Literal;
|
||||
HistoryPtr++;
|
||||
BitStream_Shift(bs, 8);
|
||||
continue;
|
||||
}
|
||||
else if ((accumulator & 0xC0000000) == 0x80000000)
|
||||
{
|
||||
/**
|
||||
* Literal, greater than 0x7F
|
||||
* bits 10 followed by the lower 7 bits of the literal
|
||||
*/
|
||||
Literal = ((accumulator & 0x3F800000) >> 23) + 0x80;
|
||||
*(HistoryPtr) = Literal;
|
||||
HistoryPtr++;
|
||||
BitStream_Shift(bs, 9);
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* CopyOffset Encoding
|
||||
*/
|
||||
if (CompressionLevel) /* RDP5 */
|
||||
{
|
||||
if ((accumulator & 0xF8000000) == 0xF8000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [0, 63]
|
||||
* bits 11111 + lower 6 bits of CopyOffset
|
||||
*/
|
||||
CopyOffset = ((accumulator >> 21) & 0x3F);
|
||||
BitStream_Shift(bs, 11);
|
||||
}
|
||||
else if ((accumulator & 0xF8000000) == 0xF0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [64, 319]
|
||||
* bits 11110 + lower 8 bits of (CopyOffset - 64)
|
||||
*/
|
||||
CopyOffset = ((accumulator >> 19) & 0xFF) + 64;
|
||||
BitStream_Shift(bs, 13);
|
||||
}
|
||||
else if ((accumulator & 0xF0000000) == 0xE0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [320, 2367]
|
||||
* bits 1110 + lower 11 bits of (CopyOffset - 320)
|
||||
*/
|
||||
CopyOffset = ((accumulator >> 17) & 0x7FF) + 320;
|
||||
BitStream_Shift(bs, 15);
|
||||
}
|
||||
else if ((accumulator & 0xE0000000) == 0xC0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [2368, ]
|
||||
* bits 110 + lower 16 bits of (CopyOffset - 2368)
|
||||
*/
|
||||
CopyOffset = ((accumulator >> 13) & 0xFFFF) + 2368;
|
||||
BitStream_Shift(bs, 19);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid CopyOffset Encoding */
|
||||
return -1001;
|
||||
}
|
||||
}
|
||||
else /* RDP4 */
|
||||
{
|
||||
if ((accumulator & 0xF0000000) == 0xF0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [0, 63]
|
||||
* bits 1111 + lower 6 bits of CopyOffset
|
||||
*/
|
||||
CopyOffset = ((accumulator >> 22) & 0x3F);
|
||||
BitStream_Shift(bs, 10);
|
||||
}
|
||||
else if ((accumulator & 0xF0000000) == 0xE0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [64, 319]
|
||||
* bits 1110 + lower 8 bits of (CopyOffset - 64)
|
||||
*/
|
||||
CopyOffset = ((accumulator >> 20) & 0xFF) + 64;
|
||||
BitStream_Shift(bs, 12);
|
||||
}
|
||||
else if ((accumulator & 0xE0000000) == 0xC0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [320, 8191]
|
||||
* bits 110 + lower 13 bits of (CopyOffset - 320)
|
||||
*/
|
||||
CopyOffset = ((accumulator >> 16) & 0x1FFF) + 320;
|
||||
BitStream_Shift(bs, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid CopyOffset Encoding */
|
||||
return -1002;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* LengthOfMatch Encoding
|
||||
*/
|
||||
accumulator = bs->accumulator;
|
||||
|
||||
if ((accumulator & 0x80000000) == 0x00000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [3]
|
||||
* bit 0 + 0 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = 3;
|
||||
BitStream_Shift(bs, 1);
|
||||
}
|
||||
else if ((accumulator & 0xC0000000) == 0x80000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [4, 7]
|
||||
* bits 10 + 2 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 28) & 0x0003) + 0x0004;
|
||||
BitStream_Shift(bs, 4);
|
||||
}
|
||||
else if ((accumulator & 0xE0000000) == 0xC0000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [8, 15]
|
||||
* bits 110 + 3 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 26) & 0x0007) + 0x0008;
|
||||
BitStream_Shift(bs, 6);
|
||||
}
|
||||
else if ((accumulator & 0xF0000000) == 0xE0000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [16, 31]
|
||||
* bits 1110 + 4 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 24) & 0x000F) + 0x0010;
|
||||
BitStream_Shift(bs, 8);
|
||||
}
|
||||
else if ((accumulator & 0xF8000000) == 0xF0000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [32, 63]
|
||||
* bits 11110 + 5 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 22) & 0x001F) + 0x0020;
|
||||
BitStream_Shift(bs, 10);
|
||||
}
|
||||
else if ((accumulator & 0xFC000000) == 0xF8000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [64, 127]
|
||||
* bits 111110 + 6 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 20) & 0x003F) + 0x0040;
|
||||
BitStream_Shift(bs, 12);
|
||||
}
|
||||
else if ((accumulator & 0xFE000000) == 0xFC000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [128, 255]
|
||||
* bits 1111110 + 7 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 18) & 0x007F) + 0x0080;
|
||||
BitStream_Shift(bs, 14);
|
||||
}
|
||||
else if ((accumulator & 0xFF000000) == 0xFE000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [256, 511]
|
||||
* bits 11111110 + 8 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 16) & 0x00FF) + 0x0100;
|
||||
BitStream_Shift(bs, 16);
|
||||
}
|
||||
else if ((accumulator & 0xFF800000) == 0xFF000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [512, 1023]
|
||||
* bits 111111110 + 9 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 14) & 0x01FF) + 0x0200;
|
||||
BitStream_Shift(bs, 18);
|
||||
}
|
||||
else if ((accumulator & 0xFFC00000) == 0xFF800000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [1024, 2047]
|
||||
* bits 1111111110 + 10 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 12) & 0x03FF) + 0x0400;
|
||||
BitStream_Shift(bs, 20);
|
||||
}
|
||||
else if ((accumulator & 0xFFE00000) == 0xFFC00000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [2048, 4095]
|
||||
* bits 11111111110 + 11 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 10) & 0x07FF) + 0x0800;
|
||||
BitStream_Shift(bs, 22);
|
||||
}
|
||||
else if ((accumulator & 0xFFF00000) == 0xFFE00000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [4096, 8191]
|
||||
* bits 111111111110 + 12 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 8) & 0x0FFF) + 0x1000;
|
||||
BitStream_Shift(bs, 24);
|
||||
}
|
||||
else if (((accumulator & 0xFFF80000) == 0xFFF00000) && CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [8192, 16383]
|
||||
* bits 1111111111110 + 13 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 6) & 0x1FFF) + 0x2000;
|
||||
BitStream_Shift(bs, 26);
|
||||
}
|
||||
else if (((accumulator & 0xFFFC0000) == 0xFFF80000) && CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [16384, 32767]
|
||||
* bits 11111111111110 + 14 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 4) & 0x3FFF) + 0x4000;
|
||||
BitStream_Shift(bs, 28);
|
||||
}
|
||||
else if (((accumulator & 0xFFFE0000) == 0xFFFC0000) && CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [32768, 65535]
|
||||
* bits 111111111111110 + 15 lower bits of LengthOfMatch
|
||||
*/
|
||||
LengthOfMatch = ((accumulator >> 2) & 0x7FFF) + 0x8000;
|
||||
BitStream_Shift(bs, 30);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid LengthOfMatch Encoding */
|
||||
return -1003;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_MPPC)
|
||||
WLog_DBG(TAG, "<%" PRIu32 ",%" PRIu32 ">", CopyOffset, LengthOfMatch);
|
||||
#endif
|
||||
|
||||
if ((HistoryPtr + LengthOfMatch - 1) > HistoryBufferEnd)
|
||||
{
|
||||
WLog_ERR(TAG, "history buffer overflow");
|
||||
return -1005;
|
||||
}
|
||||
|
||||
SrcPtr = &HistoryBuffer[(HistoryPtr - HistoryBuffer - CopyOffset) &
|
||||
(CompressionLevel ? 0xFFFF : 0x1FFF)];
|
||||
|
||||
do
|
||||
{
|
||||
*HistoryPtr++ = *SrcPtr++;
|
||||
} while (--LengthOfMatch);
|
||||
}
|
||||
|
||||
*pDstSize = (UINT32)(HistoryPtr - mppc->HistoryPtr);
|
||||
*ppDstData = mppc->HistoryPtr;
|
||||
mppc->HistoryPtr = HistoryPtr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mppc_compress(MPPC_CONTEXT* mppc, const BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstBuffer,
|
||||
const BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)
|
||||
{
|
||||
const BYTE* pSrcPtr = nullptr;
|
||||
const BYTE* pSrcEnd = nullptr;
|
||||
BYTE* MatchPtr = nullptr;
|
||||
UINT32 DstSize = 0;
|
||||
BYTE* pDstData = nullptr;
|
||||
UINT32 MatchIndex = 0;
|
||||
UINT32 accumulator = 0;
|
||||
BOOL PacketFlushed = 0;
|
||||
BOOL PacketAtFront = 0;
|
||||
DWORD CopyOffset = 0;
|
||||
DWORD LengthOfMatch = 0;
|
||||
BYTE* HistoryBuffer = nullptr;
|
||||
BYTE* HistoryPtr = nullptr;
|
||||
UINT32 HistoryOffset = 0;
|
||||
UINT32 HistoryBufferSize = 0;
|
||||
BYTE Sym1 = 0;
|
||||
BYTE Sym2 = 0;
|
||||
BYTE Sym3 = 0;
|
||||
UINT32 CompressionLevel = 0;
|
||||
wBitStream* bs = nullptr;
|
||||
|
||||
WINPR_ASSERT(mppc);
|
||||
WINPR_ASSERT(pSrcData);
|
||||
WINPR_ASSERT(pDstBuffer);
|
||||
WINPR_ASSERT(ppDstData);
|
||||
WINPR_ASSERT(pDstSize);
|
||||
WINPR_ASSERT(pFlags);
|
||||
|
||||
bs = mppc->bs;
|
||||
WINPR_ASSERT(bs);
|
||||
|
||||
HistoryBuffer = mppc->HistoryBuffer;
|
||||
WINPR_ASSERT(HistoryBuffer);
|
||||
|
||||
HistoryBufferSize = mppc->HistoryBufferSize;
|
||||
CompressionLevel = mppc->CompressionLevel;
|
||||
HistoryOffset = mppc->HistoryOffset;
|
||||
*pFlags = 0;
|
||||
PacketFlushed = FALSE;
|
||||
|
||||
if (((HistoryOffset + SrcSize) < (HistoryBufferSize - 3)) && HistoryOffset)
|
||||
{
|
||||
PacketAtFront = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HistoryOffset == (HistoryBufferSize + 1))
|
||||
PacketFlushed = TRUE;
|
||||
|
||||
HistoryOffset = 0;
|
||||
PacketAtFront = TRUE;
|
||||
}
|
||||
|
||||
HistoryPtr = &(HistoryBuffer[HistoryOffset]);
|
||||
pDstData = pDstBuffer;
|
||||
*ppDstData = pDstBuffer;
|
||||
|
||||
if (!pDstData)
|
||||
return -1;
|
||||
|
||||
if (*pDstSize > SrcSize)
|
||||
DstSize = SrcSize;
|
||||
else
|
||||
DstSize = *pDstSize;
|
||||
|
||||
BitStream_Attach(bs, pDstData, DstSize);
|
||||
pSrcPtr = pSrcData;
|
||||
pSrcEnd = &(pSrcData[SrcSize - 1]);
|
||||
|
||||
while (pSrcPtr < (pSrcEnd - 2))
|
||||
{
|
||||
Sym1 = pSrcPtr[0];
|
||||
Sym2 = pSrcPtr[1];
|
||||
Sym3 = pSrcPtr[2];
|
||||
*HistoryPtr++ = *pSrcPtr++;
|
||||
MatchIndex = MPPC_MATCH_INDEX(Sym1, Sym2, Sym3);
|
||||
MatchPtr = &(HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
|
||||
|
||||
if (MatchPtr != (HistoryPtr - 1))
|
||||
mppc->MatchBuffer[MatchIndex] = (UINT16)(HistoryPtr - HistoryBuffer);
|
||||
|
||||
if (mppc->HistoryPtr < HistoryPtr)
|
||||
mppc->HistoryPtr = HistoryPtr;
|
||||
|
||||
if ((Sym1 != *(MatchPtr - 1)) || (Sym2 != MatchPtr[0]) || (Sym3 != MatchPtr[1]) ||
|
||||
(&MatchPtr[1] > mppc->HistoryPtr) || (MatchPtr == HistoryBuffer) ||
|
||||
(MatchPtr == (HistoryPtr - 1)) || (MatchPtr == HistoryPtr))
|
||||
{
|
||||
if (((bs->position / 8) + 2) > (DstSize - 1))
|
||||
{
|
||||
mppc_context_reset(mppc, TRUE);
|
||||
*pFlags |= PACKET_FLUSHED;
|
||||
*pFlags |= CompressionLevel;
|
||||
*ppDstData = pSrcData;
|
||||
*pDstSize = SrcSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
accumulator = Sym1;
|
||||
#if defined(DEBUG_MPPC)
|
||||
WLog_DBG(TAG, "%" PRIu32 "", accumulator);
|
||||
#endif
|
||||
|
||||
if (accumulator < 0x80)
|
||||
{
|
||||
/* 8 bits of literal are encoded as-is */
|
||||
BitStream_Write_Bits(bs, accumulator, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bits 10 followed by lower 7 bits of literal */
|
||||
accumulator = 0x100 | (accumulator & 0x7F);
|
||||
BitStream_Write_Bits(bs, accumulator, 9);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyOffset = (HistoryBufferSize - 1) & (HistoryPtr - MatchPtr);
|
||||
*HistoryPtr++ = Sym2;
|
||||
*HistoryPtr++ = Sym3;
|
||||
pSrcPtr += 2;
|
||||
LengthOfMatch = 3;
|
||||
MatchPtr += 2;
|
||||
|
||||
while ((*pSrcPtr == *MatchPtr) && (pSrcPtr < pSrcEnd) && (MatchPtr <= mppc->HistoryPtr))
|
||||
{
|
||||
MatchPtr++;
|
||||
*HistoryPtr++ = *pSrcPtr++;
|
||||
LengthOfMatch++;
|
||||
}
|
||||
|
||||
#if defined(DEBUG_MPPC)
|
||||
WLog_DBG(TAG, "<%" PRIu32 ",%" PRIu32 ">", CopyOffset, LengthOfMatch);
|
||||
#endif
|
||||
|
||||
/* Encode CopyOffset */
|
||||
|
||||
if (((bs->position / 8) + 7) > (DstSize - 1))
|
||||
{
|
||||
mppc_context_reset(mppc, TRUE);
|
||||
*pFlags |= PACKET_FLUSHED;
|
||||
*pFlags |= CompressionLevel;
|
||||
*ppDstData = pSrcData;
|
||||
*pDstSize = SrcSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (CompressionLevel) /* RDP5 */
|
||||
{
|
||||
if (CopyOffset < 64)
|
||||
{
|
||||
/* bits 11111 + lower 6 bits of CopyOffset */
|
||||
accumulator = 0x07C0 | (CopyOffset & 0x003F);
|
||||
BitStream_Write_Bits(bs, accumulator, 11);
|
||||
}
|
||||
else if ((CopyOffset >= 64) && (CopyOffset < 320))
|
||||
{
|
||||
/* bits 11110 + lower 8 bits of (CopyOffset - 64) */
|
||||
accumulator = 0x1E00 | ((CopyOffset - 64) & 0x00FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 13);
|
||||
}
|
||||
else if ((CopyOffset >= 320) && (CopyOffset < 2368))
|
||||
{
|
||||
/* bits 1110 + lower 11 bits of (CopyOffset - 320) */
|
||||
accumulator = 0x7000 | ((CopyOffset - 320) & 0x07FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bits 110 + lower 16 bits of (CopyOffset - 2368) */
|
||||
accumulator = 0x060000 | ((CopyOffset - 2368) & 0xFFFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 19);
|
||||
}
|
||||
}
|
||||
else /* RDP4 */
|
||||
{
|
||||
if (CopyOffset < 64)
|
||||
{
|
||||
/* bits 1111 + lower 6 bits of CopyOffset */
|
||||
accumulator = 0x03C0 | (CopyOffset & 0x003F);
|
||||
BitStream_Write_Bits(bs, accumulator, 10);
|
||||
}
|
||||
else if ((CopyOffset >= 64) && (CopyOffset < 320))
|
||||
{
|
||||
/* bits 1110 + lower 8 bits of (CopyOffset - 64) */
|
||||
accumulator = 0x0E00 | ((CopyOffset - 64) & 0x00FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 12);
|
||||
}
|
||||
else if ((CopyOffset >= 320) && (CopyOffset < 8192))
|
||||
{
|
||||
/* bits 110 + lower 13 bits of (CopyOffset - 320) */
|
||||
accumulator = 0xC000 | ((CopyOffset - 320) & 0x1FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 16);
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode LengthOfMatch */
|
||||
|
||||
if (LengthOfMatch == 3)
|
||||
{
|
||||
/* 0 + 0 lower bits of LengthOfMatch */
|
||||
BitStream_Write_Bits(bs, 0, 1);
|
||||
}
|
||||
else if ((LengthOfMatch >= 4) && (LengthOfMatch < 8))
|
||||
{
|
||||
/* 10 + 2 lower bits of LengthOfMatch */
|
||||
accumulator = 0x0008 | (LengthOfMatch & 0x0003);
|
||||
BitStream_Write_Bits(bs, accumulator, 4);
|
||||
}
|
||||
else if ((LengthOfMatch >= 8) && (LengthOfMatch < 16))
|
||||
{
|
||||
/* 110 + 3 lower bits of LengthOfMatch */
|
||||
accumulator = 0x0030 | (LengthOfMatch & 0x0007);
|
||||
BitStream_Write_Bits(bs, accumulator, 6);
|
||||
}
|
||||
else if ((LengthOfMatch >= 16) && (LengthOfMatch < 32))
|
||||
{
|
||||
/* 1110 + 4 lower bits of LengthOfMatch */
|
||||
accumulator = 0x00E0 | (LengthOfMatch & 0x000F);
|
||||
BitStream_Write_Bits(bs, accumulator, 8);
|
||||
}
|
||||
else if ((LengthOfMatch >= 32) && (LengthOfMatch < 64))
|
||||
{
|
||||
/* 11110 + 5 lower bits of LengthOfMatch */
|
||||
accumulator = 0x03C0 | (LengthOfMatch & 0x001F);
|
||||
BitStream_Write_Bits(bs, accumulator, 10);
|
||||
}
|
||||
else if ((LengthOfMatch >= 64) && (LengthOfMatch < 128))
|
||||
{
|
||||
/* 111110 + 6 lower bits of LengthOfMatch */
|
||||
accumulator = 0x0F80 | (LengthOfMatch & 0x003F);
|
||||
BitStream_Write_Bits(bs, accumulator, 12);
|
||||
}
|
||||
else if ((LengthOfMatch >= 128) && (LengthOfMatch < 256))
|
||||
{
|
||||
/* 1111110 + 7 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3F00 | (LengthOfMatch & 0x007F);
|
||||
BitStream_Write_Bits(bs, accumulator, 14);
|
||||
}
|
||||
else if ((LengthOfMatch >= 256) && (LengthOfMatch < 512))
|
||||
{
|
||||
/* 11111110 + 8 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFE00 | (LengthOfMatch & 0x00FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 16);
|
||||
}
|
||||
else if ((LengthOfMatch >= 512) && (LengthOfMatch < 1024))
|
||||
{
|
||||
/* 111111110 + 9 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FC00 | (LengthOfMatch & 0x01FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 18);
|
||||
}
|
||||
else if ((LengthOfMatch >= 1024) && (LengthOfMatch < 2048))
|
||||
{
|
||||
/* 1111111110 + 10 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFF800 | (LengthOfMatch & 0x03FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 20);
|
||||
}
|
||||
else if ((LengthOfMatch >= 2048) && (LengthOfMatch < 4096))
|
||||
{
|
||||
/* 11111111110 + 11 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FF000 | (LengthOfMatch & 0x07FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 22);
|
||||
}
|
||||
else if ((LengthOfMatch >= 4096) && (LengthOfMatch < 8192))
|
||||
{
|
||||
/* 111111111110 + 12 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFFE000 | (LengthOfMatch & 0x0FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 24);
|
||||
}
|
||||
else if (((LengthOfMatch >= 8192) && (LengthOfMatch < 16384)) &&
|
||||
CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/* 1111111111110 + 13 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FFC000 | (LengthOfMatch & 0x1FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 26);
|
||||
}
|
||||
else if (((LengthOfMatch >= 16384) && (LengthOfMatch < 32768)) &&
|
||||
CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/* 11111111111110 + 14 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFFF8000 | (LengthOfMatch & 0x3FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 28);
|
||||
}
|
||||
else if (((LengthOfMatch >= 32768) && (LengthOfMatch < 65536)) &&
|
||||
CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/* 111111111111110 + 15 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FFF0000 | (LengthOfMatch & 0x7FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode trailing symbols as literals */
|
||||
|
||||
while (pSrcPtr <= pSrcEnd)
|
||||
{
|
||||
if (((bs->position / 8) + 2) > (DstSize - 1))
|
||||
{
|
||||
mppc_context_reset(mppc, TRUE);
|
||||
*pFlags |= PACKET_FLUSHED;
|
||||
*pFlags |= CompressionLevel;
|
||||
*ppDstData = pSrcData;
|
||||
*pDstSize = SrcSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
accumulator = *pSrcPtr;
|
||||
#if defined(DEBUG_MPPC)
|
||||
WLog_DBG(TAG, "%" PRIu32 "", accumulator);
|
||||
#endif
|
||||
|
||||
if (accumulator < 0x80)
|
||||
{
|
||||
/* 8 bits of literal are encoded as-is */
|
||||
BitStream_Write_Bits(bs, accumulator, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bits 10 followed by lower 7 bits of literal */
|
||||
accumulator = 0x100 | (accumulator & 0x7F);
|
||||
BitStream_Write_Bits(bs, accumulator, 9);
|
||||
}
|
||||
|
||||
*HistoryPtr++ = *pSrcPtr++;
|
||||
}
|
||||
|
||||
BitStream_Flush(bs);
|
||||
*pFlags |= PACKET_COMPRESSED;
|
||||
*pFlags |= CompressionLevel;
|
||||
|
||||
if (PacketAtFront)
|
||||
*pFlags |= PACKET_AT_FRONT;
|
||||
|
||||
if (PacketFlushed)
|
||||
*pFlags |= PACKET_FLUSHED;
|
||||
|
||||
*pDstSize = ((bs->position + 7) / 8);
|
||||
mppc->HistoryPtr = HistoryPtr;
|
||||
const intptr_t diff = HistoryPtr - HistoryBuffer;
|
||||
if (diff > UINT32_MAX)
|
||||
return -1;
|
||||
mppc->HistoryOffset = (UINT32)diff;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void mppc_set_compression_level(MPPC_CONTEXT* mppc, DWORD CompressionLevel)
|
||||
{
|
||||
WINPR_ASSERT(mppc);
|
||||
|
||||
if (CompressionLevel < 1)
|
||||
{
|
||||
mppc->CompressionLevel = 0;
|
||||
mppc->HistoryBufferSize = 8192;
|
||||
}
|
||||
else
|
||||
{
|
||||
mppc->CompressionLevel = 1;
|
||||
mppc->HistoryBufferSize = 65536;
|
||||
}
|
||||
}
|
||||
|
||||
void mppc_context_reset(MPPC_CONTEXT* mppc, BOOL flush)
|
||||
{
|
||||
WINPR_ASSERT(mppc);
|
||||
|
||||
ZeroMemory(&(mppc->HistoryBuffer), sizeof(mppc->HistoryBuffer));
|
||||
ZeroMemory(&(mppc->MatchBuffer), sizeof(mppc->MatchBuffer));
|
||||
|
||||
if (flush)
|
||||
{
|
||||
mppc->HistoryOffset = mppc->HistoryBufferSize + 1;
|
||||
mppc->HistoryPtr = mppc->HistoryBuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
mppc->HistoryOffset = 0;
|
||||
mppc->HistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryOffset]);
|
||||
}
|
||||
}
|
||||
|
||||
MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor)
|
||||
{
|
||||
MPPC_CONTEXT* mppc = calloc(1, sizeof(MPPC_CONTEXT));
|
||||
|
||||
if (!mppc)
|
||||
goto fail;
|
||||
|
||||
mppc->Compressor = Compressor;
|
||||
|
||||
if (CompressionLevel < 1)
|
||||
{
|
||||
mppc->CompressionLevel = 0;
|
||||
mppc->HistoryBufferSize = 8192;
|
||||
}
|
||||
else
|
||||
{
|
||||
mppc->CompressionLevel = 1;
|
||||
mppc->HistoryBufferSize = 65536;
|
||||
}
|
||||
|
||||
mppc->bs = BitStream_New();
|
||||
|
||||
if (!mppc->bs)
|
||||
goto fail;
|
||||
|
||||
mppc_context_reset(mppc, FALSE);
|
||||
|
||||
return mppc;
|
||||
|
||||
fail:
|
||||
mppc_context_free(mppc);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void mppc_context_free(MPPC_CONTEXT* mppc)
|
||||
{
|
||||
if (mppc)
|
||||
{
|
||||
BitStream_Free(mppc->bs);
|
||||
free(mppc);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* MPPC Bulk Data Compression
|
||||
*
|
||||
* Copyright 2014 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 FREERDP_MPPC_H
|
||||
#define FREERDP_MPPC_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/codec/bulk.h>
|
||||
|
||||
typedef struct s_MPPC_CONTEXT MPPC_CONTEXT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int mppc_compress(MPPC_CONTEXT* mppc, const BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE* pDstBuffer, const BYTE** ppDstData, UINT32* pDstSize,
|
||||
UINT32* pFlags);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int mppc_decompress(MPPC_CONTEXT* mppc, const BYTE* pSrcData, UINT32 SrcSize,
|
||||
const BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
|
||||
|
||||
FREERDP_LOCAL void mppc_set_compression_level(MPPC_CONTEXT* mppc, DWORD CompressionLevel);
|
||||
|
||||
FREERDP_LOCAL void mppc_context_reset(MPPC_CONTEXT* mppc, BOOL flush);
|
||||
|
||||
FREERDP_LOCAL void mppc_context_free(MPPC_CONTEXT* mppc);
|
||||
|
||||
WINPR_ATTR_MALLOC(mppc_context_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_MPPC_H */
|
||||
+3041
File diff suppressed because it is too large
Load Diff
+58
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* NCrush (RDP6) Bulk Data Compression
|
||||
*
|
||||
* Copyright 2014 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 FREERDP_CODEC_NCRUSH_H
|
||||
#define FREERDP_CODEC_NCRUSH_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#include "mppc.h"
|
||||
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
typedef struct s_NCRUSH_CONTEXT NCRUSH_CONTEXT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int ncrush_compress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE* pDstBuffer, const BYTE** ppDstData, UINT32* pDstSize,
|
||||
UINT32* pFlags);
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData,
|
||||
UINT32 SrcSize, const BYTE** ppDstData, UINT32* pDstSize,
|
||||
UINT32 flags);
|
||||
|
||||
FREERDP_LOCAL void ncrush_context_reset(NCRUSH_CONTEXT* ncrush, BOOL flush);
|
||||
|
||||
FREERDP_LOCAL void ncrush_context_free(NCRUSH_CONTEXT* ncrush);
|
||||
|
||||
WINPR_ATTR_MALLOC(ncrush_context_free, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL NCRUSH_CONTEXT* ncrush_context_new(BOOL Compressor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CODEC_NCRUSH_H */
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* NSCodec Library - SSE2 Optimizations
|
||||
*
|
||||
* Copyright 2024 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2024 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <winpr/platform.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
#include <freerdp/config.h>
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "../nsc_types.h"
|
||||
#include "nsc_neon.h"
|
||||
|
||||
#include "../../core/simd.h"
|
||||
|
||||
#if defined(NEON_INTRINSICS_ENABLED)
|
||||
#define TAG FREERDP_TAG("codec.nsc.neon")
|
||||
#endif
|
||||
|
||||
void nsc_init_neon_int(WINPR_ATTR_UNUSED NSC_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
#if defined(NEON_INTRINSICS_ENABLED)
|
||||
WLog_WARN(TAG, "TODO: Implement neon optimized version of this function");
|
||||
#else
|
||||
WLog_VRB(PRIM_TAG, "undefined WITH_SIMD or NEON intrinsics not available");
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* NSCodec Library - NEON Optimizations
|
||||
*
|
||||
* Copyright 2012 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 FREERDP_LIB_CODEC_NSC_NEON_H
|
||||
#define FREERDP_LIB_CODEC_NSC_NEON_H
|
||||
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL void nsc_init_neon_int(NSC_CONTEXT* WINPR_RESTRICT context);
|
||||
static inline void nsc_init_neon(NSC_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
if (!IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))
|
||||
return;
|
||||
|
||||
nsc_init_neon_int(context);
|
||||
}
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_NSC_NEON_H */
|
||||
@@ -0,0 +1,540 @@
|
||||
/*
|
||||
FreeRDP: A Remote Desktop Protocol Implementation
|
||||
RemoteFX Codec Library - NEON Optimizations
|
||||
|
||||
Copyright 2011 Martin Fleisz <martin.fleisz@thincast.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 <winpr/platform.h>
|
||||
#include <freerdp/config.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
#include "../rfx_types.h"
|
||||
#include "rfx_neon.h"
|
||||
|
||||
#include "../../core/simd.h"
|
||||
|
||||
#if defined(NEON_INTRINSICS_ENABLED)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <arm_neon.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
/* rfx_decode_YCbCr_to_RGB_NEON code now resides in the primitives library. */
|
||||
|
||||
static inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
rfx_quantization_decode_block_NEON(INT16* buffer, const size_t buffer_size, const UINT32 factor)
|
||||
{
|
||||
int16x8_t quantFactors = vdupq_n_s16(factor);
|
||||
int16x8_t* buf = (int16x8_t*)buffer;
|
||||
int16x8_t* buf_end = (int16x8_t*)(buffer + buffer_size);
|
||||
|
||||
do
|
||||
{
|
||||
int16x8_t val = vld1q_s16((INT16*)buf);
|
||||
val = vshlq_s16(val, quantFactors);
|
||||
vst1q_s16((INT16*)buf, val);
|
||||
buf++;
|
||||
} while (buf < buf_end);
|
||||
}
|
||||
|
||||
static void rfx_quantization_decode_NEON(INT16* buffer, const UINT32* WINPR_RESTRICT quantVals)
|
||||
{
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(quantVals);
|
||||
|
||||
rfx_quantization_decode_block_NEON(&buffer[0], 1024, quantVals[8] - 1); /* HL1 */
|
||||
rfx_quantization_decode_block_NEON(&buffer[1024], 1024, quantVals[7] - 1); /* LH1 */
|
||||
rfx_quantization_decode_block_NEON(&buffer[2048], 1024, quantVals[9] - 1); /* HH1 */
|
||||
rfx_quantization_decode_block_NEON(&buffer[3072], 256, quantVals[5] - 1); /* HL2 */
|
||||
rfx_quantization_decode_block_NEON(&buffer[3328], 256, quantVals[4] - 1); /* LH2 */
|
||||
rfx_quantization_decode_block_NEON(&buffer[3584], 256, quantVals[6] - 1); /* HH2 */
|
||||
rfx_quantization_decode_block_NEON(&buffer[3840], 64, quantVals[2] - 1); /* HL3 */
|
||||
rfx_quantization_decode_block_NEON(&buffer[3904], 64, quantVals[1] - 1); /* LH3 */
|
||||
rfx_quantization_decode_block_NEON(&buffer[3968], 64, quantVals[3] - 1); /* HH3 */
|
||||
rfx_quantization_decode_block_NEON(&buffer[4032], 64, quantVals[0] - 1); /* LL3 */
|
||||
}
|
||||
|
||||
static inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
rfx_dwt_2d_decode_block_horiz_NEON(INT16* WINPR_RESTRICT l, INT16* WINPR_RESTRICT h,
|
||||
INT16* WINPR_RESTRICT dst, size_t subband_width)
|
||||
{
|
||||
INT16* l_ptr = l;
|
||||
INT16* h_ptr = h;
|
||||
INT16* dst_ptr = dst;
|
||||
|
||||
for (size_t y = 0; y < subband_width; y++)
|
||||
{
|
||||
/* Even coefficients */
|
||||
for (size_t n = 0; n < subband_width; n += 8)
|
||||
{
|
||||
// dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1);
|
||||
int16x8_t l_n = vld1q_s16(l_ptr);
|
||||
int16x8_t h_n = vld1q_s16(h_ptr);
|
||||
int16x8_t h_n_m = vld1q_s16(h_ptr - 1);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
int16_t first = vgetq_lane_s16(h_n_m, 1);
|
||||
h_n_m = vsetq_lane_s16(first, h_n_m, 0);
|
||||
}
|
||||
|
||||
int16x8_t tmp_n = vaddq_s16(h_n, h_n_m);
|
||||
tmp_n = vaddq_s16(tmp_n, vdupq_n_s16(1));
|
||||
tmp_n = vshrq_n_s16(tmp_n, 1);
|
||||
int16x8_t dst_n = vsubq_s16(l_n, tmp_n);
|
||||
vst1q_s16(l_ptr, dst_n);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
}
|
||||
|
||||
l_ptr -= subband_width;
|
||||
h_ptr -= subband_width;
|
||||
|
||||
/* Odd coefficients */
|
||||
for (size_t n = 0; n < subband_width; n += 8)
|
||||
{
|
||||
// dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1);
|
||||
int16x8_t h_n = vld1q_s16(h_ptr);
|
||||
h_n = vshlq_n_s16(h_n, 1);
|
||||
int16x8x2_t dst_n;
|
||||
dst_n.val[0] = vld1q_s16(l_ptr);
|
||||
int16x8_t dst_n_p = vld1q_s16(l_ptr + 1);
|
||||
|
||||
if (n == subband_width - 8)
|
||||
{
|
||||
int16_t last = vgetq_lane_s16(dst_n_p, 6);
|
||||
dst_n_p = vsetq_lane_s16(last, dst_n_p, 7);
|
||||
}
|
||||
|
||||
dst_n.val[1] = vaddq_s16(dst_n_p, dst_n.val[0]);
|
||||
dst_n.val[1] = vshrq_n_s16(dst_n.val[1], 1);
|
||||
dst_n.val[1] = vaddq_s16(dst_n.val[1], h_n);
|
||||
vst2q_s16(dst_ptr, dst_n);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
dst_ptr += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
rfx_dwt_2d_decode_block_vert_NEON(INT16* WINPR_RESTRICT l, INT16* WINPR_RESTRICT h,
|
||||
INT16* WINPR_RESTRICT dst, size_t subband_width)
|
||||
{
|
||||
INT16* l_ptr = l;
|
||||
INT16* h_ptr = h;
|
||||
INT16* dst_ptr = dst;
|
||||
const size_t total_width = subband_width + subband_width;
|
||||
|
||||
/* Even coefficients */
|
||||
for (size_t n = 0; n < subband_width; n++)
|
||||
{
|
||||
for (size_t x = 0; x < total_width; x += 8)
|
||||
{
|
||||
// dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1);
|
||||
int16x8_t l_n = vld1q_s16(l_ptr);
|
||||
int16x8_t h_n = vld1q_s16(h_ptr);
|
||||
int16x8_t tmp_n = vaddq_s16(h_n, vdupq_n_s16(1));
|
||||
|
||||
if (n == 0)
|
||||
tmp_n = vaddq_s16(tmp_n, h_n);
|
||||
else
|
||||
{
|
||||
int16x8_t h_n_m = vld1q_s16((h_ptr - total_width));
|
||||
tmp_n = vaddq_s16(tmp_n, h_n_m);
|
||||
}
|
||||
|
||||
tmp_n = vshrq_n_s16(tmp_n, 1);
|
||||
int16x8_t dst_n = vsubq_s16(l_n, tmp_n);
|
||||
vst1q_s16(dst_ptr, dst_n);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
dst_ptr += 8;
|
||||
}
|
||||
|
||||
dst_ptr += total_width;
|
||||
}
|
||||
|
||||
h_ptr = h;
|
||||
dst_ptr = dst + total_width;
|
||||
|
||||
/* Odd coefficients */
|
||||
for (size_t n = 0; n < subband_width; n++)
|
||||
{
|
||||
for (size_t x = 0; x < total_width; x += 8)
|
||||
{
|
||||
// dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1);
|
||||
int16x8_t h_n = vld1q_s16(h_ptr);
|
||||
int16x8_t dst_n_m = vld1q_s16(dst_ptr - total_width);
|
||||
h_n = vshlq_n_s16(h_n, 1);
|
||||
int16x8_t tmp_n = dst_n_m;
|
||||
|
||||
if (n == subband_width - 1)
|
||||
tmp_n = vaddq_s16(tmp_n, dst_n_m);
|
||||
else
|
||||
{
|
||||
int16x8_t dst_n_p = vld1q_s16((dst_ptr + total_width));
|
||||
tmp_n = vaddq_s16(tmp_n, dst_n_p);
|
||||
}
|
||||
|
||||
tmp_n = vshrq_n_s16(tmp_n, 1);
|
||||
int16x8_t dst_n = vaddq_s16(tmp_n, h_n);
|
||||
vst1q_s16(dst_ptr, dst_n);
|
||||
h_ptr += 8;
|
||||
dst_ptr += 8;
|
||||
}
|
||||
|
||||
dst_ptr += total_width;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
|
||||
rfx_dwt_2d_decode_block_NEON(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT idwt,
|
||||
size_t subband_width)
|
||||
{
|
||||
INT16 *hl, *lh, *hh, *ll;
|
||||
INT16 *l_dst, *h_dst;
|
||||
/* 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;
|
||||
rfx_dwt_2d_decode_block_horiz_NEON(ll, hl, l_dst, subband_width);
|
||||
lh = buffer + subband_width * subband_width;
|
||||
hh = buffer + subband_width * subband_width * 2;
|
||||
h_dst = idwt + subband_width * subband_width * 2;
|
||||
rfx_dwt_2d_decode_block_horiz_NEON(lh, hh, h_dst, subband_width);
|
||||
/* Inverse DWT in vertical direction, results are stored in original buffer. */
|
||||
rfx_dwt_2d_decode_block_vert_NEON(l_dst, h_dst, buffer, subband_width);
|
||||
}
|
||||
|
||||
static void rfx_dwt_2d_decode_NEON(INT16* buffer, INT16* dwt_buffer)
|
||||
{
|
||||
rfx_dwt_2d_decode_block_NEON(buffer + 3840, dwt_buffer, 8);
|
||||
rfx_dwt_2d_decode_block_NEON(buffer + 3072, dwt_buffer, 16);
|
||||
rfx_dwt_2d_decode_block_NEON(buffer, dwt_buffer, 32);
|
||||
}
|
||||
|
||||
static inline void rfx_idwt_extrapolate_horiz_neon(INT16* restrict pLowBand, size_t nLowStep,
|
||||
const INT16* restrict pHighBand,
|
||||
size_t nHighStep, INT16* restrict pDstBand,
|
||||
size_t nDstStep, size_t nLowCount,
|
||||
size_t nHighCount, size_t nDstCount)
|
||||
{
|
||||
WINPR_ASSERT(pLowBand);
|
||||
WINPR_ASSERT(pHighBand);
|
||||
WINPR_ASSERT(pDstBand);
|
||||
|
||||
INT16* l_ptr = pLowBand;
|
||||
const INT16* h_ptr = pHighBand;
|
||||
INT16* dst_ptr = pDstBand;
|
||||
size_t batchSize = (nLowCount + nHighCount) >> 1;
|
||||
|
||||
for (size_t y = 0; y < nDstCount; y++)
|
||||
{
|
||||
/* Even coefficients */
|
||||
size_t n = 0;
|
||||
for (; n < batchSize; n += 8)
|
||||
{
|
||||
// dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1);
|
||||
int16x8_t l_n = vld1q_s16(l_ptr);
|
||||
int16x8_t h_n = vld1q_s16(h_ptr);
|
||||
int16x8_t h_n_m = vld1q_s16(h_ptr - 1);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
int16_t first = vgetq_lane_s16(h_n_m, 1);
|
||||
h_n_m = vsetq_lane_s16(first, h_n_m, 0);
|
||||
}
|
||||
else if (n == 24)
|
||||
h_n = vsetq_lane_s16(0, h_n, 7);
|
||||
|
||||
int16x8_t tmp_n = vaddq_s16(h_n, h_n_m);
|
||||
tmp_n = vaddq_s16(tmp_n, vdupq_n_s16(1));
|
||||
tmp_n = vshrq_n_s16(tmp_n, 1);
|
||||
int16x8_t dst_n = vsubq_s16(l_n, tmp_n);
|
||||
vst1q_s16(l_ptr, dst_n);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
}
|
||||
if (n < 32)
|
||||
*l_ptr -= *(h_ptr - 1);
|
||||
|
||||
l_ptr -= batchSize;
|
||||
h_ptr -= batchSize;
|
||||
|
||||
/* Odd coefficients */
|
||||
n = 0;
|
||||
for (; n < batchSize; n += 8)
|
||||
{
|
||||
// dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1);
|
||||
int16x8_t h_n = vld1q_s16(h_ptr);
|
||||
h_n = vshlq_n_s16(h_n, 1);
|
||||
int16x8x2_t dst_n;
|
||||
dst_n.val[0] = vld1q_s16(l_ptr);
|
||||
int16x8_t dst_n_p = vld1q_s16(l_ptr + 1);
|
||||
|
||||
if (n == 24)
|
||||
h_n = vsetq_lane_s16(0, h_n, 7);
|
||||
|
||||
dst_n.val[1] = vaddq_s16(dst_n_p, dst_n.val[0]);
|
||||
dst_n.val[1] = vshrq_n_s16(dst_n.val[1], 1);
|
||||
dst_n.val[1] = vaddq_s16(dst_n.val[1], h_n);
|
||||
vst2q_s16(dst_ptr, dst_n);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
dst_ptr += 16;
|
||||
}
|
||||
if (n == 32)
|
||||
{
|
||||
h_ptr -= 1;
|
||||
l_ptr += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst_ptr = *l_ptr;
|
||||
l_ptr += 1;
|
||||
dst_ptr += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rfx_idwt_extrapolate_vert_neon(const INT16* restrict pLowBand, size_t nLowStep,
|
||||
const INT16* restrict pHighBand, size_t nHighStep,
|
||||
INT16* restrict pDstBand, size_t nDstStep,
|
||||
size_t nLowCount, size_t nHighCount,
|
||||
size_t nDstCount)
|
||||
{
|
||||
WINPR_ASSERT(pLowBand);
|
||||
WINPR_ASSERT(pHighBand);
|
||||
WINPR_ASSERT(pDstBand);
|
||||
|
||||
const INT16* l_ptr = pLowBand;
|
||||
const INT16* h_ptr = pHighBand;
|
||||
INT16* dst_ptr = pDstBand;
|
||||
size_t batchSize = (nDstCount >> 3) << 3;
|
||||
size_t forceBandSize = (nLowCount + nHighCount) >> 1;
|
||||
|
||||
/* Even coefficients */
|
||||
for (size_t n = 0; n < forceBandSize; n++)
|
||||
{
|
||||
for (size_t x = 0; x < batchSize; x += 8)
|
||||
{
|
||||
// dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1);
|
||||
int16x8_t l_n = vld1q_s16(l_ptr);
|
||||
int16x8_t h_n = vld1q_s16((n == 31) ? (h_ptr - nHighStep) : h_ptr);
|
||||
int16x8_t tmp_n = vaddq_s16(h_n, vdupq_n_s16(1));
|
||||
|
||||
if (n == 0)
|
||||
tmp_n = vaddq_s16(tmp_n, h_n);
|
||||
else if (n < 31)
|
||||
{
|
||||
int16x8_t h_n_m = vld1q_s16((h_ptr - nHighStep));
|
||||
tmp_n = vaddq_s16(tmp_n, h_n_m);
|
||||
}
|
||||
|
||||
tmp_n = vshrq_n_s16(tmp_n, 1);
|
||||
int16x8_t dst_n = vsubq_s16(l_n, tmp_n);
|
||||
vst1q_s16(dst_ptr, dst_n);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
dst_ptr += 8;
|
||||
}
|
||||
|
||||
if (nDstCount > batchSize)
|
||||
{
|
||||
int16_t h_n = (n == 31) ? *(h_ptr - nHighStep) : *h_ptr;
|
||||
int16_t tmp_n = h_n + 1;
|
||||
if (n == 0)
|
||||
tmp_n += h_n;
|
||||
else if (n < 31)
|
||||
tmp_n += *(h_ptr - nHighStep);
|
||||
tmp_n >>= 1;
|
||||
*dst_ptr = *l_ptr - tmp_n;
|
||||
l_ptr += 1;
|
||||
h_ptr += 1;
|
||||
dst_ptr += 1;
|
||||
}
|
||||
|
||||
dst_ptr += nDstStep;
|
||||
}
|
||||
|
||||
if (forceBandSize < 32)
|
||||
{
|
||||
for (size_t x = 0; x < batchSize; x += 8)
|
||||
{
|
||||
int16x8_t l_n = vld1q_s16(l_ptr);
|
||||
int16x8_t h_n = vld1q_s16(h_ptr - nHighStep);
|
||||
int16x8_t tmp_n = vsubq_s16(l_n, h_n);
|
||||
vst1q_s16(dst_ptr, tmp_n);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
dst_ptr += 8;
|
||||
}
|
||||
|
||||
if (nDstCount > batchSize)
|
||||
{
|
||||
*dst_ptr = *l_ptr - *(h_ptr - nHighStep);
|
||||
l_ptr += 1;
|
||||
h_ptr += 1;
|
||||
dst_ptr += 1;
|
||||
}
|
||||
}
|
||||
|
||||
h_ptr = pHighBand;
|
||||
dst_ptr = pDstBand + nDstStep;
|
||||
|
||||
/* Odd coefficients */
|
||||
for (size_t n = 0; n < forceBandSize; n++)
|
||||
{
|
||||
for (size_t x = 0; x < batchSize; x += 8)
|
||||
{
|
||||
// dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1);
|
||||
int16x8_t tmp_n = vld1q_s16(dst_ptr - nDstStep);
|
||||
if (n == 31)
|
||||
{
|
||||
int16x8_t dst_n_p = vld1q_s16(l_ptr);
|
||||
l_ptr += 8;
|
||||
tmp_n = vaddq_s16(tmp_n, dst_n_p);
|
||||
tmp_n = vshrq_n_s16(tmp_n, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int16x8_t dst_n_p = vld1q_s16(dst_ptr + nDstStep);
|
||||
tmp_n = vaddq_s16(tmp_n, dst_n_p);
|
||||
tmp_n = vshrq_n_s16(tmp_n, 1);
|
||||
int16x8_t h_n = vld1q_s16(h_ptr);
|
||||
h_n = vshlq_n_s16(h_n, 1);
|
||||
tmp_n = vaddq_s16(tmp_n, h_n);
|
||||
}
|
||||
vst1q_s16(dst_ptr, tmp_n);
|
||||
h_ptr += 8;
|
||||
dst_ptr += 8;
|
||||
}
|
||||
|
||||
if (nDstCount > batchSize)
|
||||
{
|
||||
int16_t tmp_n = *(dst_ptr - nDstStep);
|
||||
if (n == 31)
|
||||
{
|
||||
int16_t dst_n_p = *l_ptr;
|
||||
l_ptr += 1;
|
||||
tmp_n += dst_n_p;
|
||||
tmp_n >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t dst_n_p = *(dst_ptr + nDstStep);
|
||||
tmp_n += dst_n_p;
|
||||
tmp_n >>= 1;
|
||||
int16_t h_n = *h_ptr;
|
||||
h_n <<= 1;
|
||||
tmp_n += h_n;
|
||||
}
|
||||
*dst_ptr = tmp_n;
|
||||
h_ptr += 1;
|
||||
dst_ptr += 1;
|
||||
}
|
||||
|
||||
dst_ptr += nDstStep;
|
||||
}
|
||||
}
|
||||
|
||||
static inline size_t prfx_get_band_l_count(size_t level)
|
||||
{
|
||||
return (64 >> level) + 1;
|
||||
}
|
||||
|
||||
static inline size_t prfx_get_band_h_count(size_t level)
|
||||
{
|
||||
if (level == 1)
|
||||
return (64 >> 1) - 1;
|
||||
else
|
||||
return (64 + (1 << (level - 1))) >> level;
|
||||
}
|
||||
|
||||
static inline void rfx_dwt_2d_decode_extrapolate_block_neon(INT16* buffer, INT16* temp,
|
||||
size_t level)
|
||||
{
|
||||
size_t nDstStepX;
|
||||
size_t nDstStepY;
|
||||
INT16 *HL, *LH;
|
||||
INT16 *HH, *LL;
|
||||
INT16 *L, *H, *LLx;
|
||||
|
||||
const size_t nBandL = prfx_get_band_l_count(level);
|
||||
const size_t nBandH = prfx_get_band_h_count(level);
|
||||
size_t offset = 0;
|
||||
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(temp);
|
||||
|
||||
HL = &buffer[offset];
|
||||
offset += (nBandH * nBandL);
|
||||
LH = &buffer[offset];
|
||||
offset += (nBandL * nBandH);
|
||||
HH = &buffer[offset];
|
||||
offset += (nBandH * nBandH);
|
||||
LL = &buffer[offset];
|
||||
nDstStepX = (nBandL + nBandH);
|
||||
nDstStepY = (nBandL + nBandH);
|
||||
offset = 0;
|
||||
L = &temp[offset];
|
||||
offset += (nBandL * nDstStepX);
|
||||
H = &temp[offset];
|
||||
LLx = &buffer[0];
|
||||
|
||||
/* horizontal (LL + HL -> L) */
|
||||
rfx_idwt_extrapolate_horiz_neon(LL, nBandL, HL, nBandH, L, nDstStepX, nBandL, nBandH, nBandL);
|
||||
|
||||
/* horizontal (LH + HH -> H) */
|
||||
rfx_idwt_extrapolate_horiz_neon(LH, nBandL, HH, nBandH, H, nDstStepX, nBandL, nBandH, nBandH);
|
||||
|
||||
/* vertical (L + H -> LL) */
|
||||
rfx_idwt_extrapolate_vert_neon(L, nDstStepX, H, nDstStepX, LLx, nDstStepY, nBandL, nBandH,
|
||||
nBandL + nBandH);
|
||||
}
|
||||
|
||||
static void rfx_dwt_2d_extrapolate_decode_neon(INT16* buffer, INT16* temp)
|
||||
{
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(temp);
|
||||
rfx_dwt_2d_decode_extrapolate_block_neon(&buffer[3807], temp, 3);
|
||||
rfx_dwt_2d_decode_extrapolate_block_neon(&buffer[3007], temp, 2);
|
||||
rfx_dwt_2d_decode_extrapolate_block_neon(&buffer[0], temp, 1);
|
||||
}
|
||||
#endif // NEON_INTRINSICS_ENABLED
|
||||
|
||||
void rfx_init_neon_int(RFX_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
#if defined(NEON_INTRINSICS_ENABLED)
|
||||
WLog_VRB(PRIM_TAG, "NEON optimizations");
|
||||
PROFILER_RENAME(context->priv->prof_rfx_ycbcr_to_rgb, "rfx_decode_YCbCr_to_RGB_NEON");
|
||||
PROFILER_RENAME(context->priv->prof_rfx_quantization_decode, "rfx_quantization_decode_NEON");
|
||||
PROFILER_RENAME(context->priv->prof_rfx_dwt_2d_decode, "rfx_dwt_2d_decode_NEON");
|
||||
context->quantization_decode = rfx_quantization_decode_NEON;
|
||||
context->dwt_2d_decode = rfx_dwt_2d_decode_NEON;
|
||||
context->dwt_2d_extrapolate_decode = rfx_dwt_2d_extrapolate_decode_neon;
|
||||
#else
|
||||
WLog_VRB(PRIM_TAG, "undefined WITH_SIMD or NEON intrinsics not available");
|
||||
WINPR_UNUSED(context);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
FreeRDP: A Remote Desktop Protocol Implementation
|
||||
RemoteFX Codec Library - NEON Optimizations
|
||||
|
||||
Copyright 2011 Martin Fleisz <martin.fleisz@thincast.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 FREERDP_LIB_CODEC_RFX_NEON_H
|
||||
#define FREERDP_LIB_CODEC_RFX_NEON_H
|
||||
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL void rfx_init_neon_int(RFX_CONTEXT* WINPR_RESTRICT context);
|
||||
static inline void rfx_init_neon(RFX_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
if (!IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))
|
||||
return;
|
||||
|
||||
rfx_init_neon_int(context);
|
||||
}
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_NEON_H */
|
||||
+534
@@ -0,0 +1,534 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* NSCodec Codec
|
||||
*
|
||||
* Copyright 2011 Samsung, Author Jiten Pathy
|
||||
* Copyright 2012 Vic Lee
|
||||
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2016 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include "nsc_types.h"
|
||||
#include "nsc_encode.h"
|
||||
|
||||
#include "sse/nsc_sse2.h"
|
||||
#include "neon/nsc_neon.h"
|
||||
|
||||
#include <freerdp/log.h>
|
||||
|
||||
static BOOL nsc_decode(NSC_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
size_t pos = 0;
|
||||
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
const UINT16 rw = ROUND_UP_TO(context->width, 8);
|
||||
WINPR_ASSERT(context->ColorLossLevel >= 1);
|
||||
const BYTE shift = WINPR_ASSERTING_INT_CAST(BYTE, context->ColorLossLevel -
|
||||
1); /* colorloss recovery + YCoCg shift */
|
||||
BYTE* bmpdata = context->BitmapData;
|
||||
|
||||
if (!bmpdata)
|
||||
return FALSE;
|
||||
|
||||
for (size_t y = 0; y < context->height; y++)
|
||||
{
|
||||
const BYTE* yplane = nullptr;
|
||||
const BYTE* coplane = nullptr;
|
||||
const BYTE* cgplane = nullptr;
|
||||
const BYTE* aplane = context->priv->PlaneBuffers[3] + y * context->width; /* A */
|
||||
|
||||
if (context->ChromaSubsamplingLevel)
|
||||
{
|
||||
yplane = context->priv->PlaneBuffers[0] + y * rw; /* Y */
|
||||
coplane = context->priv->PlaneBuffers[1] + (y >> 1) * (rw >> 1); /* Co, supersampled */
|
||||
cgplane = context->priv->PlaneBuffers[2] + (y >> 1) * (rw >> 1); /* Cg, supersampled */
|
||||
}
|
||||
else
|
||||
{
|
||||
yplane = context->priv->PlaneBuffers[0] + y * context->width; /* Y */
|
||||
coplane = context->priv->PlaneBuffers[1] + y * context->width; /* Co */
|
||||
cgplane = context->priv->PlaneBuffers[2] + y * context->width; /* Cg */
|
||||
}
|
||||
|
||||
for (UINT32 x = 0; x < context->width; x++)
|
||||
{
|
||||
INT16 y_val = (INT16)*yplane;
|
||||
INT16 co_val = (INT16)(INT8)(((INT16)*coplane) << shift);
|
||||
INT16 cg_val = (INT16)(INT8)(((INT16)*cgplane) << shift);
|
||||
INT16 r_val = WINPR_ASSERTING_INT_CAST(int16_t, y_val + co_val - cg_val);
|
||||
INT16 g_val = WINPR_ASSERTING_INT_CAST(int16_t, y_val + cg_val);
|
||||
INT16 b_val = WINPR_ASSERTING_INT_CAST(int16_t, y_val - co_val - cg_val);
|
||||
|
||||
if (pos + 4 > context->BitmapDataLength)
|
||||
return FALSE;
|
||||
|
||||
pos += 4;
|
||||
*bmpdata++ = MINMAX(b_val, 0, 0xFF);
|
||||
*bmpdata++ = MINMAX(g_val, 0, 0xFF);
|
||||
*bmpdata++ = MINMAX(r_val, 0, 0xFF);
|
||||
*bmpdata++ = *aplane;
|
||||
yplane++;
|
||||
coplane += (context->ChromaSubsamplingLevel ? x % 2 : 1);
|
||||
cgplane += (context->ChromaSubsamplingLevel ? x % 2 : 1);
|
||||
aplane++;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL nsc_rle_decode(const BYTE* WINPR_RESTRICT in, size_t inSize, BYTE* WINPR_RESTRICT out,
|
||||
UINT32 outSize, UINT32 originalSize)
|
||||
{
|
||||
UINT32 left = originalSize;
|
||||
|
||||
while (left > 4)
|
||||
{
|
||||
if (inSize < 1)
|
||||
return FALSE;
|
||||
inSize--;
|
||||
|
||||
const BYTE value = *in++;
|
||||
UINT32 len = 0;
|
||||
|
||||
if (left == 5)
|
||||
{
|
||||
if (outSize < 1)
|
||||
return FALSE;
|
||||
|
||||
outSize--;
|
||||
*out++ = value;
|
||||
left--;
|
||||
}
|
||||
else if (inSize < 1)
|
||||
return FALSE;
|
||||
else if (value == *in)
|
||||
{
|
||||
inSize--;
|
||||
in++;
|
||||
|
||||
if (inSize < 1)
|
||||
return FALSE;
|
||||
else if (*in < 0xFF)
|
||||
{
|
||||
inSize--;
|
||||
len = (UINT32)*in++;
|
||||
len += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inSize < 5)
|
||||
return FALSE;
|
||||
inSize -= 5;
|
||||
in++;
|
||||
len = ((UINT32)(*in++));
|
||||
len |= ((UINT32)(*in++)) << 8U;
|
||||
len |= ((UINT32)(*in++)) << 16U;
|
||||
len |= ((UINT32)(*in++)) << 24U;
|
||||
}
|
||||
|
||||
if ((outSize < len) || (left < len))
|
||||
return FALSE;
|
||||
|
||||
outSize -= len;
|
||||
FillMemory(out, len, value);
|
||||
out += len;
|
||||
left -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outSize < 1)
|
||||
return FALSE;
|
||||
|
||||
outSize--;
|
||||
*out++ = value;
|
||||
left--;
|
||||
}
|
||||
}
|
||||
|
||||
if ((outSize < 4) || (left < 4))
|
||||
return FALSE;
|
||||
|
||||
if (inSize < 4)
|
||||
return FALSE;
|
||||
memcpy(out, in, 4);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL nsc_rle_decompress_data(NSC_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
const BYTE* rle = context->Planes;
|
||||
size_t rleSize = context->PlanesSize;
|
||||
WINPR_ASSERT(rle);
|
||||
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
const UINT32 originalSize = context->OrgByteCount[i];
|
||||
const UINT32 planeSize = context->PlaneByteCount[i];
|
||||
|
||||
if (rleSize < planeSize)
|
||||
return FALSE;
|
||||
|
||||
if (planeSize == 0)
|
||||
{
|
||||
if (context->priv->PlaneBuffersLength < originalSize)
|
||||
return FALSE;
|
||||
|
||||
FillMemory(context->priv->PlaneBuffers[i], originalSize, 0xFF);
|
||||
}
|
||||
else if (planeSize < originalSize)
|
||||
{
|
||||
if (!nsc_rle_decode(rle, rleSize, context->priv->PlaneBuffers[i],
|
||||
context->priv->PlaneBuffersLength, originalSize))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context->priv->PlaneBuffersLength < originalSize)
|
||||
return FALSE;
|
||||
|
||||
if (rleSize < originalSize)
|
||||
return FALSE;
|
||||
|
||||
CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize);
|
||||
}
|
||||
|
||||
rle += planeSize;
|
||||
rleSize -= planeSize;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL nsc_stream_initialize(NSC_CONTEXT* WINPR_RESTRICT context, wStream* WINPR_RESTRICT s)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(context->priv);
|
||||
if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
|
||||
return FALSE;
|
||||
|
||||
size_t total = 0;
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
Stream_Read_UINT32(s, context->PlaneByteCount[i]);
|
||||
total += context->PlaneByteCount[i];
|
||||
}
|
||||
|
||||
Stream_Read_UINT8(s, context->ColorLossLevel); /* ColorLossLevel (1 byte) */
|
||||
if ((context->ColorLossLevel < 1) || (context->ColorLossLevel > 7))
|
||||
{
|
||||
WLog_Print(context->priv->log, WLOG_ERROR,
|
||||
"ColorLossLevel=%" PRIu8 " out of range, must be [1,7] inclusive",
|
||||
context->ColorLossLevel);
|
||||
return FALSE;
|
||||
}
|
||||
Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
|
||||
Stream_Seek(s, 2); /* Reserved (2 bytes) */
|
||||
context->Planes = Stream_Pointer(s);
|
||||
context->PlanesSize = total;
|
||||
return Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, total);
|
||||
}
|
||||
|
||||
static BOOL nsc_context_initialize(NSC_CONTEXT* WINPR_RESTRICT context, wStream* WINPR_RESTRICT s)
|
||||
{
|
||||
if (!nsc_stream_initialize(context, s))
|
||||
return FALSE;
|
||||
|
||||
const size_t blength = 4ull * context->width * context->height;
|
||||
|
||||
if (!context->BitmapData || (blength > context->BitmapDataLength))
|
||||
{
|
||||
void* tmp = winpr_aligned_recalloc(context->BitmapData, blength + 16, sizeof(BYTE), 32);
|
||||
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
|
||||
context->BitmapData = tmp;
|
||||
context->BitmapDataLength = blength;
|
||||
}
|
||||
|
||||
const UINT32 tempWidth = ROUND_UP_TO(context->width, 8);
|
||||
const UINT32 tempHeight = ROUND_UP_TO(context->height, 2);
|
||||
/* The maximum length a decoded plane can reach in all cases */
|
||||
const size_t plength = 1ull * tempWidth * tempHeight;
|
||||
if (plength > UINT32_MAX)
|
||||
return FALSE;
|
||||
|
||||
if (plength > context->priv->PlaneBuffersLength)
|
||||
{
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
void* tmp = (BYTE*)winpr_aligned_recalloc(context->priv->PlaneBuffers[i], plength,
|
||||
sizeof(BYTE), 32);
|
||||
|
||||
if (!tmp)
|
||||
return FALSE;
|
||||
|
||||
context->priv->PlaneBuffers[i] = tmp;
|
||||
}
|
||||
|
||||
context->priv->PlaneBuffersLength = (UINT32)plength;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
context->OrgByteCount[i] = context->width * context->height;
|
||||
|
||||
if (context->ChromaSubsamplingLevel)
|
||||
{
|
||||
context->OrgByteCount[0] = tempWidth * context->height;
|
||||
context->OrgByteCount[1] = (tempWidth >> 1) * (tempHeight >> 1);
|
||||
context->OrgByteCount[2] = context->OrgByteCount[1];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void nsc_profiler_print(NSC_CONTEXT_PRIV* WINPR_RESTRICT priv)
|
||||
{
|
||||
WINPR_UNUSED(priv);
|
||||
|
||||
PROFILER_PRINT_HEADER
|
||||
PROFILER_PRINT(priv->prof_nsc_rle_decompress_data)
|
||||
PROFILER_PRINT(priv->prof_nsc_decode)
|
||||
PROFILER_PRINT(priv->prof_nsc_rle_compress_data)
|
||||
PROFILER_PRINT(priv->prof_nsc_encode)
|
||||
PROFILER_PRINT_FOOTER
|
||||
}
|
||||
|
||||
BOOL nsc_context_reset(NSC_CONTEXT* WINPR_RESTRICT context, UINT32 width, UINT32 height)
|
||||
{
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
if ((width > UINT16_MAX) || (height > UINT16_MAX))
|
||||
return FALSE;
|
||||
|
||||
context->width = (UINT16)width;
|
||||
context->height = (UINT16)height;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
NSC_CONTEXT* nsc_context_new(void)
|
||||
{
|
||||
NSC_CONTEXT* context = (NSC_CONTEXT*)winpr_aligned_calloc(1, sizeof(NSC_CONTEXT), 32);
|
||||
|
||||
if (!context)
|
||||
return nullptr;
|
||||
|
||||
context->priv = (NSC_CONTEXT_PRIV*)winpr_aligned_calloc(1, sizeof(NSC_CONTEXT_PRIV), 32);
|
||||
|
||||
if (!context->priv)
|
||||
goto error;
|
||||
|
||||
context->priv->log = WLog_Get("com.freerdp.codec.nsc");
|
||||
WLog_OpenAppender(context->priv->log);
|
||||
context->BitmapData = nullptr;
|
||||
context->decode = nsc_decode;
|
||||
context->encode = nsc_encode;
|
||||
|
||||
PROFILER_CREATE(context->priv->prof_nsc_rle_decompress_data, "nsc_rle_decompress_data")
|
||||
PROFILER_CREATE(context->priv->prof_nsc_decode, "nsc_decode")
|
||||
PROFILER_CREATE(context->priv->prof_nsc_rle_compress_data, "nsc_rle_compress_data")
|
||||
PROFILER_CREATE(context->priv->prof_nsc_encode, "nsc_encode")
|
||||
/* Default encoding parameters */
|
||||
context->ColorLossLevel = 3;
|
||||
context->ChromaSubsamplingLevel = 1;
|
||||
/* init optimized methods */
|
||||
nsc_init_sse2(context);
|
||||
nsc_init_neon(context);
|
||||
return context;
|
||||
error:
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
|
||||
nsc_context_free(context);
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void nsc_context_free(NSC_CONTEXT* context)
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
if (context->priv)
|
||||
{
|
||||
for (size_t i = 0; i < 5; i++)
|
||||
winpr_aligned_free(context->priv->PlaneBuffers[i]);
|
||||
|
||||
nsc_profiler_print(context->priv);
|
||||
PROFILER_FREE(context->priv->prof_nsc_rle_decompress_data)
|
||||
PROFILER_FREE(context->priv->prof_nsc_decode)
|
||||
PROFILER_FREE(context->priv->prof_nsc_rle_compress_data)
|
||||
PROFILER_FREE(context->priv->prof_nsc_encode)
|
||||
winpr_aligned_free(context->priv);
|
||||
}
|
||||
|
||||
winpr_aligned_free(context->BitmapData);
|
||||
winpr_aligned_free(context);
|
||||
}
|
||||
|
||||
#if defined(WITH_FREERDP_DEPRECATED)
|
||||
BOOL nsc_context_set_pixel_format(NSC_CONTEXT* context, UINT32 pixel_format)
|
||||
{
|
||||
return nsc_context_set_parameters(context, NSC_COLOR_FORMAT, pixel_format);
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL nsc_context_set_parameters(NSC_CONTEXT* WINPR_RESTRICT context, NSC_PARAMETER what,
|
||||
UINT32 value)
|
||||
{
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
switch (what)
|
||||
{
|
||||
case NSC_COLOR_LOSS_LEVEL:
|
||||
context->ColorLossLevel = value;
|
||||
break;
|
||||
case NSC_ALLOW_SUBSAMPLING:
|
||||
context->ChromaSubsamplingLevel = value;
|
||||
break;
|
||||
case NSC_DYNAMIC_COLOR_FIDELITY:
|
||||
context->DynamicColorFidelity = value != 0;
|
||||
break;
|
||||
case NSC_COLOR_FORMAT:
|
||||
context->format = value;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL nsc_process_message(NSC_CONTEXT* WINPR_RESTRICT context, UINT16 bpp, UINT32 width,
|
||||
UINT32 height, const BYTE* data, UINT32 length,
|
||||
BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStride,
|
||||
UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight, UINT32 flip)
|
||||
{
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(context->priv);
|
||||
|
||||
wStream sbuffer = WINPR_C_ARRAY_INIT;
|
||||
BOOL ret = 0;
|
||||
if (!data || !pDstData)
|
||||
{
|
||||
WLog_Print(context->priv->log, WLOG_ERROR, "Invalid argument: data=%p, pDstData=%p",
|
||||
(const void*)data, (void*)pDstData);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nXDst > nWidth)
|
||||
{
|
||||
WLog_Print(context->priv->log, WLOG_ERROR, "nXDst %" PRIu32 " > nWidth %" PRIu32, nXDst,
|
||||
nWidth);
|
||||
return FALSE;
|
||||
}
|
||||
if (nYDst > nHeight)
|
||||
{
|
||||
WLog_Print(context->priv->log, WLOG_ERROR, "nYDst %" PRIu32 " > nHeight %" PRIu32, nYDst,
|
||||
nHeight);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wStream* s = Stream_StaticConstInit(&sbuffer, data, length);
|
||||
if (!s)
|
||||
return FALSE;
|
||||
|
||||
const UINT32 minStride = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
|
||||
if (nDstStride == 0)
|
||||
nDstStride = minStride;
|
||||
if (nDstStride < minStride)
|
||||
{
|
||||
WLog_Print(context->priv->log, WLOG_ERROR,
|
||||
"nDstStride %" PRIu32 " < minimum stride %" PRIu32, nDstStride, minStride);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (bpp)
|
||||
{
|
||||
case 32:
|
||||
context->format = PIXEL_FORMAT_BGRA32;
|
||||
break;
|
||||
|
||||
case 24:
|
||||
context->format = PIXEL_FORMAT_BGR24;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
context->format = PIXEL_FORMAT_BGR16;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
context->format = PIXEL_FORMAT_RGB8;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
context->format = PIXEL_FORMAT_A4;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
context->width = WINPR_ASSERTING_INT_CAST(UINT16, width);
|
||||
context->height = WINPR_ASSERTING_INT_CAST(UINT16, height);
|
||||
ret = nsc_context_initialize(context, s);
|
||||
|
||||
if (!ret)
|
||||
return FALSE;
|
||||
|
||||
/* RLE decode */
|
||||
{
|
||||
BOOL rc = 0;
|
||||
PROFILER_ENTER(context->priv->prof_nsc_rle_decompress_data)
|
||||
rc = nsc_rle_decompress_data(context);
|
||||
PROFILER_EXIT(context->priv->prof_nsc_rle_decompress_data)
|
||||
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
}
|
||||
/* Colorloss recover, Chroma supersample and AYCoCg to ARGB Conversion in one step */
|
||||
{
|
||||
BOOL rc = 0;
|
||||
PROFILER_ENTER(context->priv->prof_nsc_decode)
|
||||
rc = context->decode(context);
|
||||
PROFILER_EXIT(context->priv->prof_nsc_decode)
|
||||
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return (freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStride, nXDst, nYDst, width,
|
||||
height, context->BitmapData, PIXEL_FORMAT_BGRA32, 0, 0, 0,
|
||||
nullptr, flip));
|
||||
}
|
||||
+518
@@ -0,0 +1,518 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* NSCodec Encoder
|
||||
*
|
||||
* Copyright 2012 Vic Lee
|
||||
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2016 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include "nsc_types.h"
|
||||
#include "nsc_encode.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 x;
|
||||
UINT32 y;
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
const BYTE* data;
|
||||
UINT32 scanline;
|
||||
BYTE* PlaneBuffer;
|
||||
UINT32 MaxPlaneSize;
|
||||
BYTE* PlaneBuffers[5];
|
||||
UINT32 OrgByteCount[4];
|
||||
|
||||
UINT32 LumaPlaneByteCount;
|
||||
UINT32 OrangeChromaPlaneByteCount;
|
||||
UINT32 GreenChromaPlaneByteCount;
|
||||
UINT32 AlphaPlaneByteCount;
|
||||
UINT8 ColorLossLevel;
|
||||
UINT8 ChromaSubsamplingLevel;
|
||||
} NSC_MESSAGE;
|
||||
|
||||
static BOOL nsc_write_message(NSC_CONTEXT* WINPR_RESTRICT context, wStream* WINPR_RESTRICT s,
|
||||
const NSC_MESSAGE* WINPR_RESTRICT message);
|
||||
|
||||
static BOOL nsc_context_initialize_encode(NSC_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
UINT32 length = 0;
|
||||
UINT32 tempWidth = 0;
|
||||
UINT32 tempHeight = 0;
|
||||
tempWidth = ROUND_UP_TO(context->width, 8);
|
||||
tempHeight = ROUND_UP_TO(context->height, 2);
|
||||
/* The maximum length a decoded plane can reach in all cases */
|
||||
length = tempWidth * tempHeight + 16;
|
||||
|
||||
if (length > context->priv->PlaneBuffersLength)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
BYTE* tmp = (BYTE*)winpr_aligned_recalloc(context->priv->PlaneBuffers[i], length,
|
||||
sizeof(BYTE), 32);
|
||||
|
||||
if (!tmp)
|
||||
goto fail;
|
||||
|
||||
context->priv->PlaneBuffers[i] = tmp;
|
||||
}
|
||||
|
||||
context->priv->PlaneBuffersLength = length;
|
||||
}
|
||||
|
||||
if (context->ChromaSubsamplingLevel)
|
||||
{
|
||||
context->OrgByteCount[0] = tempWidth * context->height;
|
||||
context->OrgByteCount[1] = tempWidth * tempHeight / 4;
|
||||
context->OrgByteCount[2] = tempWidth * tempHeight / 4;
|
||||
context->OrgByteCount[3] = context->width * context->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->OrgByteCount[0] = context->width * context->height;
|
||||
context->OrgByteCount[1] = context->width * context->height;
|
||||
context->OrgByteCount[2] = context->width * context->height;
|
||||
context->OrgByteCount[3] = context->width * context->height;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
fail:
|
||||
|
||||
if (length > context->priv->PlaneBuffersLength)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
winpr_aligned_free(context->priv->PlaneBuffers[i]);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL nsc_encode_argb_to_aycocg(NSC_CONTEXT* WINPR_RESTRICT context,
|
||||
const BYTE* WINPR_RESTRICT data, UINT32 scanline)
|
||||
{
|
||||
size_t y = 0;
|
||||
const BYTE* src = nullptr;
|
||||
BYTE* yplane = nullptr;
|
||||
BYTE* coplane = nullptr;
|
||||
BYTE* cgplane = nullptr;
|
||||
BYTE* aplane = nullptr;
|
||||
INT16 r_val = 0;
|
||||
INT16 g_val = 0;
|
||||
INT16 b_val = 0;
|
||||
BYTE a_val = 0;
|
||||
|
||||
UINT16 tempWidth = ROUND_UP_TO(context->width, 8);
|
||||
const UINT16 rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width);
|
||||
const BYTE ccl = WINPR_ASSERTING_INT_CAST(BYTE, context->ColorLossLevel);
|
||||
|
||||
for (; y < context->height; y++)
|
||||
{
|
||||
src = data + (context->height - 1 - y) * scanline;
|
||||
yplane = context->priv->PlaneBuffers[0] + y * rw;
|
||||
coplane = context->priv->PlaneBuffers[1] + y * rw;
|
||||
cgplane = context->priv->PlaneBuffers[2] + y * rw;
|
||||
aplane = context->priv->PlaneBuffers[3] + y * context->width;
|
||||
|
||||
UINT16 x = 0;
|
||||
for (; x < context->width; x++)
|
||||
{
|
||||
switch (context->format)
|
||||
{
|
||||
case PIXEL_FORMAT_BGRX32:
|
||||
b_val = *src++;
|
||||
g_val = *src++;
|
||||
r_val = *src++;
|
||||
src++;
|
||||
a_val = 0xFF;
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_BGRA32:
|
||||
b_val = *src++;
|
||||
g_val = *src++;
|
||||
r_val = *src++;
|
||||
a_val = *src++;
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_RGBX32:
|
||||
r_val = *src++;
|
||||
g_val = *src++;
|
||||
b_val = *src++;
|
||||
src++;
|
||||
a_val = 0xFF;
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_RGBA32:
|
||||
r_val = *src++;
|
||||
g_val = *src++;
|
||||
b_val = *src++;
|
||||
a_val = *src++;
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_BGR24:
|
||||
b_val = *src++;
|
||||
g_val = *src++;
|
||||
r_val = *src++;
|
||||
a_val = 0xFF;
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_RGB24:
|
||||
r_val = *src++;
|
||||
g_val = *src++;
|
||||
b_val = *src++;
|
||||
a_val = 0xFF;
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_BGR16:
|
||||
b_val = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
|
||||
g_val = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3));
|
||||
r_val = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07));
|
||||
a_val = 0xFF;
|
||||
src += 2;
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_RGB16:
|
||||
r_val = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
|
||||
g_val = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3));
|
||||
b_val = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07));
|
||||
a_val = 0xFF;
|
||||
src += 2;
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_A4:
|
||||
{
|
||||
int shift = 0;
|
||||
BYTE idx = 0;
|
||||
shift = (7 - (x % 8));
|
||||
idx = ((*src) >> shift) & 1;
|
||||
idx |= (((*(src + 1)) >> shift) & 1) << 1;
|
||||
idx |= (((*(src + 2)) >> shift) & 1) << 2;
|
||||
idx |= (((*(src + 3)) >> shift) & 1) << 3;
|
||||
idx *= 3;
|
||||
r_val = (INT16)context->palette[idx];
|
||||
g_val = (INT16)context->palette[idx + 1];
|
||||
b_val = (INT16)context->palette[idx + 2];
|
||||
|
||||
if (shift == 0)
|
||||
src += 4;
|
||||
}
|
||||
|
||||
a_val = 0xFF;
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_RGB8:
|
||||
{
|
||||
int idx = (*src) * 3;
|
||||
r_val = (INT16)context->palette[idx];
|
||||
g_val = (INT16)context->palette[idx + 1];
|
||||
b_val = (INT16)context->palette[idx + 2];
|
||||
src++;
|
||||
}
|
||||
|
||||
a_val = 0xFF;
|
||||
break;
|
||||
|
||||
default:
|
||||
r_val = g_val = b_val = a_val = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
*yplane++ = (BYTE)((r_val >> 2) + (g_val >> 1) + (b_val >> 2));
|
||||
/* Perform color loss reduction here */
|
||||
*coplane++ = (BYTE)((r_val - b_val) >> ccl);
|
||||
*cgplane++ = (BYTE)((-(r_val >> 1) + g_val - (b_val >> 1)) >> ccl);
|
||||
*aplane++ = a_val;
|
||||
}
|
||||
|
||||
if (context->ChromaSubsamplingLevel && (x % 2) == 1)
|
||||
{
|
||||
*yplane = *(yplane - 1);
|
||||
*coplane = *(coplane - 1);
|
||||
*cgplane = *(cgplane - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (context->ChromaSubsamplingLevel && (y % 2) == 1)
|
||||
{
|
||||
yplane = context->priv->PlaneBuffers[0] + y * rw;
|
||||
coplane = context->priv->PlaneBuffers[1] + y * rw;
|
||||
cgplane = context->priv->PlaneBuffers[2] + y * rw;
|
||||
CopyMemory(yplane, yplane - rw, rw);
|
||||
CopyMemory(coplane, coplane - rw, rw);
|
||||
CopyMemory(cgplane, cgplane - rw, rw);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL nsc_encode_subsampling(NSC_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
UINT32 tempWidth = 0;
|
||||
UINT32 tempHeight = 0;
|
||||
|
||||
if (!context)
|
||||
return FALSE;
|
||||
|
||||
tempWidth = ROUND_UP_TO(context->width, 8);
|
||||
tempHeight = ROUND_UP_TO(context->height, 2);
|
||||
|
||||
if (tempHeight == 0)
|
||||
return FALSE;
|
||||
|
||||
if (tempWidth > context->priv->PlaneBuffersLength / tempHeight)
|
||||
return FALSE;
|
||||
|
||||
for (size_t y = 0; y < tempHeight >> 1; y++)
|
||||
{
|
||||
BYTE* co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
|
||||
BYTE* cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
|
||||
const INT8* co_src0 = (INT8*)context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
|
||||
const INT8* co_src1 = co_src0 + tempWidth;
|
||||
const INT8* cg_src0 = (INT8*)context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
|
||||
const INT8* cg_src1 = cg_src0 + tempWidth;
|
||||
|
||||
for (UINT32 x = 0; x < tempWidth >> 1; x++)
|
||||
{
|
||||
*co_dst++ = (BYTE)(((INT16)*co_src0 + (INT16) * (co_src0 + 1) + (INT16)*co_src1 +
|
||||
(INT16) * (co_src1 + 1)) >>
|
||||
2);
|
||||
*cg_dst++ = (BYTE)(((INT16)*cg_src0 + (INT16) * (cg_src0 + 1) + (INT16)*cg_src1 +
|
||||
(INT16) * (cg_src1 + 1)) >>
|
||||
2);
|
||||
co_src0 += 2;
|
||||
co_src1 += 2;
|
||||
cg_src0 += 2;
|
||||
cg_src1 += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL nsc_encode(NSC_CONTEXT* WINPR_RESTRICT context, const BYTE* WINPR_RESTRICT bmpdata,
|
||||
UINT32 rowstride)
|
||||
{
|
||||
if (!context || !bmpdata || (rowstride == 0))
|
||||
return FALSE;
|
||||
|
||||
if (!nsc_encode_argb_to_aycocg(context, bmpdata, rowstride))
|
||||
return FALSE;
|
||||
|
||||
if (context->ChromaSubsamplingLevel)
|
||||
{
|
||||
if (!nsc_encode_subsampling(context))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static UINT32 nsc_rle_encode(const BYTE* WINPR_RESTRICT in, BYTE* WINPR_RESTRICT out,
|
||||
UINT32 originalSize)
|
||||
{
|
||||
UINT32 left = 0;
|
||||
UINT32 runlength = 1;
|
||||
UINT32 planeSize = 0;
|
||||
left = originalSize;
|
||||
|
||||
/**
|
||||
* We quit the loop if the running compressed size is larger than the original.
|
||||
* In such cases data will be sent uncompressed.
|
||||
*/
|
||||
while (left > 4 && planeSize < originalSize - 4)
|
||||
{
|
||||
if (left > 5 && *in == *(in + 1))
|
||||
{
|
||||
runlength++;
|
||||
}
|
||||
else if (runlength == 1)
|
||||
{
|
||||
*out++ = *in;
|
||||
planeSize++;
|
||||
}
|
||||
else if (runlength < 256)
|
||||
{
|
||||
*out++ = *in;
|
||||
*out++ = *in;
|
||||
WINPR_ASSERT(runlength >= 2);
|
||||
*out++ = WINPR_ASSERTING_INT_CAST(BYTE, runlength - 2);
|
||||
runlength = 1;
|
||||
planeSize += 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out++ = *in;
|
||||
*out++ = *in;
|
||||
*out++ = 0xFF;
|
||||
*out++ = (runlength & 0x000000FF);
|
||||
*out++ = (runlength & 0x0000FF00) >> 8;
|
||||
*out++ = (runlength & 0x00FF0000) >> 16;
|
||||
*out++ = (runlength & 0xFF000000) >> 24;
|
||||
runlength = 1;
|
||||
planeSize += 7;
|
||||
}
|
||||
|
||||
in++;
|
||||
left--;
|
||||
}
|
||||
|
||||
if (planeSize < originalSize - 4)
|
||||
CopyMemory(out, in, 4);
|
||||
|
||||
planeSize += 4;
|
||||
return planeSize;
|
||||
}
|
||||
|
||||
static void nsc_rle_compress_data(NSC_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
UINT32 planeSize = 0;
|
||||
UINT32 originalSize = 0;
|
||||
|
||||
for (UINT16 i = 0; i < 4; i++)
|
||||
{
|
||||
originalSize = context->OrgByteCount[i];
|
||||
|
||||
if (originalSize == 0)
|
||||
{
|
||||
planeSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
planeSize = nsc_rle_encode(context->priv->PlaneBuffers[i],
|
||||
context->priv->PlaneBuffers[4], originalSize);
|
||||
|
||||
if (planeSize < originalSize)
|
||||
CopyMemory(context->priv->PlaneBuffers[i], context->priv->PlaneBuffers[4],
|
||||
planeSize);
|
||||
else
|
||||
planeSize = originalSize;
|
||||
}
|
||||
|
||||
context->PlaneByteCount[i] = planeSize;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL nsc_write_message(WINPR_ATTR_UNUSED NSC_CONTEXT* WINPR_RESTRICT context,
|
||||
wStream* WINPR_RESTRICT s, const NSC_MESSAGE* WINPR_RESTRICT message)
|
||||
{
|
||||
UINT32 totalPlaneByteCount = 0;
|
||||
totalPlaneByteCount = message->LumaPlaneByteCount + message->OrangeChromaPlaneByteCount +
|
||||
message->GreenChromaPlaneByteCount + message->AlphaPlaneByteCount;
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, 20 + totalPlaneByteCount))
|
||||
return FALSE;
|
||||
|
||||
Stream_Write_UINT32(s, message->LumaPlaneByteCount); /* LumaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(
|
||||
s, message->OrangeChromaPlaneByteCount); /* OrangeChromaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(
|
||||
s, message->GreenChromaPlaneByteCount); /* GreenChromaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT32(s, message->AlphaPlaneByteCount); /* AlphaPlaneByteCount (4 bytes) */
|
||||
Stream_Write_UINT8(s, message->ColorLossLevel); /* ColorLossLevel (1 byte) */
|
||||
Stream_Write_UINT8(s, message->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
|
||||
Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
|
||||
|
||||
if (message->LumaPlaneByteCount)
|
||||
Stream_Write(s, message->PlaneBuffers[0], message->LumaPlaneByteCount); /* LumaPlane */
|
||||
|
||||
if (message->OrangeChromaPlaneByteCount)
|
||||
Stream_Write(s, message->PlaneBuffers[1],
|
||||
message->OrangeChromaPlaneByteCount); /* OrangeChromaPlane */
|
||||
|
||||
if (message->GreenChromaPlaneByteCount)
|
||||
Stream_Write(s, message->PlaneBuffers[2],
|
||||
message->GreenChromaPlaneByteCount); /* GreenChromaPlane */
|
||||
|
||||
if (message->AlphaPlaneByteCount)
|
||||
Stream_Write(s, message->PlaneBuffers[3], message->AlphaPlaneByteCount); /* AlphaPlane */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL nsc_compose_message(NSC_CONTEXT* WINPR_RESTRICT context, wStream* WINPR_RESTRICT s,
|
||||
const BYTE* WINPR_RESTRICT data, UINT32 width, UINT32 height,
|
||||
UINT32 scanline)
|
||||
{
|
||||
BOOL rc = 0;
|
||||
NSC_MESSAGE message = WINPR_C_ARRAY_INIT;
|
||||
|
||||
if (!context || !s || !data)
|
||||
return FALSE;
|
||||
|
||||
if (scanline == 0)
|
||||
scanline = width * FreeRDPGetBytesPerPixel(context->format);
|
||||
|
||||
context->width = WINPR_ASSERTING_INT_CAST(UINT16, width);
|
||||
context->height = WINPR_ASSERTING_INT_CAST(UINT16, height);
|
||||
|
||||
if (!nsc_context_initialize_encode(context))
|
||||
return FALSE;
|
||||
|
||||
/* ARGB to AYCoCg conversion, chroma subsampling and colorloss reduction */
|
||||
PROFILER_ENTER(context->priv->prof_nsc_encode)
|
||||
rc = context->encode(context, data, scanline);
|
||||
PROFILER_EXIT(context->priv->prof_nsc_encode)
|
||||
if (!rc)
|
||||
return FALSE;
|
||||
|
||||
/* RLE encode */
|
||||
PROFILER_ENTER(context->priv->prof_nsc_rle_compress_data)
|
||||
nsc_rle_compress_data(context);
|
||||
PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data)
|
||||
message.PlaneBuffers[0] = context->priv->PlaneBuffers[0];
|
||||
message.PlaneBuffers[1] = context->priv->PlaneBuffers[1];
|
||||
message.PlaneBuffers[2] = context->priv->PlaneBuffers[2];
|
||||
message.PlaneBuffers[3] = context->priv->PlaneBuffers[3];
|
||||
message.LumaPlaneByteCount = context->PlaneByteCount[0];
|
||||
message.OrangeChromaPlaneByteCount = context->PlaneByteCount[1];
|
||||
message.GreenChromaPlaneByteCount = context->PlaneByteCount[2];
|
||||
message.AlphaPlaneByteCount = context->PlaneByteCount[3];
|
||||
|
||||
message.ColorLossLevel = WINPR_ASSERTING_INT_CAST(BYTE, context->ColorLossLevel);
|
||||
message.ChromaSubsamplingLevel =
|
||||
WINPR_ASSERTING_INT_CAST(BYTE, context->ChromaSubsamplingLevel);
|
||||
return nsc_write_message(context, s, &message);
|
||||
}
|
||||
|
||||
#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
|
||||
BOOL nsc_decompose_message(NSC_CONTEXT* WINPR_RESTRICT context, wStream* WINPR_RESTRICT s,
|
||||
BYTE* WINPR_RESTRICT bmpdata, UINT32 x, UINT32 y, UINT32 width,
|
||||
UINT32 height, UINT32 rowstride, UINT32 format, UINT32 flip)
|
||||
{
|
||||
size_t size = Stream_GetRemainingLength(s);
|
||||
|
||||
if (size > UINT32_MAX)
|
||||
return FALSE;
|
||||
|
||||
if (!nsc_process_message(context, (UINT16)FreeRDPGetBitsPerPixel(context->format), width,
|
||||
height, Stream_Pointer(s), (UINT32)size, bmpdata, format, rowstride, x,
|
||||
y, width, height, flip))
|
||||
return FALSE;
|
||||
Stream_Seek(s, size);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* NSCodec Encoder
|
||||
*
|
||||
* Copyright 2012 Vic Lee
|
||||
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2016 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 FREERDP_LIB_CODEC_NSC_ENCODE_H
|
||||
#define FREERDP_LIB_CODEC_NSC_ENCODE_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/codec/nsc.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL nsc_encode(NSC_CONTEXT* WINPR_RESTRICT context,
|
||||
const BYTE* WINPR_RESTRICT bmpdata, UINT32 rowstride);
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_NSC_ENCODE_H */
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* NSCodec Library
|
||||
*
|
||||
* Copyright 2011 Samsung, Author Jiten Pathy
|
||||
* Copyright 2012 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 FREERDP_LIB_CODEC_NSC_TYPES_H
|
||||
#define FREERDP_LIB_CODEC_NSC_TYPES_H
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/utils/profiler.h>
|
||||
#include <freerdp/codec/nsc.h>
|
||||
|
||||
#define ROUND_UP_TO(_b, _n) (_b + ((~(_b & (_n - 1)) + 0x1) & (_n - 1)))
|
||||
#define MINMAX(_v, _l, _h) \
|
||||
((_v) < (_l) ? WINPR_ASSERTING_INT_CAST(BYTE, (_l)) \
|
||||
: ((_v) > (_h) ? WINPR_ASSERTING_INT_CAST(BYTE, (_h)) \
|
||||
: WINPR_ASSERTING_INT_CAST(BYTE, (_v))))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
wLog* log;
|
||||
|
||||
BYTE* PlaneBuffers[5]; /* Decompressed Plane Buffers in the respective order */
|
||||
UINT32 PlaneBuffersLength; /* Lengths of each plane buffer */
|
||||
|
||||
/* profilers */
|
||||
PROFILER_DEFINE(prof_nsc_rle_decompress_data)
|
||||
PROFILER_DEFINE(prof_nsc_decode)
|
||||
PROFILER_DEFINE(prof_nsc_rle_compress_data)
|
||||
PROFILER_DEFINE(prof_nsc_encode)
|
||||
} NSC_CONTEXT_PRIV;
|
||||
|
||||
struct S_NSC_CONTEXT
|
||||
{
|
||||
UINT32 OrgByteCount[4];
|
||||
UINT32 format;
|
||||
UINT16 width;
|
||||
UINT16 height;
|
||||
BYTE* BitmapData;
|
||||
size_t BitmapDataLength;
|
||||
|
||||
BYTE* Planes;
|
||||
size_t PlanesSize;
|
||||
UINT32 PlaneByteCount[4];
|
||||
UINT32 ColorLossLevel;
|
||||
UINT32 ChromaSubsamplingLevel;
|
||||
BOOL DynamicColorFidelity;
|
||||
|
||||
/* color palette allocated by the application */
|
||||
const BYTE* palette;
|
||||
|
||||
WINPR_ATTR_NODISCARD BOOL (*decode)(NSC_CONTEXT* WINPR_RESTRICT context);
|
||||
WINPR_ATTR_NODISCARD BOOL (*encode)(NSC_CONTEXT* WINPR_RESTRICT context,
|
||||
const BYTE* WINPR_RESTRICT BitmapData, UINT32 rowstride);
|
||||
|
||||
NSC_CONTEXT_PRIV* priv;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_NSC_TYPES_H */
|
||||
+1820
File diff suppressed because it is too large
Load Diff
+2654
File diff suppressed because it is too large
Load Diff
+235
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Progressive Codec Bitmap Compression
|
||||
*
|
||||
* Copyright 2017 Armin Novak <anovak@thincast.com>
|
||||
* Copyright 2017 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 INTERNAL_CODEC_PROGRESSIVE_H
|
||||
#define INTERNAL_CODEC_PROGRESSIVE_H
|
||||
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/pool.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
|
||||
#define RFX_SUBBAND_DIFFING 0x01
|
||||
|
||||
#define RFX_TILE_DIFFERENCE 0x01
|
||||
|
||||
#define RFX_DWT_REDUCE_EXTRAPOLATE 0x01
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE LL3;
|
||||
BYTE HL3;
|
||||
BYTE LH3;
|
||||
BYTE HH3;
|
||||
BYTE HL2;
|
||||
BYTE LH2;
|
||||
BYTE HH2;
|
||||
BYTE HL1;
|
||||
BYTE LH1;
|
||||
BYTE HH1;
|
||||
} RFX_COMPONENT_CODEC_QUANT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE quality;
|
||||
RFX_COMPONENT_CODEC_QUANT yQuantValues;
|
||||
RFX_COMPONENT_CODEC_QUANT cbQuantValues;
|
||||
RFX_COMPONENT_CODEC_QUANT crQuantValues;
|
||||
} RFX_PROGRESSIVE_CODEC_QUANT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 blockType;
|
||||
UINT32 blockLen;
|
||||
} PROGRESSIVE_BLOCK;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 blockType;
|
||||
UINT32 blockLen;
|
||||
|
||||
UINT32 magic;
|
||||
UINT16 version;
|
||||
} PROGRESSIVE_BLOCK_SYNC;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 blockType;
|
||||
UINT32 blockLen;
|
||||
|
||||
BYTE ctxId;
|
||||
UINT16 tileSize;
|
||||
BYTE flags;
|
||||
} PROGRESSIVE_BLOCK_CONTEXT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 blockType;
|
||||
UINT32 blockLen;
|
||||
|
||||
BYTE quantIdxY;
|
||||
BYTE quantIdxCb;
|
||||
BYTE quantIdxCr;
|
||||
UINT16 xIdx;
|
||||
UINT16 yIdx;
|
||||
|
||||
BYTE flags;
|
||||
BYTE quality;
|
||||
BOOL dirty;
|
||||
|
||||
UINT16 yLen;
|
||||
UINT16 cbLen;
|
||||
UINT16 crLen;
|
||||
UINT16 tailLen;
|
||||
const BYTE* yData;
|
||||
const BYTE* cbData;
|
||||
const BYTE* crData;
|
||||
const BYTE* tailData;
|
||||
|
||||
UINT16 ySrlLen;
|
||||
UINT16 yRawLen;
|
||||
UINT16 cbSrlLen;
|
||||
UINT16 cbRawLen;
|
||||
UINT16 crSrlLen;
|
||||
UINT16 crRawLen;
|
||||
const BYTE* ySrlData;
|
||||
const BYTE* yRawData;
|
||||
const BYTE* cbSrlData;
|
||||
const BYTE* cbRawData;
|
||||
const BYTE* crSrlData;
|
||||
const BYTE* crRawData;
|
||||
|
||||
UINT32 x;
|
||||
UINT32 y;
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
UINT32 stride;
|
||||
|
||||
BYTE* data;
|
||||
BYTE* current;
|
||||
|
||||
UINT16 pass;
|
||||
BYTE* sign;
|
||||
|
||||
RFX_COMPONENT_CODEC_QUANT yBitPos;
|
||||
RFX_COMPONENT_CODEC_QUANT cbBitPos;
|
||||
RFX_COMPONENT_CODEC_QUANT crBitPos;
|
||||
RFX_COMPONENT_CODEC_QUANT yQuant;
|
||||
RFX_COMPONENT_CODEC_QUANT cbQuant;
|
||||
RFX_COMPONENT_CODEC_QUANT crQuant;
|
||||
RFX_COMPONENT_CODEC_QUANT yProgQuant;
|
||||
RFX_COMPONENT_CODEC_QUANT cbProgQuant;
|
||||
RFX_COMPONENT_CODEC_QUANT crProgQuant;
|
||||
} RFX_PROGRESSIVE_TILE;
|
||||
|
||||
typedef struct S_PROGRESSIVE_CONTEXT PROGRESSIVE_CONTEXT;
|
||||
typedef struct S_PROGRESSIVE_BLOCK_REGION PROGRESSIVE_BLOCK_REGION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PROGRESSIVE_CONTEXT* progressive;
|
||||
PROGRESSIVE_BLOCK_REGION* region;
|
||||
const PROGRESSIVE_BLOCK_CONTEXT* context;
|
||||
RFX_PROGRESSIVE_TILE* tile;
|
||||
} PROGRESSIVE_TILE_PROCESS_WORK_PARAM;
|
||||
|
||||
struct S_PROGRESSIVE_BLOCK_REGION
|
||||
{
|
||||
UINT16 blockType;
|
||||
UINT32 blockLen;
|
||||
|
||||
BYTE tileSize;
|
||||
UINT16 numRects;
|
||||
BYTE numQuant;
|
||||
BYTE numProgQuant;
|
||||
BYTE flags;
|
||||
UINT16 numTiles;
|
||||
UINT16 usedTiles;
|
||||
UINT32 tileDataSize;
|
||||
RFX_RECT rects[0x10000];
|
||||
RFX_COMPONENT_CODEC_QUANT quantVals[0x100];
|
||||
RFX_PROGRESSIVE_CODEC_QUANT quantProgVals[0x100];
|
||||
RFX_PROGRESSIVE_TILE* tiles[0x10000];
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 blockType;
|
||||
UINT32 blockLen;
|
||||
|
||||
UINT32 frameIndex;
|
||||
UINT16 regionCount;
|
||||
PROGRESSIVE_BLOCK_REGION* regions;
|
||||
} PROGRESSIVE_BLOCK_FRAME_BEGIN;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 blockType;
|
||||
UINT32 blockLen;
|
||||
} PROGRESSIVE_BLOCK_FRAME_END;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 id;
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
UINT32 gridWidth;
|
||||
UINT32 gridHeight;
|
||||
UINT32 gridSize;
|
||||
RFX_PROGRESSIVE_TILE** tiles;
|
||||
size_t tilesSize;
|
||||
UINT32 frameId;
|
||||
UINT32 numUpdatedTiles;
|
||||
UINT32* updatedTileIndices;
|
||||
} PROGRESSIVE_SURFACE_CONTEXT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FLAG_WBT_SYNC = 0x01,
|
||||
FLAG_WBT_FRAME_BEGIN = 0x02,
|
||||
FLAG_WBT_FRAME_END = 0x04,
|
||||
FLAG_WBT_CONTEXT = 0x08,
|
||||
FLAG_WBT_REGION = 0x10
|
||||
} WBT_STATE_FLAG;
|
||||
|
||||
struct S_PROGRESSIVE_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
|
||||
wBufferPool* bufferPool;
|
||||
|
||||
UINT32 format;
|
||||
UINT32 state;
|
||||
|
||||
PROGRESSIVE_BLOCK_CONTEXT context;
|
||||
PROGRESSIVE_BLOCK_REGION region;
|
||||
RFX_PROGRESSIVE_CODEC_QUANT quantProgValFull;
|
||||
|
||||
wHashTable* SurfaceContexts;
|
||||
wLog* log;
|
||||
wStream* buffer;
|
||||
wStream* rects;
|
||||
RFX_CONTEXT* rfx_context;
|
||||
PROGRESSIVE_TILE_PROCESS_WORK_PARAM params[0x10000];
|
||||
PTP_WORK work_objects[0x10000];
|
||||
};
|
||||
|
||||
#endif /* INTERNAL_CODEC_PROGRESSIVE_H */
|
||||
+885
@@ -0,0 +1,885 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 Thincast Technologies GmbH
|
||||
* Copyright 2014 Hardening <contact@hardening-consulting.com>
|
||||
* Copyright 2017 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2017 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <winpr/assert.h>
|
||||
#include <winpr/memory.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/region.h>
|
||||
|
||||
#define TAG FREERDP_TAG("codec")
|
||||
|
||||
/*
|
||||
* The functions in this file implement the Region abstraction largely inspired from
|
||||
* pixman library. The following comment is taken from the pixman code.
|
||||
*
|
||||
* A Region is simply a set of disjoint(non-overlapping) rectangles, plus an
|
||||
* "extent" rectangle which is the smallest single rectangle that contains all
|
||||
* the non-overlapping rectangles.
|
||||
*
|
||||
* A Region is implemented as a "y-x-banded" array of rectangles. This array
|
||||
* imposes two degrees of order. First, all rectangles are sorted by top side
|
||||
* y coordinate first (y1), and then by left side x coordinate (x1).
|
||||
*
|
||||
* Furthermore, the rectangles are grouped into "bands". Each rectangle in a
|
||||
* band has the same top y coordinate (y1), and each has the same bottom y
|
||||
* coordinate (y2). Thus all rectangles in a band differ only in their left
|
||||
* and right side (x1 and x2). Bands are implicit in the array of rectangles:
|
||||
* there is no separate list of band start pointers.
|
||||
*
|
||||
* The y-x band representation does not minimize rectangles. In particular,
|
||||
* if a rectangle vertically crosses a band (the rectangle has scanlines in
|
||||
* the y1 to y2 area spanned by the band), then the rectangle may be broken
|
||||
* down into two or more smaller rectangles stacked one atop the other.
|
||||
*
|
||||
* ----------- -----------
|
||||
* | | | | band 0
|
||||
* | | -------- ----------- --------
|
||||
* | | | | in y-x banded | | | | band 1
|
||||
* | | | | form is | | | |
|
||||
* ----------- | | ----------- --------
|
||||
* | | | | band 2
|
||||
* -------- --------
|
||||
*
|
||||
* An added constraint on the rectangles is that they must cover as much
|
||||
* horizontal area as possible: no two rectangles within a band are allowed
|
||||
* to touch.
|
||||
*
|
||||
* Whenever possible, bands will be merged together to cover a greater vertical
|
||||
* distance (and thus reduce the number of rectangles). Two bands can be merged
|
||||
* only if the bottom of one touches the top of the other and they have
|
||||
* rectangles in the same places (of the same width, of course).
|
||||
*/
|
||||
|
||||
struct S_REGION16_DATA
|
||||
{
|
||||
size_t nbRects;
|
||||
RECTANGLE_16* rects;
|
||||
};
|
||||
|
||||
void region16_init(REGION16* region)
|
||||
{
|
||||
WINPR_ASSERT(region);
|
||||
|
||||
const REGION16 empty = WINPR_C_ARRAY_INIT;
|
||||
*region = empty;
|
||||
}
|
||||
|
||||
int region16_n_rects(const REGION16* region)
|
||||
{
|
||||
WINPR_ASSERT(region);
|
||||
if (!region->data)
|
||||
return 0;
|
||||
|
||||
return WINPR_ASSERTING_INT_CAST(int, region->data->nbRects);
|
||||
}
|
||||
|
||||
const RECTANGLE_16* region16_rects(const REGION16* region, UINT32* nbRects)
|
||||
{
|
||||
if (nbRects)
|
||||
*nbRects = 0;
|
||||
|
||||
if (!region)
|
||||
return nullptr;
|
||||
|
||||
REGION16_DATA* data = region->data;
|
||||
if (!data)
|
||||
return nullptr;
|
||||
|
||||
if (nbRects)
|
||||
*nbRects = WINPR_ASSERTING_INT_CAST(UINT32, data->nbRects);
|
||||
|
||||
return data->rects;
|
||||
}
|
||||
|
||||
static inline RECTANGLE_16* region16_rects_noconst(REGION16* region)
|
||||
{
|
||||
WINPR_ASSERT(region);
|
||||
|
||||
REGION16_DATA* data = region->data;
|
||||
|
||||
if (!data)
|
||||
return nullptr;
|
||||
|
||||
return data->rects;
|
||||
}
|
||||
|
||||
const RECTANGLE_16* region16_extents(const REGION16* region)
|
||||
{
|
||||
if (!region)
|
||||
return nullptr;
|
||||
|
||||
return ®ion->extents;
|
||||
}
|
||||
|
||||
static RECTANGLE_16* region16_extents_noconst(REGION16* region)
|
||||
{
|
||||
if (!region)
|
||||
return nullptr;
|
||||
|
||||
return ®ion->extents;
|
||||
}
|
||||
|
||||
BOOL rectangle_is_empty(const RECTANGLE_16* rect)
|
||||
{
|
||||
WINPR_ASSERT(rect);
|
||||
|
||||
/* A rectangle with width <= 0 or height <= 0 should be regarded
|
||||
* as empty.
|
||||
*/
|
||||
return ((rect->left >= rect->right) || (rect->top >= rect->bottom));
|
||||
}
|
||||
|
||||
BOOL region16_is_empty(const REGION16* region)
|
||||
{
|
||||
WINPR_ASSERT(region);
|
||||
if (!region->data)
|
||||
return TRUE;
|
||||
return (region->data->nbRects == 0);
|
||||
}
|
||||
|
||||
BOOL rectangles_equal(const RECTANGLE_16* r1, const RECTANGLE_16* r2)
|
||||
{
|
||||
WINPR_ASSERT(r1);
|
||||
WINPR_ASSERT(r2);
|
||||
|
||||
return ((r1->left == r2->left) && (r1->top == r2->top) && (r1->right == r2->right) &&
|
||||
(r1->bottom == r2->bottom));
|
||||
}
|
||||
|
||||
BOOL rectangles_intersects(const RECTANGLE_16* r1, const RECTANGLE_16* r2)
|
||||
{
|
||||
RECTANGLE_16 tmp = WINPR_C_ARRAY_INIT;
|
||||
return rectangles_intersection(r1, r2, &tmp);
|
||||
}
|
||||
|
||||
BOOL rectangles_intersection(const RECTANGLE_16* r1, const RECTANGLE_16* r2, RECTANGLE_16* dst)
|
||||
{
|
||||
WINPR_ASSERT(r1);
|
||||
WINPR_ASSERT(r2);
|
||||
WINPR_ASSERT(dst);
|
||||
|
||||
dst->left = MAX(r1->left, r2->left);
|
||||
dst->right = MIN(r1->right, r2->right);
|
||||
dst->top = MAX(r1->top, r2->top);
|
||||
dst->bottom = MIN(r1->bottom, r2->bottom);
|
||||
return (dst->left < dst->right) && (dst->top < dst->bottom);
|
||||
}
|
||||
|
||||
static void freeRegion(REGION16_DATA* data)
|
||||
{
|
||||
if (data)
|
||||
free(data->rects);
|
||||
free(data);
|
||||
}
|
||||
|
||||
void region16_clear(REGION16* region)
|
||||
{
|
||||
WINPR_ASSERT(region);
|
||||
|
||||
freeRegion(region->data);
|
||||
region->data = nullptr;
|
||||
|
||||
const RECTANGLE_16 empty = WINPR_C_ARRAY_INIT;
|
||||
region->extents = empty;
|
||||
}
|
||||
|
||||
WINPR_ATTR_MALLOC(freeRegion, 1)
|
||||
WINPR_ATTR_NODISCARD
|
||||
static REGION16_DATA* allocateRegion(size_t nbItems)
|
||||
{
|
||||
REGION16_DATA* data = calloc(1, sizeof(REGION16_DATA));
|
||||
if (!data)
|
||||
return nullptr;
|
||||
|
||||
if (nbItems > 0)
|
||||
{
|
||||
data->rects = calloc(nbItems, sizeof(RECTANGLE_16));
|
||||
if (!data->rects)
|
||||
{
|
||||
free(data);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
data->nbRects = nbItems;
|
||||
return data;
|
||||
}
|
||||
|
||||
static inline RECTANGLE_16* nextRect(REGION16_DATA* data, size_t index)
|
||||
{
|
||||
WINPR_ASSERT(data);
|
||||
if (index + 1 > data->nbRects)
|
||||
{
|
||||
RECTANGLE_16* rects = realloc(data->rects, (index + 1) * sizeof(RECTANGLE_16));
|
||||
if (!rects)
|
||||
{
|
||||
freeRegion(data);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const RECTANGLE_16 empty = WINPR_C_ARRAY_INIT;
|
||||
rects[index] = empty;
|
||||
data->nbRects = index + 1;
|
||||
data->rects = rects;
|
||||
}
|
||||
return &data->rects[index];
|
||||
}
|
||||
|
||||
static BOOL resizeRegion(REGION16* region, size_t nbItems)
|
||||
{
|
||||
WINPR_ASSERT(region);
|
||||
if (nbItems == 0)
|
||||
{
|
||||
freeRegion(region->data);
|
||||
region->data = nullptr;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!region->data)
|
||||
{
|
||||
region->data = allocateRegion(nbItems);
|
||||
return region->data != nullptr;
|
||||
}
|
||||
|
||||
RECTANGLE_16* rects = realloc(region->data->rects, nbItems * sizeof(RECTANGLE_16));
|
||||
if (!rects)
|
||||
{
|
||||
free(region->data->rects);
|
||||
region->data->nbRects = 0;
|
||||
region->data->rects = nullptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (size_t x = region->data->nbRects; x < nbItems; x++)
|
||||
{
|
||||
const RECTANGLE_16 empty = WINPR_C_ARRAY_INIT;
|
||||
rects[x] = empty;
|
||||
}
|
||||
region->data->rects = rects;
|
||||
region->data->nbRects = nbItems;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline BOOL region16_copy_data(REGION16* dst, const REGION16* src)
|
||||
{
|
||||
WINPR_ASSERT(dst);
|
||||
WINPR_ASSERT(src);
|
||||
|
||||
freeRegion(dst->data);
|
||||
dst->data = nullptr;
|
||||
|
||||
if (src->data && (src->data->nbRects > 0))
|
||||
{
|
||||
dst->data = allocateRegion(src->data->nbRects);
|
||||
if (!dst->data || !dst->data->rects)
|
||||
return FALSE;
|
||||
memcpy(dst->data->rects, src->data->rects, dst->data->nbRects * sizeof(RECTANGLE_16));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL region16_copy(REGION16* dst, const REGION16* src)
|
||||
{
|
||||
if (dst == src)
|
||||
return TRUE;
|
||||
|
||||
WINPR_ASSERT(dst);
|
||||
WINPR_ASSERT(src);
|
||||
|
||||
dst->extents = src->extents;
|
||||
|
||||
return region16_copy_data(dst, src);
|
||||
}
|
||||
|
||||
void region16_print(const REGION16* region)
|
||||
{
|
||||
UINT32 nbRects = 0;
|
||||
int currentBandY = -1;
|
||||
const RECTANGLE_16* rects = region16_rects(region, &nbRects);
|
||||
|
||||
WLog_DBG(TAG, "nrects=%" PRIu32 "", nbRects);
|
||||
|
||||
for (UINT32 i = 0; i < nbRects; i++)
|
||||
{
|
||||
const RECTANGLE_16* rect = &rects[i];
|
||||
|
||||
if (rect->top != currentBandY)
|
||||
{
|
||||
currentBandY = rect->top;
|
||||
WLog_DBG(TAG, "band %d: ", currentBandY);
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "(%" PRIu16 ",%" PRIu16 "-%" PRIu16 ",%" PRIu16 ")", rect->left, rect->top,
|
||||
rect->right, rect->bottom);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL region16_copy_band_with_union(REGION16_DATA* region, const RECTANGLE_16* src,
|
||||
const RECTANGLE_16* end, UINT16 newTop, UINT16 newBottom,
|
||||
const RECTANGLE_16* unionRect, UINT32* dstCounter,
|
||||
const RECTANGLE_16** srcPtr)
|
||||
{
|
||||
WINPR_ASSERT(region);
|
||||
WINPR_ASSERT(src);
|
||||
WINPR_ASSERT(end);
|
||||
WINPR_ASSERT(dstCounter);
|
||||
|
||||
UINT16 refY = src->top;
|
||||
|
||||
/* merges a band with the given rect
|
||||
* Input:
|
||||
* unionRect
|
||||
* | |
|
||||
* | |
|
||||
* ==============+===============+================================
|
||||
* |Item1| |Item2| |Item3| |Item4| |Item5| Band
|
||||
* ==============+===============+================================
|
||||
* before | overlap | after
|
||||
*
|
||||
* Resulting band:
|
||||
* +-----+ +----------------------+ +-----+
|
||||
* |Item1| | Item2 | |Item3|
|
||||
* +-----+ +----------------------+ +-----+
|
||||
*
|
||||
* We first copy as-is items that are before Item2, the first overlapping
|
||||
* item.
|
||||
* Then we find the last one that overlap unionRect to aggregate Item2, Item3
|
||||
* and Item4 to create Item2.
|
||||
* Finally Item5 is copied as Item3.
|
||||
*
|
||||
* When no unionRect is provided, we skip the two first steps to just copy items
|
||||
*/
|
||||
|
||||
if (unionRect)
|
||||
{
|
||||
/* items before unionRect */
|
||||
while ((src < end) && (src->top == refY) && (src->right < unionRect->left))
|
||||
{
|
||||
RECTANGLE_16* dst = nextRect(region, (*dstCounter)++);
|
||||
if (!dst)
|
||||
return FALSE;
|
||||
dst->top = newTop;
|
||||
dst->bottom = newBottom;
|
||||
dst->right = src->right;
|
||||
dst->left = src->left;
|
||||
src++;
|
||||
}
|
||||
|
||||
/* treat items overlapping with unionRect */
|
||||
const RECTANGLE_16* startOverlap = unionRect;
|
||||
const RECTANGLE_16* endOverlap = unionRect;
|
||||
|
||||
if ((src < end) && (src->top == refY) && (src->left < unionRect->left))
|
||||
startOverlap = src;
|
||||
|
||||
while ((src < end) && (src->top == refY) && (src->right < unionRect->right))
|
||||
{
|
||||
src++;
|
||||
}
|
||||
|
||||
if ((src < end) && (src->top == refY) && (src->left < unionRect->right))
|
||||
{
|
||||
endOverlap = src;
|
||||
src++;
|
||||
}
|
||||
|
||||
{
|
||||
RECTANGLE_16* dst = nextRect(region, (*dstCounter)++);
|
||||
if (!dst)
|
||||
return FALSE;
|
||||
dst->bottom = newBottom;
|
||||
dst->top = newTop;
|
||||
dst->left = startOverlap->left;
|
||||
dst->right = endOverlap->right;
|
||||
}
|
||||
}
|
||||
|
||||
/* treat remaining items on the same band */
|
||||
while ((src < end) && (src->top == refY))
|
||||
{
|
||||
RECTANGLE_16* dst = nextRect(region, (*dstCounter)++);
|
||||
if (!dst)
|
||||
return FALSE;
|
||||
|
||||
dst->top = newTop;
|
||||
dst->bottom = newBottom;
|
||||
dst->right = src->right;
|
||||
dst->left = src->left;
|
||||
src++;
|
||||
}
|
||||
|
||||
if (srcPtr)
|
||||
*srcPtr = src;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static RECTANGLE_16* next_band(RECTANGLE_16* band1, RECTANGLE_16* endPtr, int* nbItems)
|
||||
{
|
||||
WINPR_ASSERT(band1);
|
||||
WINPR_ASSERT(endPtr);
|
||||
WINPR_ASSERT(nbItems);
|
||||
|
||||
UINT16 refY = band1->top;
|
||||
*nbItems = 0;
|
||||
|
||||
while ((band1 < endPtr) && (band1->top == refY))
|
||||
{
|
||||
band1++;
|
||||
*nbItems += 1;
|
||||
}
|
||||
|
||||
return band1;
|
||||
}
|
||||
|
||||
static BOOL band_match(const RECTANGLE_16* band1, const RECTANGLE_16* band2,
|
||||
const RECTANGLE_16* endPtr)
|
||||
{
|
||||
int refBand2 = band2->top;
|
||||
const RECTANGLE_16* band2Start = band2;
|
||||
|
||||
while ((band1 < band2Start) && (band2 < endPtr) && (band2->top == refBand2))
|
||||
{
|
||||
if ((band1->left != band2->left) || (band1->right != band2->right))
|
||||
return FALSE;
|
||||
|
||||
band1++;
|
||||
band2++;
|
||||
}
|
||||
|
||||
if (band1 != band2Start)
|
||||
return FALSE;
|
||||
|
||||
return (band2 == endPtr) || (band2->top != refBand2);
|
||||
}
|
||||
|
||||
/** compute if the rectangle is fully included in the band
|
||||
* @param band a pointer on the beginning of the band
|
||||
* @param endPtr end of the region
|
||||
* @param rect the rectangle to test
|
||||
* @return if rect is fully included in an item of the band
|
||||
*/
|
||||
static BOOL rectangle_contained_in_band(const RECTANGLE_16* band, const RECTANGLE_16* endPtr,
|
||||
const RECTANGLE_16* rect)
|
||||
{
|
||||
WINPR_ASSERT(band);
|
||||
WINPR_ASSERT(endPtr);
|
||||
WINPR_ASSERT(rect);
|
||||
|
||||
UINT16 refY = band->top;
|
||||
|
||||
if ((band->top > rect->top) || (rect->bottom > band->bottom))
|
||||
return FALSE;
|
||||
|
||||
/* note: as the band is sorted from left to right, once we've seen an item
|
||||
* that is after rect->left we're sure that the result is False.
|
||||
*/
|
||||
while ((band < endPtr) && (band->top == refY) && (band->left <= rect->left))
|
||||
{
|
||||
if (rect->right <= band->right)
|
||||
return TRUE;
|
||||
|
||||
band++;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL region16_simplify_bands(REGION16* region)
|
||||
{
|
||||
/** Simplify consecutive bands that touch and have the same items
|
||||
*
|
||||
* ==================== ====================
|
||||
* | 1 | | 2 | | | | |
|
||||
* ==================== | | | |
|
||||
* | 1 | | 2 | ====> | 1 | | 2 |
|
||||
* ==================== | | | |
|
||||
* | 1 | | 2 | | | | |
|
||||
* ==================== ====================
|
||||
*
|
||||
*/
|
||||
|
||||
const int nbRects = region16_n_rects(region);
|
||||
int finalNbRects = nbRects;
|
||||
|
||||
if (nbRects < 2)
|
||||
return TRUE;
|
||||
|
||||
RECTANGLE_16* band1 = region16_rects_noconst(region);
|
||||
RECTANGLE_16* endPtr = band1 + nbRects;
|
||||
|
||||
do
|
||||
{
|
||||
int bandItems = 0;
|
||||
RECTANGLE_16* band2 = next_band(band1, endPtr, &bandItems);
|
||||
|
||||
if (band2 == endPtr)
|
||||
break;
|
||||
|
||||
if ((band1->bottom == band2->top) && band_match(band1, band2, endPtr))
|
||||
{
|
||||
/* adjust the bottom of band1 items */
|
||||
RECTANGLE_16* tmp = band1;
|
||||
|
||||
while (tmp < band2)
|
||||
{
|
||||
tmp->bottom = band2->bottom;
|
||||
tmp++;
|
||||
}
|
||||
|
||||
/* override band2, we don't move band1 pointer as the band after band2
|
||||
* may be merged too */
|
||||
const RECTANGLE_16* endBand = band2 + bandItems;
|
||||
const size_t toMove =
|
||||
WINPR_ASSERTING_INT_CAST(size_t, (endPtr - endBand)) * sizeof(RECTANGLE_16);
|
||||
|
||||
if (toMove)
|
||||
MoveMemory(band2, endBand, toMove);
|
||||
|
||||
finalNbRects -= bandItems;
|
||||
endPtr -= bandItems;
|
||||
}
|
||||
else
|
||||
{
|
||||
band1 = band2;
|
||||
}
|
||||
} while (TRUE);
|
||||
|
||||
if (finalNbRects != nbRects)
|
||||
{
|
||||
if (!resizeRegion(region, WINPR_ASSERTING_INT_CAST(size_t, finalNbRects)))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL region16_union_rect(REGION16* dst, const REGION16* src, const RECTANGLE_16* rect)
|
||||
{
|
||||
const RECTANGLE_16* nextBand = nullptr;
|
||||
UINT32 srcNbRects = 0;
|
||||
UINT16 topInterBand = 0;
|
||||
WINPR_ASSERT(src);
|
||||
WINPR_ASSERT(dst);
|
||||
|
||||
const RECTANGLE_16* srcExtents = region16_extents(src);
|
||||
RECTANGLE_16* dstExtents = region16_extents_noconst(dst);
|
||||
|
||||
const int nrSrcRects = region16_n_rects(src);
|
||||
if (nrSrcRects == 0)
|
||||
{
|
||||
/* source is empty, so the union is rect */
|
||||
dst->extents = *rect;
|
||||
|
||||
if (!resizeRegion(dst, 1))
|
||||
return FALSE;
|
||||
|
||||
RECTANGLE_16* dstRect = region16_rects_noconst(dst);
|
||||
WINPR_ASSERT(dstRect);
|
||||
|
||||
dstRect->top = rect->top;
|
||||
dstRect->left = rect->left;
|
||||
dstRect->right = rect->right;
|
||||
dstRect->bottom = rect->bottom;
|
||||
dst->data->nbRects = 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
REGION16_DATA* newItems = allocateRegion(WINPR_ASSERTING_INT_CAST(size_t, nrSrcRects + 1));
|
||||
|
||||
if (!newItems)
|
||||
return FALSE;
|
||||
|
||||
UINT32 usedRects = 0;
|
||||
|
||||
/* adds the piece of rect that is on the top of src */
|
||||
if (rect->top < srcExtents->top)
|
||||
{
|
||||
RECTANGLE_16* dstRect = nextRect(newItems, usedRects++);
|
||||
if (!dstRect)
|
||||
return FALSE;
|
||||
|
||||
dstRect->top = rect->top;
|
||||
dstRect->left = rect->left;
|
||||
dstRect->right = rect->right;
|
||||
dstRect->bottom = MIN(srcExtents->top, rect->bottom);
|
||||
}
|
||||
|
||||
/* treat possibly overlapping region */
|
||||
const RECTANGLE_16* currentBand = region16_rects(src, &srcNbRects);
|
||||
const RECTANGLE_16* endSrcRect = currentBand + srcNbRects;
|
||||
|
||||
while (currentBand < endSrcRect)
|
||||
{
|
||||
if ((currentBand->bottom <= rect->top) || (rect->bottom <= currentBand->top) ||
|
||||
rectangle_contained_in_band(currentBand, endSrcRect, rect))
|
||||
{
|
||||
/* no overlap between rect and the band, rect is totally below or totally above
|
||||
* the current band, or rect is already covered by an item of the band.
|
||||
* let's copy all the rectangles from this band
|
||||
+----+
|
||||
| | rect (case 1)
|
||||
+----+
|
||||
|
||||
=================
|
||||
band of srcRect
|
||||
=================
|
||||
+----+
|
||||
| | rect (case 2)
|
||||
+----+
|
||||
*/
|
||||
if (!region16_copy_band_with_union(newItems, currentBand, endSrcRect, currentBand->top,
|
||||
currentBand->bottom, nullptr, &usedRects, &nextBand))
|
||||
return FALSE;
|
||||
topInterBand = rect->top;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* rect overlaps the band:
|
||||
| | | |
|
||||
====^=================| |==| |=========================== band
|
||||
| top split | | | |
|
||||
v | 1 | | 2 |
|
||||
^ | | | | +----+ +----+
|
||||
| merge zone | | | | | | | 4 |
|
||||
v +----+ | | | | +----+
|
||||
^ | | | 3 |
|
||||
| bottom split | | | |
|
||||
====v=========================| |==| |===================
|
||||
| | | |
|
||||
|
||||
possible cases:
|
||||
1) no top split, merge zone then a bottom split. The band will be split
|
||||
in two
|
||||
2) not band split, only the merge zone, band merged with rect but not split
|
||||
3) a top split, the merge zone and no bottom split. The band will be split
|
||||
in two
|
||||
4) a top split, the merge zone and also a bottom split. The band will be
|
||||
split in 3, but the coalesce algorithm may merge the created bands
|
||||
*/
|
||||
UINT16 mergeTop = currentBand->top;
|
||||
UINT16 mergeBottom = currentBand->bottom;
|
||||
|
||||
/* test if we need a top split, case 3 and 4 */
|
||||
if (rect->top > currentBand->top)
|
||||
{
|
||||
if (!region16_copy_band_with_union(newItems, currentBand, endSrcRect,
|
||||
currentBand->top, rect->top, nullptr, &usedRects,
|
||||
&nextBand))
|
||||
return FALSE;
|
||||
mergeTop = rect->top;
|
||||
}
|
||||
|
||||
/* do the merge zone (all cases) */
|
||||
if (rect->bottom < currentBand->bottom)
|
||||
mergeBottom = rect->bottom;
|
||||
|
||||
if (!region16_copy_band_with_union(newItems, currentBand, endSrcRect, mergeTop,
|
||||
mergeBottom, rect, &usedRects, &nextBand))
|
||||
return FALSE;
|
||||
|
||||
/* test if we need a bottom split, case 1 and 4 */
|
||||
if (rect->bottom < currentBand->bottom)
|
||||
{
|
||||
if (!region16_copy_band_with_union(newItems, currentBand, endSrcRect, mergeBottom,
|
||||
currentBand->bottom, nullptr, &usedRects,
|
||||
&nextBand))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
topInterBand = currentBand->bottom;
|
||||
}
|
||||
|
||||
/* test if a piece of rect should be inserted as a new band between
|
||||
* the current band and the next one. band n and n+1 shouldn't touch.
|
||||
*
|
||||
* ==============================================================
|
||||
* band n
|
||||
* +------+ +------+
|
||||
* ===========| rect |====================| |===============
|
||||
* | | +------+ | |
|
||||
* +------+ | rect | | rect |
|
||||
* +------+ | |
|
||||
* =======================================| |================
|
||||
* +------+ band n+1
|
||||
* ===============================================================
|
||||
*
|
||||
*/
|
||||
if ((nextBand < endSrcRect) && (nextBand->top != currentBand->bottom) &&
|
||||
(rect->bottom > currentBand->bottom) && (rect->top < nextBand->top))
|
||||
{
|
||||
RECTANGLE_16* dstRect = nextRect(newItems, usedRects++);
|
||||
if (!dstRect)
|
||||
return FALSE;
|
||||
|
||||
dstRect->right = rect->right;
|
||||
dstRect->left = rect->left;
|
||||
dstRect->top = topInterBand;
|
||||
dstRect->bottom = MIN(nextBand->top, rect->bottom);
|
||||
}
|
||||
|
||||
currentBand = nextBand;
|
||||
}
|
||||
|
||||
/* adds the piece of rect that is below src */
|
||||
if (srcExtents->bottom < rect->bottom)
|
||||
{
|
||||
RECTANGLE_16* dstRect = nextRect(newItems, usedRects++);
|
||||
if (!dstRect)
|
||||
return FALSE;
|
||||
|
||||
dstRect->top = MAX(srcExtents->bottom, rect->top);
|
||||
dstRect->left = rect->left;
|
||||
dstRect->right = rect->right;
|
||||
dstRect->bottom = rect->bottom;
|
||||
}
|
||||
|
||||
dstExtents->top = MIN(rect->top, srcExtents->top);
|
||||
dstExtents->left = MIN(rect->left, srcExtents->left);
|
||||
dstExtents->bottom = MAX(rect->bottom, srcExtents->bottom);
|
||||
dstExtents->right = MAX(rect->right, srcExtents->right);
|
||||
|
||||
newItems->nbRects = usedRects;
|
||||
freeRegion(dst->data);
|
||||
dst->data = newItems;
|
||||
|
||||
return region16_simplify_bands(dst);
|
||||
}
|
||||
|
||||
BOOL region16_intersects_rect(const REGION16* src, const RECTANGLE_16* arg2)
|
||||
{
|
||||
const RECTANGLE_16* endPtr = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
|
||||
if (!src || !src->data || !arg2)
|
||||
return FALSE;
|
||||
|
||||
const RECTANGLE_16* rect = region16_rects(src, &nbRects);
|
||||
|
||||
if (!nbRects)
|
||||
return FALSE;
|
||||
|
||||
const RECTANGLE_16* srcExtents = region16_extents(src);
|
||||
|
||||
if (nbRects == 1)
|
||||
return rectangles_intersects(srcExtents, arg2);
|
||||
|
||||
if (!rectangles_intersects(srcExtents, arg2))
|
||||
return FALSE;
|
||||
|
||||
for (endPtr = rect + nbRects; (rect < endPtr) && (arg2->bottom > rect->top); rect++)
|
||||
{
|
||||
if (rectangles_intersects(rect, arg2))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL region16_intersect_rect(REGION16* dst, const REGION16* src, const RECTANGLE_16* rect)
|
||||
{
|
||||
const RECTANGLE_16* endPtr = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 common = WINPR_C_ARRAY_INIT;
|
||||
|
||||
WINPR_ASSERT(dst);
|
||||
WINPR_ASSERT(src);
|
||||
|
||||
const RECTANGLE_16* srcPtr = region16_rects(src, &nbRects);
|
||||
|
||||
if (!nbRects)
|
||||
{
|
||||
region16_clear(dst);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const RECTANGLE_16* srcExtents = region16_extents(src);
|
||||
|
||||
if (nbRects == 1)
|
||||
{
|
||||
BOOL intersects = rectangles_intersection(srcExtents, rect, &common);
|
||||
region16_clear(dst);
|
||||
|
||||
if (intersects)
|
||||
return region16_union_rect(dst, dst, &common);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
REGION16_DATA* newItems = allocateRegion(nbRects);
|
||||
|
||||
if (!newItems)
|
||||
return FALSE;
|
||||
|
||||
RECTANGLE_16* dstPtr = newItems->rects;
|
||||
UINT32 usedRects = 0;
|
||||
RECTANGLE_16 newExtents = WINPR_C_ARRAY_INIT;
|
||||
|
||||
/* accumulate intersecting rectangles, the final region16_simplify_bands() will
|
||||
* do all the bad job to recreate correct rectangles
|
||||
*/
|
||||
for (endPtr = srcPtr + nbRects; (srcPtr < endPtr) && (rect->bottom > srcPtr->top); srcPtr++)
|
||||
{
|
||||
if (usedRects > nbRects)
|
||||
{
|
||||
freeRegion(newItems);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (rectangles_intersection(srcPtr, rect, &common))
|
||||
{
|
||||
*dstPtr = common;
|
||||
usedRects++;
|
||||
dstPtr++;
|
||||
|
||||
if (rectangle_is_empty(&newExtents))
|
||||
{
|
||||
/* Check if the existing newExtents is empty. If it is empty, use
|
||||
* new common directly. We do not need to check common rectangle
|
||||
* because the rectangles_intersection() ensures that it is not empty.
|
||||
*/
|
||||
newExtents = common;
|
||||
}
|
||||
else
|
||||
{
|
||||
newExtents.top = MIN(common.top, newExtents.top);
|
||||
newExtents.left = MIN(common.left, newExtents.left);
|
||||
newExtents.bottom = MAX(common.bottom, newExtents.bottom);
|
||||
newExtents.right = MAX(common.right, newExtents.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newItems->nbRects = usedRects;
|
||||
|
||||
freeRegion(dst->data);
|
||||
dst->data = newItems;
|
||||
dst->extents = newExtents;
|
||||
return region16_simplify_bands(dst);
|
||||
}
|
||||
|
||||
void region16_uninit(REGION16* region)
|
||||
{
|
||||
WINPR_ASSERT(region);
|
||||
|
||||
freeRegion(region->data);
|
||||
region->data = nullptr;
|
||||
}
|
||||
+2504
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_LIB_CODEC_RFX_BITSTREAM_H
|
||||
#define FREERDP_LIB_CODEC_RFX_BITSTREAM_H
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE* buffer;
|
||||
uint32_t nbytes;
|
||||
uint32_t byte_pos;
|
||||
uint32_t bits_left;
|
||||
} RFX_BITSTREAM;
|
||||
|
||||
static inline void rfx_bitstream_attach(RFX_BITSTREAM* bs, BYTE* WINPR_RESTRICT buffer,
|
||||
size_t nbytes)
|
||||
{
|
||||
WINPR_ASSERT(bs);
|
||||
bs->buffer = (buffer);
|
||||
|
||||
WINPR_ASSERT(nbytes <= UINT32_MAX);
|
||||
bs->nbytes = WINPR_ASSERTING_INT_CAST(uint32_t, nbytes);
|
||||
bs->byte_pos = 0;
|
||||
bs->bits_left = 8;
|
||||
}
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline uint32_t rfx_bitstream_get_bits(RFX_BITSTREAM* bs, uint32_t nbits)
|
||||
{
|
||||
UINT16 n = 0;
|
||||
while (bs->byte_pos < bs->nbytes && nbits > 0)
|
||||
{
|
||||
uint32_t 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;
|
||||
}
|
||||
|
||||
static inline void rfx_bitstream_put_bits(RFX_BITSTREAM* bs, uint32_t _bits, uint32_t _nbits)
|
||||
{
|
||||
UINT16 bits = WINPR_ASSERTING_INT_CAST(UINT16, _bits);
|
||||
|
||||
uint32_t nbits = (_nbits);
|
||||
while (bs->byte_pos < bs->nbytes && nbits > 0)
|
||||
{
|
||||
uint32_t 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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rfx_bitstream_flush(RFX_BITSTREAM* bs)
|
||||
{
|
||||
WINPR_ASSERT(bs);
|
||||
if (bs->bits_left != 8)
|
||||
{
|
||||
uint32_t _nbits = 8 - bs->bits_left;
|
||||
rfx_bitstream_put_bits(bs, 0, _nbits);
|
||||
}
|
||||
}
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline BOOL rfx_bitstream_eos(RFX_BITSTREAM* bs)
|
||||
{
|
||||
WINPR_ASSERT(bs);
|
||||
return ((bs)->byte_pos >= (bs)->nbytes);
|
||||
}
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline uint32_t rfx_bitstream_left(RFX_BITSTREAM* bs)
|
||||
{
|
||||
WINPR_ASSERT(bs);
|
||||
|
||||
if ((bs)->byte_pos >= (bs)->nbytes)
|
||||
return 0;
|
||||
|
||||
return ((bs)->nbytes - (bs)->byte_pos - 1) * 8 + (bs)->bits_left;
|
||||
}
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
static inline uint32_t rfx_bitstream_get_processed_bytes(RFX_BITSTREAM* bs)
|
||||
{
|
||||
WINPR_ASSERT(bs);
|
||||
if ((bs)->bits_left < 8)
|
||||
return (bs)->byte_pos + 1;
|
||||
return (bs)->byte_pos;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_BITSTREAM_H */
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_LIB_CODEC_RFX_CONSTANTS_H
|
||||
#define FREERDP_LIB_CODEC_RFX_CONSTANTS_H
|
||||
|
||||
#include <freerdp/api.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
|
||||
|
||||
#define PROGRESSIVE_WBT_SYNC 0xCCC0
|
||||
#define PROGRESSIVE_WBT_FRAME_BEGIN 0xCCC1
|
||||
#define PROGRESSIVE_WBT_FRAME_END 0xCCC2
|
||||
#define PROGRESSIVE_WBT_CONTEXT 0xCCC3
|
||||
#define PROGRESSIVE_WBT_REGION 0xCCC4
|
||||
#define PROGRESSIVE_WBT_TILE_SIMPLE 0xCCC5
|
||||
#define PROGRESSIVE_WBT_TILE_FIRST 0xCCC6
|
||||
#define PROGRESSIVE_WBT_TILE_UPGRADE 0xCCC7
|
||||
|
||||
/* 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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL const char* rfx_get_progressive_block_type_string(UINT16 blockType);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_CONSTANTS_H */
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX Codec Library - Decode
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
* Copyright 2011 Norbert Federa <norbert.federa@thincast.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 <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
#include <freerdp/primitives.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 inline void rfx_decode_component(RFX_CONTEXT* WINPR_RESTRICT context,
|
||||
const UINT32* WINPR_RESTRICT quantization_values,
|
||||
const BYTE* WINPR_RESTRICT data, size_t size,
|
||||
INT16* WINPR_RESTRICT buffer)
|
||||
{
|
||||
INT16* dwt_buffer = BufferPool_Take(context->priv->BufferPool, -1); /* dwt_buffer */
|
||||
WINPR_ASSERT(dwt_buffer);
|
||||
|
||||
PROFILER_ENTER(context->priv->prof_rfx_decode_component)
|
||||
PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode)
|
||||
WINPR_ASSERT(size <= UINT32_MAX);
|
||||
|
||||
{
|
||||
const int rc = context->rlgr_decode(context->mode, data, (UINT32)size, buffer, 4096);
|
||||
if (rc < 0)
|
||||
WLog_Print(context->priv->log, WLOG_ERROR, "context->rlgr_decode failed: %d", rc);
|
||||
}
|
||||
|
||||
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, dwt_buffer);
|
||||
PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_decode)
|
||||
PROFILER_EXIT(context->priv->prof_rfx_decode_component)
|
||||
BufferPool_Return(context->priv->BufferPool, dwt_buffer);
|
||||
}
|
||||
|
||||
/* rfx_decode_ycbcr_to_rgb code now resides in the primitives library. */
|
||||
|
||||
/* stride is bytes between rows in the output buffer. */
|
||||
BOOL rfx_decode_rgb(RFX_CONTEXT* WINPR_RESTRICT context, const RFX_TILE* WINPR_RESTRICT tile,
|
||||
BYTE* WINPR_RESTRICT rgb_buffer, UINT32 stride)
|
||||
{
|
||||
union
|
||||
{
|
||||
const INT16** cpv;
|
||||
INT16** pv;
|
||||
} cnv;
|
||||
BOOL rc = TRUE;
|
||||
BYTE* pBuffer = nullptr;
|
||||
INT16* pSrcDst[3];
|
||||
UINT32* y_quants = nullptr;
|
||||
UINT32* cb_quants = nullptr;
|
||||
UINT32* cr_quants = nullptr;
|
||||
static const prim_size_t roi_64x64 = { 64, 64 };
|
||||
const primitives_t* prims = primitives_get();
|
||||
PROFILER_ENTER(context->priv->prof_rfx_decode_rgb)
|
||||
y_quants = context->quants + (10ULL * tile->quantIdxY);
|
||||
cb_quants = context->quants + (10ULL * tile->quantIdxCb);
|
||||
cr_quants = context->quants + (10ULL * tile->quantIdxCr);
|
||||
pBuffer = (BYTE*)BufferPool_Take(context->priv->BufferPool, -1);
|
||||
pSrcDst[0] = (INT16*)((&pBuffer[((8192ULL + 32ULL) * 0ULL) + 16ULL])); /* y_r_buffer */
|
||||
pSrcDst[1] = (INT16*)((&pBuffer[((8192ULL + 32ULL) * 1ULL) + 16ULL])); /* cb_g_buffer */
|
||||
pSrcDst[2] = (INT16*)((&pBuffer[((8192ULL + 32ULL) * 2ULL) + 16ULL])); /* cr_b_buffer */
|
||||
rfx_decode_component(context, y_quants, tile->YData, tile->YLen, pSrcDst[0]); /* YData */
|
||||
rfx_decode_component(context, cb_quants, tile->CbData, tile->CbLen, pSrcDst[1]); /* CbData */
|
||||
rfx_decode_component(context, cr_quants, tile->CrData, tile->CrLen, pSrcDst[2]); /* CrData */
|
||||
PROFILER_ENTER(context->priv->prof_rfx_ycbcr_to_rgb)
|
||||
|
||||
cnv.pv = pSrcDst;
|
||||
if (prims->yCbCrToRGB_16s8u_P3AC4R(cnv.cpv, 64 * sizeof(INT16), rgb_buffer, stride,
|
||||
context->pixel_format, &roi_64x64) != PRIMITIVES_SUCCESS)
|
||||
rc = FALSE;
|
||||
|
||||
PROFILER_EXIT(context->priv->prof_rfx_ycbcr_to_rgb)
|
||||
PROFILER_EXIT(context->priv->prof_rfx_decode_rgb)
|
||||
BufferPool_Return(context->priv->BufferPool, pBuffer);
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_LIB_CODEC_RFX_DECODE_H
|
||||
#define FREERDP_LIB_CODEC_RFX_DECODE_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
/* stride is bytes between rows in the output buffer. */
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rfx_decode_rgb(RFX_CONTEXT* WINPR_RESTRICT context,
|
||||
const RFX_TILE* WINPR_RESTRICT tile,
|
||||
BYTE* WINPR_RESTRICT rgb_buffer, UINT32 stride);
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_DECODE_H */
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_LIB_CODEC_RFX_DIFFERENTIAL_H
|
||||
#define FREERDP_LIB_CODEC_RFX_DIFFERENTIAL_H
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
static inline void rfx_differential_decode(INT16* WINPR_RESTRICT buffer, size_t size)
|
||||
{
|
||||
INT16* ptr = buffer;
|
||||
INT16* end = &buffer[size - 1];
|
||||
|
||||
while (ptr != end)
|
||||
{
|
||||
const int tmp = ptr[0] + ptr[1];
|
||||
ptr[1] = WINPR_ASSERTING_INT_CAST(INT16, tmp);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rfx_differential_encode(INT16* WINPR_RESTRICT buffer, size_t size)
|
||||
{
|
||||
INT16 n1 = buffer[0];
|
||||
for (size_t x = 0; x < size - 1; x++)
|
||||
{
|
||||
INT16* dst = &buffer[x + 1];
|
||||
const INT16 n2 = *dst;
|
||||
const int tmp = n2 - n1;
|
||||
*dst = WINPR_ASSERTING_INT_CAST(INT16, tmp);
|
||||
n1 = n2;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_DIFFERENTIAL_H */
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rfx_dwt.h"
|
||||
|
||||
static inline void rfx_dwt_2d_decode_block(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT idwt,
|
||||
size_t subband_width)
|
||||
{
|
||||
const size_t 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). */
|
||||
|
||||
const INT16* ll = buffer + subband_width * subband_width * 3;
|
||||
const INT16* hl = buffer;
|
||||
INT16* l_dst = idwt;
|
||||
|
||||
const INT16* lh = buffer + subband_width * subband_width;
|
||||
const INT16* hh = buffer + subband_width * subband_width * 2;
|
||||
INT16* h_dst = idwt + subband_width * subband_width * 2;
|
||||
|
||||
for (size_t y = 0; y < subband_width; y++)
|
||||
{
|
||||
/* Even coefficients */
|
||||
l_dst[0] = WINPR_ASSERTING_INT_CAST(int16_t, ll[0] - ((hl[0] + hl[0] + 1) >> 1));
|
||||
h_dst[0] = WINPR_ASSERTING_INT_CAST(int16_t, lh[0] - ((hh[0] + hh[0] + 1) >> 1));
|
||||
for (size_t n = 1; n < subband_width; n++)
|
||||
{
|
||||
const size_t x = n << 1;
|
||||
l_dst[x] = WINPR_ASSERTING_INT_CAST(int16_t, ll[n] - ((hl[n - 1] + hl[n] + 1) >> 1));
|
||||
h_dst[x] = WINPR_ASSERTING_INT_CAST(int16_t, lh[n] - ((hh[n - 1] + hh[n] + 1) >> 1));
|
||||
}
|
||||
|
||||
/* Odd coefficients */
|
||||
size_t n = 0;
|
||||
for (; n < subband_width - 1; n++)
|
||||
{
|
||||
const size_t x = n << 1;
|
||||
|
||||
const int ld = (hl[n] << 1) + ((l_dst[x] + l_dst[x + 2]) >> 1);
|
||||
const int hd = (hh[n] << 1) + ((h_dst[x] + h_dst[x + 2]) >> 1);
|
||||
|
||||
l_dst[x + 1] = WINPR_ASSERTING_INT_CAST(INT16, ld);
|
||||
h_dst[x + 1] = WINPR_ASSERTING_INT_CAST(INT16, hd);
|
||||
}
|
||||
|
||||
const size_t x = n << 1;
|
||||
|
||||
const int ld = (hl[n] << 1) + (l_dst[x]);
|
||||
const int hd = (hh[n] << 1) + (h_dst[x]);
|
||||
l_dst[x + 1] = WINPR_ASSERTING_INT_CAST(INT16, ld);
|
||||
h_dst[x + 1] = WINPR_ASSERTING_INT_CAST(INT16, hd);
|
||||
|
||||
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 (size_t x = 0; x < total_width; x++)
|
||||
{
|
||||
const INT16* l = idwt + x;
|
||||
const INT16* h = idwt + x + subband_width * total_width;
|
||||
INT16* dst = buffer + x;
|
||||
|
||||
const int dd = *l - ((*h * 2 + 1) >> 1);
|
||||
*dst = WINPR_ASSERTING_INT_CAST(INT16, dd);
|
||||
|
||||
for (size_t n = 1; n < subband_width; n++)
|
||||
{
|
||||
l += total_width;
|
||||
h += total_width;
|
||||
|
||||
/* Even coefficients */
|
||||
const int d2 = *l - ((*(h - total_width) + *h + 1) >> 1);
|
||||
dst[2 * total_width] = WINPR_ASSERTING_INT_CAST(INT16, d2);
|
||||
|
||||
/* Odd coefficients */
|
||||
const int d = (*(h - total_width) << 1) + ((*dst + dst[2 * total_width]) >> 1);
|
||||
dst[total_width] = WINPR_ASSERTING_INT_CAST(INT16, d);
|
||||
|
||||
dst += 2 * total_width;
|
||||
}
|
||||
|
||||
const int d = (*h << 1) + ((*dst * 2) >> 1);
|
||||
dst[total_width] = WINPR_ASSERTING_INT_CAST(INT16, d);
|
||||
}
|
||||
}
|
||||
|
||||
void rfx_dwt_2d_decode(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt_buffer)
|
||||
{
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(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[0], dwt_buffer, 32);
|
||||
}
|
||||
|
||||
static void rfx_dwt_2d_encode_block(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt,
|
||||
UINT32 subband_width)
|
||||
{
|
||||
INT16* src = nullptr;
|
||||
INT16* l = nullptr;
|
||||
INT16* h = nullptr;
|
||||
INT16* l_src = nullptr;
|
||||
INT16* h_src = nullptr;
|
||||
INT16* hl = nullptr;
|
||||
INT16* lh = nullptr;
|
||||
INT16* hh = nullptr;
|
||||
INT16* ll = nullptr;
|
||||
|
||||
const UINT32 total_width = subband_width << 1;
|
||||
|
||||
/* DWT in vertical direction, results in 2 sub-bands in L, H order in tmp buffer dwt. */
|
||||
for (UINT32 x = 0; x < total_width; x++)
|
||||
{
|
||||
for (UINT32 n = 0; n < subband_width; n++)
|
||||
{
|
||||
UINT32 y = n << 1;
|
||||
l = dwt + 1ULL * n * total_width + x;
|
||||
h = l + 1ULL * subband_width * total_width;
|
||||
src = buffer + 1ULL * y * total_width + x;
|
||||
|
||||
/* H */
|
||||
*h = WINPR_ASSERTING_INT_CAST(
|
||||
int16_t, (src[total_width] -
|
||||
((src[0] + src[n < subband_width - 1 ? 2 * total_width : 0]) >> 1)) >>
|
||||
1);
|
||||
|
||||
/* L */
|
||||
*l = WINPR_ASSERTING_INT_CAST(int16_t,
|
||||
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 + 3ULL * subband_width * subband_width;
|
||||
hl = buffer;
|
||||
l_src = dwt;
|
||||
|
||||
lh = buffer + 1ULL * subband_width * subband_width;
|
||||
hh = buffer + 2ULL * subband_width * subband_width;
|
||||
h_src = dwt + 2ULL * subband_width * subband_width;
|
||||
|
||||
for (size_t y = 0; y < subband_width; y++)
|
||||
{
|
||||
/* L */
|
||||
for (UINT32 n = 0; n < subband_width; n++)
|
||||
{
|
||||
UINT32 x = n << 1;
|
||||
|
||||
/* HL */
|
||||
hl[n] = WINPR_ASSERTING_INT_CAST(
|
||||
int16_t,
|
||||
(l_src[x + 1] - ((l_src[x] + l_src[n < subband_width - 1 ? x + 2 : x]) >> 1)) >> 1);
|
||||
/* LL */
|
||||
ll[n] = WINPR_ASSERTING_INT_CAST(
|
||||
int16_t, l_src[x] + (n == 0 ? hl[n] : (hl[n - 1] + hl[n]) >> 1));
|
||||
}
|
||||
|
||||
/* H */
|
||||
for (UINT32 n = 0; n < subband_width; n++)
|
||||
{
|
||||
UINT32 x = n << 1;
|
||||
|
||||
/* HH */
|
||||
hh[n] = WINPR_ASSERTING_INT_CAST(
|
||||
int16_t,
|
||||
(h_src[x + 1] - ((h_src[x] + h_src[n < subband_width - 1 ? x + 2 : x]) >> 1)) >> 1);
|
||||
/* LH */
|
||||
lh[n] = WINPR_ASSERTING_INT_CAST(
|
||||
int16_t, 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(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt_buffer)
|
||||
{
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(dwt_buffer);
|
||||
|
||||
rfx_dwt_2d_encode_block(&buffer[0], dwt_buffer, 32);
|
||||
rfx_dwt_2d_encode_block(&buffer[3072], dwt_buffer, 16);
|
||||
rfx_dwt_2d_encode_block(&buffer[3840], dwt_buffer, 8);
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_LIB_CODEC_RFX_DWT_H
|
||||
#define FREERDP_LIB_CODEC_RFX_DWT_H
|
||||
|
||||
#include <winpr/wtypes.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL void rfx_dwt_2d_decode(INT16* WINPR_RESTRICT buffer,
|
||||
INT16* WINPR_RESTRICT dwt_buffer);
|
||||
FREERDP_LOCAL void rfx_dwt_2d_encode(INT16* WINPR_RESTRICT buffer,
|
||||
INT16* WINPR_RESTRICT dwt_buffer);
|
||||
FREERDP_LOCAL void rfx_dwt_2d_extrapolate_decode(INT16* WINPR_RESTRICT buffer,
|
||||
INT16* WINPR_RESTRICT dwt_buffer);
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_DWT_H */
|
||||
+312
@@ -0,0 +1,312 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX Codec Library - Encode
|
||||
*
|
||||
* Copyright 2011 Vic Lee
|
||||
* Copyright 2011 Norbert Federa <norbert.federa@thincast.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 <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/primitives.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"
|
||||
|
||||
static void rfx_encode_format_rgb(const BYTE* WINPR_RESTRICT rgb_data, uint32_t width,
|
||||
uint32_t height, uint32_t rowstride, UINT32 pixel_format,
|
||||
const BYTE* WINPR_RESTRICT palette, INT16* WINPR_RESTRICT r_buf,
|
||||
INT16* WINPR_RESTRICT g_buf, INT16* WINPR_RESTRICT b_buf)
|
||||
{
|
||||
const BYTE* src = nullptr;
|
||||
INT16 r = 0;
|
||||
INT16 g = 0;
|
||||
INT16 b = 0;
|
||||
INT16* r_last = nullptr;
|
||||
INT16* g_last = nullptr;
|
||||
INT16* b_last = nullptr;
|
||||
uint32_t x_exceed = 64 - width;
|
||||
uint32_t y_exceed = 64 - height;
|
||||
|
||||
for (uint32_t y = 0; y < height; y++)
|
||||
{
|
||||
src = rgb_data + 1ULL * y * rowstride;
|
||||
|
||||
switch (pixel_format)
|
||||
{
|
||||
case PIXEL_FORMAT_BGRX32:
|
||||
case PIXEL_FORMAT_BGRA32:
|
||||
for (uint32_t x = 0; x < width; x++)
|
||||
{
|
||||
*b_buf++ = (INT16)(*src++);
|
||||
*g_buf++ = (INT16)(*src++);
|
||||
*r_buf++ = (INT16)(*src++);
|
||||
src++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_XBGR32:
|
||||
case PIXEL_FORMAT_ABGR32:
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
src++;
|
||||
*b_buf++ = (INT16)(*src++);
|
||||
*g_buf++ = (INT16)(*src++);
|
||||
*r_buf++ = (INT16)(*src++);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_RGBX32:
|
||||
case PIXEL_FORMAT_RGBA32:
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
*r_buf++ = (INT16)(*src++);
|
||||
*g_buf++ = (INT16)(*src++);
|
||||
*b_buf++ = (INT16)(*src++);
|
||||
src++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_XRGB32:
|
||||
case PIXEL_FORMAT_ARGB32:
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
src++;
|
||||
*r_buf++ = (INT16)(*src++);
|
||||
*g_buf++ = (INT16)(*src++);
|
||||
*b_buf++ = (INT16)(*src++);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_BGR24:
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
*b_buf++ = (INT16)(*src++);
|
||||
*g_buf++ = (INT16)(*src++);
|
||||
*r_buf++ = (INT16)(*src++);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_RGB24:
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
*r_buf++ = (INT16)(*src++);
|
||||
*g_buf++ = (INT16)(*src++);
|
||||
*b_buf++ = (INT16)(*src++);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_BGR16:
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
*b_buf++ = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
|
||||
*g_buf++ = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3));
|
||||
*r_buf++ = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07));
|
||||
src += 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_RGB16:
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
*r_buf++ = (INT16)(((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
|
||||
*g_buf++ = (INT16)((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3));
|
||||
*b_buf++ = (INT16)((((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07));
|
||||
src += 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_RGB8:
|
||||
if (!palette)
|
||||
break;
|
||||
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
BYTE idx = 0;
|
||||
const size_t shift = (7 - (x % 8));
|
||||
idx = ((*src) >> shift) & 1;
|
||||
idx |= (((*(src + 1)) >> shift) & 1) << 1;
|
||||
idx |= (((*(src + 2)) >> shift) & 1) << 2;
|
||||
idx |= (((*(src + 3)) >> shift) & 1) << 3;
|
||||
idx *= 3;
|
||||
*r_buf++ = (INT16)palette[idx];
|
||||
*g_buf++ = (INT16)palette[idx + 1];
|
||||
*b_buf++ = (INT16)palette[idx + 2];
|
||||
|
||||
if (shift == 0)
|
||||
src += 4;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PIXEL_FORMAT_A4:
|
||||
if (!palette)
|
||||
break;
|
||||
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
int idx = (*src) * 3;
|
||||
*r_buf++ = (INT16)palette[idx];
|
||||
*g_buf++ = (INT16)palette[idx + 1];
|
||||
*b_buf++ = (INT16)palette[idx + 2];
|
||||
src++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fill the horizontal region outside of 64x64 tile size with the right-most pixel for best
|
||||
* quality */
|
||||
if (x_exceed > 0)
|
||||
{
|
||||
r = *(r_buf - 1);
|
||||
g = *(g_buf - 1);
|
||||
b = *(b_buf - 1);
|
||||
|
||||
for (size_t x = 0; x < x_exceed; x++)
|
||||
{
|
||||
*r_buf++ = r;
|
||||
*g_buf++ = g;
|
||||
*b_buf++ = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill the vertical region outside of 64x64 tile size with the last line. */
|
||||
if (y_exceed > 0)
|
||||
{
|
||||
r_last = r_buf - 64;
|
||||
g_last = g_buf - 64;
|
||||
b_last = b_buf - 64;
|
||||
|
||||
while (y_exceed > 0)
|
||||
{
|
||||
CopyMemory(r_buf, r_last, 64 * sizeof(INT16));
|
||||
CopyMemory(g_buf, g_last, 64 * sizeof(INT16));
|
||||
CopyMemory(b_buf, b_last, 64 * sizeof(INT16));
|
||||
r_buf += 64;
|
||||
g_buf += 64;
|
||||
b_buf += 64;
|
||||
y_exceed--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* rfx_encode_rgb_to_ycbcr code now resides in the primitives library. */
|
||||
|
||||
static void rfx_encode_component(RFX_CONTEXT* WINPR_RESTRICT context,
|
||||
const UINT32* WINPR_RESTRICT quantization_values,
|
||||
INT16* WINPR_RESTRICT data, BYTE* WINPR_RESTRICT buffer,
|
||||
uint32_t buffer_size, uint32_t* WINPR_RESTRICT size)
|
||||
{
|
||||
INT16* dwt_buffer = BufferPool_Take(context->priv->BufferPool, -1); /* dwt_buffer */
|
||||
PROFILER_ENTER(context->priv->prof_rfx_encode_component)
|
||||
PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_encode)
|
||||
context->dwt_2d_encode(data, 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)
|
||||
const int rc = context->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)
|
||||
BufferPool_Return(context->priv->BufferPool, dwt_buffer);
|
||||
|
||||
*size = WINPR_ASSERTING_INT_CAST(uint32_t, rc);
|
||||
}
|
||||
|
||||
BOOL rfx_encode_rgb(RFX_CONTEXT* WINPR_RESTRICT context, RFX_TILE* WINPR_RESTRICT tile)
|
||||
{
|
||||
BOOL rc = TRUE;
|
||||
union
|
||||
{
|
||||
const INT16** cpv;
|
||||
INT16** pv;
|
||||
} cnv;
|
||||
INT16* pSrcDst[3] = WINPR_C_ARRAY_INIT;
|
||||
uint32_t CbLen = 0;
|
||||
uint32_t CrLen = 0;
|
||||
primitives_t* prims = primitives_get();
|
||||
static const prim_size_t roi_64x64 = { 64, 64 };
|
||||
|
||||
BYTE* pBuffer = (BYTE*)BufferPool_Take(context->priv->BufferPool, -1);
|
||||
if (!pBuffer)
|
||||
return FALSE;
|
||||
|
||||
uint32_t YLen = CbLen = CrLen = 0;
|
||||
UINT32* YQuant = context->quants + (10ULL * tile->quantIdxY);
|
||||
UINT32* CbQuant = context->quants + (10ULL * tile->quantIdxCb);
|
||||
UINT32* CrQuant = context->quants + (10ULL * tile->quantIdxCr);
|
||||
pSrcDst[0] = (INT16*)((&pBuffer[((8192ULL + 32ULL) * 0ULL) + 16ULL])); /* y_r_buffer */
|
||||
pSrcDst[1] = (INT16*)((&pBuffer[((8192ULL + 32ULL) * 1ULL) + 16ULL])); /* cb_g_buffer */
|
||||
pSrcDst[2] = (INT16*)((&pBuffer[((8192ULL + 32ULL) * 2ULL) + 16ULL])); /* cr_b_buffer */
|
||||
PROFILER_ENTER(context->priv->prof_rfx_encode_rgb)
|
||||
PROFILER_ENTER(context->priv->prof_rfx_encode_format_rgb)
|
||||
rfx_encode_format_rgb(tile->data, tile->width, tile->height, tile->scanline,
|
||||
context->pixel_format, context->palette, pSrcDst[0], pSrcDst[1],
|
||||
pSrcDst[2]);
|
||||
PROFILER_EXIT(context->priv->prof_rfx_encode_format_rgb)
|
||||
PROFILER_ENTER(context->priv->prof_rfx_rgb_to_ycbcr)
|
||||
|
||||
cnv.pv = pSrcDst;
|
||||
if (prims->RGBToYCbCr_16s16s_P3P3(cnv.cpv, 64 * sizeof(INT16), pSrcDst, 64 * sizeof(INT16),
|
||||
&roi_64x64) != PRIMITIVES_SUCCESS)
|
||||
rc = FALSE;
|
||||
PROFILER_EXIT(context->priv->prof_rfx_rgb_to_ycbcr)
|
||||
/**
|
||||
* We need to clear the buffers as the RLGR encoder expects it to be initialized to zero.
|
||||
* This allows simplifying and improving the performance of the encoding process.
|
||||
*/
|
||||
ZeroMemory(tile->YData, 4096);
|
||||
ZeroMemory(tile->CbData, 4096);
|
||||
ZeroMemory(tile->CrData, 4096);
|
||||
rfx_encode_component(context, YQuant, pSrcDst[0], tile->YData, 4096, &YLen);
|
||||
rfx_encode_component(context, CbQuant, pSrcDst[1], tile->CbData, 4096, &CbLen);
|
||||
rfx_encode_component(context, CrQuant, pSrcDst[2], tile->CrData, 4096, &CrLen);
|
||||
tile->YLen = WINPR_ASSERTING_INT_CAST(UINT16, YLen);
|
||||
tile->CbLen = WINPR_ASSERTING_INT_CAST(UINT16, CbLen);
|
||||
tile->CrLen = WINPR_ASSERTING_INT_CAST(UINT16, CrLen);
|
||||
PROFILER_EXIT(context->priv->prof_rfx_encode_rgb)
|
||||
if (!BufferPool_Return(context->priv->BufferPool, pBuffer))
|
||||
return FALSE;
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_LIB_CODEC_RFX_ENCODE_H
|
||||
#define FREERDP_LIB_CODEC_RFX_ENCODE_H
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL BOOL rfx_encode_rgb(RFX_CONTEXT* WINPR_RESTRICT context,
|
||||
RFX_TILE* WINPR_RESTRICT tile);
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_ENCODE_H */
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <freerdp/primitives.h>
|
||||
|
||||
#include "rfx_quantization.h"
|
||||
|
||||
/*
|
||||
* Band Offset Dimensions Size
|
||||
*
|
||||
* HL1 0 32x32 1024
|
||||
* LH1 1024 32x32 1024
|
||||
* HH1 2048 32x32 1024
|
||||
*
|
||||
* HL2 3072 16x16 256
|
||||
* LH2 3328 16x16 256
|
||||
* HH2 3584 16x16 256
|
||||
*
|
||||
* HL3 3840 8x8 64
|
||||
* LH3 3904 8x8 64
|
||||
* HH3 3968 8x8 64
|
||||
*
|
||||
* LL3 4032 8x8 64
|
||||
*/
|
||||
|
||||
static inline BOOL rfx_quantization_decode_block(const primitives_t* WINPR_RESTRICT prims,
|
||||
INT16* WINPR_RESTRICT buffer, UINT32 buffer_size,
|
||||
UINT32 factor)
|
||||
{
|
||||
if (factor == 0)
|
||||
return TRUE;
|
||||
|
||||
return prims->lShiftC_16s_inplace(buffer, factor, buffer_size) == PRIMITIVES_SUCCESS;
|
||||
}
|
||||
|
||||
void rfx_quantization_decode(INT16* WINPR_RESTRICT buffer,
|
||||
const UINT32* WINPR_RESTRICT quantization_values)
|
||||
{
|
||||
const primitives_t* prims = primitives_get();
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(quantization_values);
|
||||
|
||||
rfx_quantization_decode_block(prims, &buffer[0], 1024, quantization_values[8] - 1); /* HL1 */
|
||||
rfx_quantization_decode_block(prims, &buffer[1024], 1024, quantization_values[7] - 1); /* LH1 */
|
||||
rfx_quantization_decode_block(prims, &buffer[2048], 1024, quantization_values[9] - 1); /* HH1 */
|
||||
rfx_quantization_decode_block(prims, &buffer[3072], 256, quantization_values[5] - 1); /* HL2 */
|
||||
rfx_quantization_decode_block(prims, &buffer[3328], 256, quantization_values[4] - 1); /* LH2 */
|
||||
rfx_quantization_decode_block(prims, &buffer[3584], 256, quantization_values[6] - 1); /* HH2 */
|
||||
rfx_quantization_decode_block(prims, &buffer[3840], 64, quantization_values[2] - 1); /* HL3 */
|
||||
rfx_quantization_decode_block(prims, &buffer[3904], 64, quantization_values[1] - 1); /* LH3 */
|
||||
rfx_quantization_decode_block(prims, &buffer[3968], 64, quantization_values[3] - 1); /* HH3 */
|
||||
rfx_quantization_decode_block(prims, &buffer[4032], 64, quantization_values[0] - 1); /* LL3 */
|
||||
}
|
||||
|
||||
static inline void rfx_quantization_encode_block(INT16* WINPR_RESTRICT buffer, size_t buffer_size,
|
||||
UINT32 factor)
|
||||
{
|
||||
if (factor == 0)
|
||||
return;
|
||||
|
||||
const INT16 half = WINPR_ASSERTING_INT_CAST(INT16, 1 << (factor - 1));
|
||||
/* Could probably use prims->rShiftC_16s(dst+half, factor, dst, buffer_size); */
|
||||
for (INT16* dst = buffer; buffer_size > 0; dst++, buffer_size--)
|
||||
{
|
||||
*dst = WINPR_ASSERTING_INT_CAST(INT16, (*dst + half) >> factor);
|
||||
}
|
||||
}
|
||||
|
||||
void rfx_quantization_encode(INT16* WINPR_RESTRICT buffer,
|
||||
const UINT32* WINPR_RESTRICT quantization_values)
|
||||
{
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(quantization_values);
|
||||
|
||||
rfx_quantization_encode_block(buffer, 1024, quantization_values[8] - 6); /* HL1 */
|
||||
rfx_quantization_encode_block(buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */
|
||||
rfx_quantization_encode_block(buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */
|
||||
rfx_quantization_encode_block(buffer + 3072, 256, quantization_values[5] - 6); /* HL2 */
|
||||
rfx_quantization_encode_block(buffer + 3328, 256, quantization_values[4] - 6); /* LH2 */
|
||||
rfx_quantization_encode_block(buffer + 3584, 256, quantization_values[6] - 6); /* HH2 */
|
||||
rfx_quantization_encode_block(buffer + 3840, 64, quantization_values[2] - 6); /* HL3 */
|
||||
rfx_quantization_encode_block(buffer + 3904, 64, quantization_values[1] - 6); /* LH3 */
|
||||
rfx_quantization_encode_block(buffer + 3968, 64, quantization_values[3] - 6); /* HH3 */
|
||||
rfx_quantization_encode_block(buffer + 4032, 64, quantization_values[0] - 6); /* LL3 */
|
||||
|
||||
/* The coefficients are scaled by << 5 at RGB->YCbCr phase, so we round it back here */
|
||||
rfx_quantization_encode_block(buffer, 4096, 5);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_LIB_CODEC_RFX_QUANTIZATION_H
|
||||
#define FREERDP_LIB_CODEC_RFX_QUANTIZATION_H
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL void rfx_quantization_decode(INT16* WINPR_RESTRICT buffer,
|
||||
const UINT32* WINPR_RESTRICT quantization_values);
|
||||
FREERDP_LOCAL void rfx_quantization_encode(INT16* WINPR_RESTRICT buffer,
|
||||
const UINT32* WINPR_RESTRICT quantization_values);
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_QUANTIZATION_H */
|
||||
+795
@@ -0,0 +1,795 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 <freerdp/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
#include <winpr/bitstream.h>
|
||||
#include <winpr/intrin.h>
|
||||
|
||||
#include "rfx_bitstream.h"
|
||||
|
||||
#include "rfx_rlgr.h"
|
||||
|
||||
/* Constants used in 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 */
|
||||
|
||||
/* Returns the least number of bits required to represent a given value */
|
||||
#define GetMinBits(_val, _nbits) \
|
||||
do \
|
||||
{ \
|
||||
UINT32 _v = (_val); \
|
||||
(_nbits) = 0; \
|
||||
while (_v) \
|
||||
{ \
|
||||
_v >>= 1; \
|
||||
(_nbits)++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Update the passed parameter and clamp it to the range [0, KPMAX]
|
||||
* Return the value of parameter right-shifted by LSGR
|
||||
*/
|
||||
static inline uint32_t UpdateParam(uint32_t* param, int32_t deltaP)
|
||||
{
|
||||
WINPR_ASSERT(param);
|
||||
if (deltaP < 0)
|
||||
{
|
||||
const uint32_t udeltaP = WINPR_ASSERTING_INT_CAST(uint32_t, -deltaP);
|
||||
if (udeltaP > *param)
|
||||
*param = 0;
|
||||
else
|
||||
*param -= udeltaP;
|
||||
}
|
||||
else
|
||||
*param += WINPR_ASSERTING_INT_CAST(uint32_t, deltaP);
|
||||
|
||||
if ((*param) > KPMAX)
|
||||
(*param) = KPMAX;
|
||||
return (*param) >> LSGR;
|
||||
}
|
||||
|
||||
static BOOL g_LZCNT = FALSE;
|
||||
|
||||
static INIT_ONCE rfx_rlgr_init_once = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
static BOOL CALLBACK rfx_rlgr_init(PINIT_ONCE once, PVOID param, PVOID* context)
|
||||
{
|
||||
WINPR_UNUSED(once);
|
||||
WINPR_UNUSED(param);
|
||||
WINPR_UNUSED(context);
|
||||
|
||||
g_LZCNT = IsProcessorFeaturePresentEx(PF_EX_LZCNT);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline UINT32 lzcnt_s(UINT32 x)
|
||||
{
|
||||
if (!x)
|
||||
return 32;
|
||||
|
||||
if (!g_LZCNT)
|
||||
{
|
||||
UINT32 y = 0;
|
||||
UINT32 n = 32;
|
||||
y = x >> 16;
|
||||
if (y != 0)
|
||||
{
|
||||
WINPR_ASSERT(n >= 16);
|
||||
n = n - 16;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 8;
|
||||
if (y != 0)
|
||||
{
|
||||
WINPR_ASSERT(n >= 8);
|
||||
n = n - 8;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 4;
|
||||
if (y != 0)
|
||||
{
|
||||
WINPR_ASSERT(n >= 4);
|
||||
n = n - 4;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 2;
|
||||
if (y != 0)
|
||||
{
|
||||
WINPR_ASSERT(n >= 2);
|
||||
n = n - 2;
|
||||
x = y;
|
||||
}
|
||||
y = x >> 1;
|
||||
if (y != 0)
|
||||
{
|
||||
WINPR_ASSERT(n >= 2);
|
||||
return n - 2;
|
||||
}
|
||||
|
||||
WINPR_ASSERT(n >= x);
|
||||
return n - x;
|
||||
}
|
||||
|
||||
return __lzcnt(x);
|
||||
}
|
||||
|
||||
int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize,
|
||||
INT16* WINPR_RESTRICT pDstData, UINT32 rDstSize)
|
||||
{
|
||||
uint32_t vk = 0;
|
||||
size_t run = 0;
|
||||
size_t cnt = 0;
|
||||
size_t size = 0;
|
||||
size_t offset = 0;
|
||||
INT16 mag = 0;
|
||||
UINT32 k = 0;
|
||||
UINT32 kp = 0;
|
||||
UINT32 kr = 0;
|
||||
UINT32 krp = 0;
|
||||
UINT16 code = 0;
|
||||
UINT32 sign = 0;
|
||||
UINT32 nIdx = 0;
|
||||
UINT32 val1 = 0;
|
||||
UINT32 val2 = 0;
|
||||
INT16* pOutput = nullptr;
|
||||
wBitStream* bs = nullptr;
|
||||
wBitStream s_bs = WINPR_C_ARRAY_INIT;
|
||||
const SSIZE_T DstSize = rDstSize;
|
||||
|
||||
if (!InitOnceExecuteOnce(&rfx_rlgr_init_once, rfx_rlgr_init, nullptr, nullptr))
|
||||
return -1;
|
||||
|
||||
k = 1;
|
||||
kp = k << LSGR;
|
||||
|
||||
kr = 1;
|
||||
krp = kr << LSGR;
|
||||
|
||||
if ((mode != RLGR1) && (mode != RLGR3))
|
||||
mode = RLGR1;
|
||||
|
||||
if (!pSrcData || !SrcSize)
|
||||
return -1;
|
||||
|
||||
if (!pDstData || !DstSize)
|
||||
return -1;
|
||||
|
||||
pOutput = pDstData;
|
||||
|
||||
bs = &s_bs;
|
||||
|
||||
BitStream_Attach(bs, pSrcData, SrcSize);
|
||||
BitStream_Fetch(bs);
|
||||
|
||||
while ((BitStream_GetRemainingLength(bs) > 0) && ((pOutput - pDstData) < DstSize))
|
||||
{
|
||||
if (k)
|
||||
{
|
||||
/* Run-Length (RL) Mode */
|
||||
|
||||
run = 0;
|
||||
|
||||
/* count number of leading 0s */
|
||||
|
||||
cnt = lzcnt_s(bs->accumulator);
|
||||
|
||||
size_t nbits = BitStream_GetRemainingLength(bs);
|
||||
|
||||
if (cnt > nbits)
|
||||
cnt = WINPR_ASSERTING_INT_CAST(uint32_t, nbits);
|
||||
|
||||
vk = WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
|
||||
|
||||
while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0))
|
||||
{
|
||||
BitStream_Shift32(bs);
|
||||
|
||||
cnt = lzcnt_s(bs->accumulator);
|
||||
|
||||
nbits = BitStream_GetRemainingLength(bs);
|
||||
|
||||
if (cnt > nbits)
|
||||
cnt = nbits;
|
||||
|
||||
WINPR_ASSERT(cnt + vk <= UINT32_MAX);
|
||||
vk += WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
|
||||
}
|
||||
|
||||
BitStream_Shift(bs, (vk % 32));
|
||||
|
||||
if (BitStream_GetRemainingLength(bs) < 1)
|
||||
break;
|
||||
|
||||
BitStream_Shift(bs, 1);
|
||||
|
||||
while (vk--)
|
||||
{
|
||||
const UINT32 add = (1 << k); /* add (1 << k) to run length */
|
||||
run += add;
|
||||
|
||||
/* update k, kp params */
|
||||
|
||||
kp += UP_GR;
|
||||
|
||||
if (kp > KPMAX)
|
||||
kp = KPMAX;
|
||||
|
||||
k = kp >> LSGR;
|
||||
}
|
||||
|
||||
/* next k bits contain run length remainder */
|
||||
|
||||
if (BitStream_GetRemainingLength(bs) < k)
|
||||
break;
|
||||
|
||||
bs->mask = ((1 << k) - 1);
|
||||
run += ((bs->accumulator >> (32 - k)) & bs->mask);
|
||||
BitStream_Shift(bs, k);
|
||||
|
||||
/* read sign bit */
|
||||
|
||||
if (BitStream_GetRemainingLength(bs) < 1)
|
||||
break;
|
||||
|
||||
sign = (bs->accumulator & 0x80000000) ? 1 : 0;
|
||||
BitStream_Shift(bs, 1);
|
||||
|
||||
/* count number of leading 1s */
|
||||
|
||||
cnt = lzcnt_s(~(bs->accumulator));
|
||||
|
||||
nbits = BitStream_GetRemainingLength(bs);
|
||||
|
||||
if (cnt > nbits)
|
||||
cnt = nbits;
|
||||
|
||||
vk = WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
|
||||
|
||||
while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0))
|
||||
{
|
||||
BitStream_Shift32(bs);
|
||||
|
||||
cnt = lzcnt_s(~(bs->accumulator));
|
||||
|
||||
nbits = BitStream_GetRemainingLength(bs);
|
||||
|
||||
if (cnt > nbits)
|
||||
cnt = nbits;
|
||||
|
||||
WINPR_ASSERT(cnt + vk <= UINT32_MAX);
|
||||
vk += WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
|
||||
}
|
||||
|
||||
BitStream_Shift(bs, (vk % 32));
|
||||
|
||||
if (BitStream_GetRemainingLength(bs) < 1)
|
||||
break;
|
||||
|
||||
BitStream_Shift(bs, 1);
|
||||
|
||||
/* next kr bits contain code remainder */
|
||||
|
||||
if (BitStream_GetRemainingLength(bs) < kr)
|
||||
break;
|
||||
|
||||
bs->mask = ((1 << kr) - 1);
|
||||
if (kr > 0)
|
||||
code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
|
||||
else
|
||||
code = 0;
|
||||
BitStream_Shift(bs, kr);
|
||||
|
||||
/* add (vk << kr) to code */
|
||||
|
||||
code |= (vk << kr);
|
||||
|
||||
if (!vk)
|
||||
{
|
||||
/* update kr, krp params */
|
||||
|
||||
if (krp > 2)
|
||||
krp -= 2;
|
||||
else
|
||||
krp = 0;
|
||||
|
||||
kr = krp >> LSGR;
|
||||
}
|
||||
else if (vk != 1)
|
||||
{
|
||||
/* update kr, krp params */
|
||||
|
||||
krp += vk;
|
||||
|
||||
if (krp > KPMAX)
|
||||
krp = KPMAX;
|
||||
|
||||
kr = krp >> LSGR;
|
||||
}
|
||||
|
||||
/* update k, kp params */
|
||||
|
||||
if (kp > DN_GR)
|
||||
kp -= DN_GR;
|
||||
else
|
||||
kp = 0;
|
||||
|
||||
k = kp >> LSGR;
|
||||
|
||||
/* compute magnitude from code */
|
||||
|
||||
if (sign)
|
||||
mag = WINPR_ASSERTING_INT_CAST(int16_t, (code + 1)) * -1;
|
||||
else
|
||||
mag = WINPR_ASSERTING_INT_CAST(int16_t, code + 1);
|
||||
|
||||
/* write to output stream */
|
||||
|
||||
offset = WINPR_ASSERTING_INT_CAST(size_t, (pOutput)-pDstData);
|
||||
size = run;
|
||||
|
||||
if ((offset + size) > rDstSize)
|
||||
size = WINPR_ASSERTING_INT_CAST(size_t, DstSize) - offset;
|
||||
|
||||
if (size)
|
||||
{
|
||||
ZeroMemory(pOutput, size * sizeof(INT16));
|
||||
pOutput += size;
|
||||
}
|
||||
|
||||
if ((pOutput - pDstData) < DstSize)
|
||||
{
|
||||
*pOutput = mag;
|
||||
pOutput++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Golomb-Rice (GR) Mode */
|
||||
|
||||
/* count number of leading 1s */
|
||||
|
||||
cnt = lzcnt_s(~(bs->accumulator));
|
||||
|
||||
size_t nbits = BitStream_GetRemainingLength(bs);
|
||||
|
||||
if (cnt > nbits)
|
||||
cnt = nbits;
|
||||
|
||||
vk = WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
|
||||
|
||||
while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0))
|
||||
{
|
||||
BitStream_Shift32(bs);
|
||||
|
||||
cnt = lzcnt_s(~(bs->accumulator));
|
||||
|
||||
nbits = BitStream_GetRemainingLength(bs);
|
||||
|
||||
if (cnt > nbits)
|
||||
cnt = nbits;
|
||||
|
||||
WINPR_ASSERT(cnt + vk <= UINT32_MAX);
|
||||
vk += WINPR_ASSERTING_INT_CAST(uint32_t, cnt);
|
||||
}
|
||||
|
||||
BitStream_Shift(bs, (vk % 32));
|
||||
|
||||
if (BitStream_GetRemainingLength(bs) < 1)
|
||||
break;
|
||||
|
||||
BitStream_Shift(bs, 1);
|
||||
|
||||
/* next kr bits contain code remainder */
|
||||
|
||||
if (BitStream_GetRemainingLength(bs) < kr)
|
||||
break;
|
||||
|
||||
bs->mask = ((1 << kr) - 1);
|
||||
if (kr > 0)
|
||||
code = (UINT16)((bs->accumulator >> (32 - kr)) & bs->mask);
|
||||
else
|
||||
code = 0;
|
||||
BitStream_Shift(bs, kr);
|
||||
|
||||
/* add (vk << kr) to code */
|
||||
|
||||
code |= (vk << kr);
|
||||
|
||||
if (!vk)
|
||||
{
|
||||
/* update kr, krp params */
|
||||
|
||||
if (krp > 2)
|
||||
krp -= 2;
|
||||
else
|
||||
krp = 0;
|
||||
|
||||
kr = (krp >> LSGR) & UINT32_MAX;
|
||||
}
|
||||
else if (vk != 1)
|
||||
{
|
||||
/* update kr, krp params */
|
||||
|
||||
krp += vk;
|
||||
|
||||
if (krp > KPMAX)
|
||||
krp = KPMAX;
|
||||
|
||||
kr = krp >> LSGR;
|
||||
}
|
||||
|
||||
if (mode == RLGR1) /* RLGR1 */
|
||||
{
|
||||
if (!code)
|
||||
{
|
||||
/* update k, kp params */
|
||||
|
||||
kp += UQ_GR;
|
||||
|
||||
if (kp > KPMAX)
|
||||
kp = KPMAX;
|
||||
|
||||
k = kp >> LSGR;
|
||||
|
||||
mag = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update k, kp params */
|
||||
|
||||
if (kp > DQ_GR)
|
||||
kp -= DQ_GR;
|
||||
else
|
||||
kp = 0;
|
||||
|
||||
k = kp >> LSGR;
|
||||
|
||||
/*
|
||||
* code = 2 * mag - sign
|
||||
* sign + code = 2 * mag
|
||||
*/
|
||||
|
||||
if (code & 1)
|
||||
mag = WINPR_ASSERTING_INT_CAST(INT16, (code + 1) >> 1) * -1;
|
||||
else
|
||||
mag = WINPR_ASSERTING_INT_CAST(INT16, code >> 1);
|
||||
}
|
||||
|
||||
if ((pOutput - pDstData) < DstSize)
|
||||
{
|
||||
*pOutput = mag;
|
||||
pOutput++;
|
||||
}
|
||||
}
|
||||
else if (mode == RLGR3) /* RLGR3 */
|
||||
{
|
||||
nIdx = 0;
|
||||
|
||||
if (code)
|
||||
{
|
||||
mag = WINPR_ASSERTING_INT_CAST(int16_t, code);
|
||||
nIdx = 32 - lzcnt_s(WINPR_ASSERTING_INT_CAST(uint32_t, mag));
|
||||
}
|
||||
|
||||
if (BitStream_GetRemainingLength(bs) < nIdx)
|
||||
break;
|
||||
|
||||
bs->mask = ((1 << nIdx) - 1);
|
||||
if (nIdx > 0)
|
||||
val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask);
|
||||
else
|
||||
val1 = 0;
|
||||
BitStream_Shift(bs, nIdx);
|
||||
|
||||
val2 = code - val1;
|
||||
|
||||
if (val1 && val2)
|
||||
{
|
||||
/* update k, kp params */
|
||||
|
||||
if (kp > 2 * DQ_GR)
|
||||
kp -= (2 * DQ_GR);
|
||||
else
|
||||
kp = 0;
|
||||
|
||||
k = kp >> LSGR;
|
||||
}
|
||||
else if (!val1 && !val2)
|
||||
{
|
||||
/* update k, kp params */
|
||||
|
||||
kp += (2 * UQ_GR);
|
||||
|
||||
if (kp > KPMAX)
|
||||
kp = KPMAX;
|
||||
|
||||
k = kp >> LSGR;
|
||||
}
|
||||
|
||||
if (val1 & 1)
|
||||
mag = WINPR_ASSERTING_INT_CAST(int16_t, (val1 + 1) >> 1) * -1;
|
||||
else
|
||||
mag = WINPR_ASSERTING_INT_CAST(int16_t, val1 >> 1);
|
||||
|
||||
if ((pOutput - pDstData) < DstSize)
|
||||
{
|
||||
*pOutput = mag;
|
||||
pOutput++;
|
||||
}
|
||||
|
||||
if (val2 & 1)
|
||||
mag = WINPR_ASSERTING_INT_CAST(int16_t, (val2 + 1) >> 1) * -1;
|
||||
else
|
||||
mag = WINPR_ASSERTING_INT_CAST(int16_t, val2 >> 1);
|
||||
|
||||
if ((pOutput - pDstData) < DstSize)
|
||||
{
|
||||
*pOutput = WINPR_ASSERTING_INT_CAST(int16_t, mag);
|
||||
pOutput++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
offset = WINPR_ASSERTING_INT_CAST(size_t, (pOutput - pDstData));
|
||||
|
||||
if (offset < rDstSize)
|
||||
{
|
||||
size = WINPR_ASSERTING_INT_CAST(size_t, DstSize) - offset;
|
||||
ZeroMemory(pOutput, size * 2);
|
||||
pOutput += size;
|
||||
}
|
||||
|
||||
offset = WINPR_ASSERTING_INT_CAST(size_t, (pOutput - pDstData));
|
||||
|
||||
if ((DstSize < 0) || (offset != (size_t)DstSize))
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Returns the next coefficient (a signed int) to encode, from the input stream */
|
||||
#define GetNextInput(_n) \
|
||||
do \
|
||||
{ \
|
||||
if (data_size > 0) \
|
||||
{ \
|
||||
(_n) = *data++; \
|
||||
data_size--; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
(_n) = 0; \
|
||||
} \
|
||||
} while (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 */
|
||||
static inline void OutputBit(RFX_BITSTREAM* bs, uint32_t count, UINT8 bit)
|
||||
{
|
||||
UINT16 _b = ((bit) ? 0xFFFF : 0);
|
||||
const uint32_t rem = count % 16;
|
||||
for (uint32_t x = 0; x < count - rem; x += 16)
|
||||
rfx_bitstream_put_bits(bs, _b, 16);
|
||||
|
||||
if (rem > 0)
|
||||
rfx_bitstream_put_bits(bs, _b, rem);
|
||||
}
|
||||
|
||||
/* Converts the input value to (2 * abs(input) - sign(input)), where sign(input) = (input < 0 ? 1 :
|
||||
* 0) and returns it */
|
||||
static inline UINT32 Get2MagSign(INT32 input)
|
||||
{
|
||||
if (input >= 0)
|
||||
return WINPR_ASSERTING_INT_CAST(UINT32, 2 * input);
|
||||
return WINPR_ASSERTING_INT_CAST(UINT32, -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, uint32_t* krp, UINT32 val)
|
||||
{
|
||||
uint32_t kr = *krp >> LSGR;
|
||||
|
||||
/* unary part of GR code */
|
||||
|
||||
const uint32_t vk = val >> kr;
|
||||
OutputBit(bs, vk, 1);
|
||||
OutputBit(bs, 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)
|
||||
{
|
||||
(void)UpdateParam(krp, -2);
|
||||
}
|
||||
else if (vk > 1)
|
||||
{
|
||||
(void)UpdateParam(krp, WINPR_CXX_COMPAT_CAST(int32_t, vk));
|
||||
}
|
||||
}
|
||||
|
||||
int rfx_rlgr_encode(RLGR_MODE mode, const INT16* WINPR_RESTRICT data, UINT32 data_size,
|
||||
BYTE* WINPR_RESTRICT buffer, UINT32 buffer_size)
|
||||
{
|
||||
uint32_t k = 0;
|
||||
uint32_t kp = 0;
|
||||
uint32_t krp = 0;
|
||||
RFX_BITSTREAM* bs = nullptr;
|
||||
|
||||
if (!(bs = (RFX_BITSTREAM*)winpr_aligned_calloc(1, sizeof(RFX_BITSTREAM), 32)))
|
||||
return 0;
|
||||
|
||||
rfx_bitstream_attach(bs, buffer, buffer_size);
|
||||
|
||||
/* initialize the parameters */
|
||||
k = 1;
|
||||
kp = 1 << LSGR;
|
||||
krp = 1 << LSGR;
|
||||
|
||||
/* process all the input coefficients */
|
||||
while (data_size > 0)
|
||||
{
|
||||
int input = 0;
|
||||
|
||||
if (k)
|
||||
{
|
||||
uint32_t numZeros = 0;
|
||||
uint32_t runmax = 0;
|
||||
BYTE sign = 0;
|
||||
|
||||
/* 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(bs, 1, 0); /* output a zero bit */
|
||||
numZeros -= runmax;
|
||||
k = UpdateParam(&kp, UP_GR); /* update kp, k */
|
||||
runmax = 1 << k;
|
||||
}
|
||||
|
||||
/* output a 1 to terminate runs */
|
||||
OutputBit(bs, 1, 1);
|
||||
|
||||
/* output the remaining run length using k bits */
|
||||
OutputBits(k, numZeros);
|
||||
|
||||
/* note: when we reach here and the last byte being encoded is 0, we still
|
||||
need to output the last two bits, otherwise mstsc will crash */
|
||||
|
||||
/* encode the nonzero value using GR coding */
|
||||
const UINT32 mag =
|
||||
(UINT32)(input < 0 ? -input : input); /* absolute value of input coefficient */
|
||||
sign = (input < 0 ? 1 : 0); /* sign of input coefficient */
|
||||
|
||||
OutputBit(bs, 1, sign); /* output the sign bit */
|
||||
CodeGR(&krp, mag ? mag - 1 : 0); /* output GR code for (mag - 1) */
|
||||
|
||||
k = UpdateParam(&kp, -DN_GR);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* GOLOMB-RICE MODE */
|
||||
|
||||
if (mode == RLGR1)
|
||||
{
|
||||
UINT32 twoMs = 0;
|
||||
|
||||
/* RLGR1 variant */
|
||||
|
||||
/* convert input to (2*magnitude - sign), encode using GR code */
|
||||
GetNextInput(input);
|
||||
twoMs = Get2MagSign(input);
|
||||
CodeGR(&krp, twoMs);
|
||||
|
||||
/* update k, kp */
|
||||
/* NOTE: as of Aug 2011, the algorithm is still wrongly documented
|
||||
and the update direction is reversed */
|
||||
if (twoMs)
|
||||
{
|
||||
k = UpdateParam(&kp, -DQ_GR);
|
||||
}
|
||||
else
|
||||
{
|
||||
k = UpdateParam(&kp, UQ_GR);
|
||||
}
|
||||
}
|
||||
else /* mode == RLGR3 */
|
||||
{
|
||||
UINT32 twoMs1 = 0;
|
||||
UINT32 twoMs2 = 0;
|
||||
UINT32 sum2Ms = 0;
|
||||
UINT32 nIdx = 0;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
k = UpdateParam(&kp, -2 * DQ_GR);
|
||||
}
|
||||
else if (!twoMs1 && !twoMs2)
|
||||
{
|
||||
k = UpdateParam(&kp, 2 * UQ_GR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rfx_bitstream_flush(bs);
|
||||
uint32_t processed_size = rfx_bitstream_get_processed_bytes(bs);
|
||||
winpr_aligned_free(bs);
|
||||
|
||||
return WINPR_ASSERTING_INT_CAST(int, processed_size);
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_LIB_CODEC_RFX_RLGR_H
|
||||
#define FREERDP_LIB_CODEC_RFX_RLGR_H
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rfx_rlgr_encode(RLGR_MODE mode, const INT16* WINPR_RESTRICT data,
|
||||
UINT32 data_size, BYTE* WINPR_RESTRICT buffer,
|
||||
UINT32 buffer_size);
|
||||
|
||||
WINPR_ATTR_NODISCARD
|
||||
FREERDP_LOCAL int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* WINPR_RESTRICT pSrcData,
|
||||
UINT32 SrcSize, INT16* WINPR_RESTRICT pDstData, UINT32 rDstSize);
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_RLGR_H */
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_LIB_CODEC_RFX_TYPES_H
|
||||
#define FREERDP_LIB_CODEC_RFX_TYPES_H
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/pool.h>
|
||||
#include <winpr/wlog.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/utils/profiler.h>
|
||||
|
||||
#define RFX_TAG FREERDP_TAG("codec.rfx")
|
||||
#ifdef WITH_DEBUG_RFX
|
||||
#define DEBUG_RFX(...) WLog_DBG(RFX_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_RFX(...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define RFX_DECODED_SYNC 0x00000001
|
||||
#define RFX_DECODED_CONTEXT 0x00000002
|
||||
#define RFX_DECODED_VERSIONS 0x00000004
|
||||
#define RFX_DECODED_CHANNELS 0x00000008
|
||||
#define RFX_DECODED_HEADERS 0x0000000F
|
||||
|
||||
typedef enum
|
||||
{
|
||||
RFX_STATE_INITIAL,
|
||||
RFX_STATE_SERVER_UNINITIALIZED,
|
||||
RFX_STATE_SEND_HEADERS,
|
||||
RFX_STATE_SEND_FRAME_DATA,
|
||||
RFX_STATE_FRAME_DATA_SENT,
|
||||
RFX_STATE_FINAL
|
||||
} RFX_STATE;
|
||||
|
||||
typedef struct S_RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE_COMPOSE_WORK_PARAM;
|
||||
|
||||
typedef struct S_RFX_CONTEXT_PRIV RFX_CONTEXT_PRIV;
|
||||
struct S_RFX_CONTEXT_PRIV
|
||||
{
|
||||
wLog* log;
|
||||
wObjectPool* TilePool;
|
||||
|
||||
BOOL UseThreads;
|
||||
PTP_WORK* workObjects;
|
||||
RFX_TILE_COMPOSE_WORK_PARAM* tileWorkParams;
|
||||
|
||||
wBufferPool* BufferPool;
|
||||
|
||||
/* 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_ycbcr_to_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_rgb_to_ycbcr)
|
||||
PROFILER_DEFINE(prof_rfx_encode_format_rgb)
|
||||
};
|
||||
|
||||
struct S_RFX_MESSAGE
|
||||
{
|
||||
UINT32 frameIdx;
|
||||
|
||||
/**
|
||||
* 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 numRects;
|
||||
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 numTiles;
|
||||
size_t allocatedTiles;
|
||||
RFX_TILE** tiles;
|
||||
|
||||
UINT16 numQuant;
|
||||
UINT32* quantVals;
|
||||
|
||||
UINT32 tilesDataSize;
|
||||
|
||||
BOOL freeArray;
|
||||
};
|
||||
|
||||
struct S_RFX_MESSAGE_LIST
|
||||
{
|
||||
struct S_RFX_MESSAGE* list;
|
||||
size_t count;
|
||||
RFX_CONTEXT* context;
|
||||
};
|
||||
|
||||
struct S_RFX_CONTEXT
|
||||
{
|
||||
RFX_STATE state;
|
||||
|
||||
BOOL encoder;
|
||||
UINT16 flags;
|
||||
UINT16 properties;
|
||||
UINT16 width;
|
||||
UINT16 height;
|
||||
RLGR_MODE mode;
|
||||
UINT32 version;
|
||||
UINT32 codec_id;
|
||||
UINT32 codec_version;
|
||||
UINT32 pixel_format;
|
||||
BYTE bits_per_pixel;
|
||||
|
||||
/* color palette allocated by the application */
|
||||
const BYTE* palette;
|
||||
|
||||
/* temporary data within a frame */
|
||||
UINT32 frameIdx;
|
||||
BYTE numQuant;
|
||||
UINT32* quants;
|
||||
BYTE quantIdxY;
|
||||
BYTE quantIdxCb;
|
||||
BYTE quantIdxCr;
|
||||
|
||||
/* decoded header blocks */
|
||||
UINT32 decodedHeaderBlocks;
|
||||
UINT16 expectedDataBlockType;
|
||||
struct S_RFX_MESSAGE currentMessage;
|
||||
|
||||
/* routines */
|
||||
void (*quantization_decode)(INT16* WINPR_RESTRICT buffer,
|
||||
const UINT32* WINPR_RESTRICT quantization_values);
|
||||
void (*quantization_encode)(INT16* WINPR_RESTRICT buffer,
|
||||
const UINT32* WINPR_RESTRICT quantization_values);
|
||||
void (*dwt_2d_decode)(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt_buffer);
|
||||
void (*dwt_2d_extrapolate_decode)(INT16* WINPR_RESTRICT src, INT16* WINPR_RESTRICT temp);
|
||||
void (*dwt_2d_encode)(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt_buffer);
|
||||
WINPR_ATTR_NODISCARD int (*rlgr_decode)(RLGR_MODE mode, const BYTE* WINPR_RESTRICT data,
|
||||
UINT32 data_size, INT16* WINPR_RESTRICT buffer,
|
||||
UINT32 buffer_size);
|
||||
WINPR_ATTR_NODISCARD int (*rlgr_encode)(RLGR_MODE mode, const INT16* WINPR_RESTRICT data,
|
||||
UINT32 data_size, BYTE* WINPR_RESTRICT buffer,
|
||||
UINT32 buffer_size);
|
||||
|
||||
/* private definitions */
|
||||
RFX_CONTEXT_PRIV* priv;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_TYPES_H */
|
||||
+455
@@ -0,0 +1,455 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* NSCodec Library - SSE2 Optimizations
|
||||
*
|
||||
* Copyright 2012 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 <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
#include <winpr/platform.h>
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "../nsc_types.h"
|
||||
#include "nsc_sse2.h"
|
||||
|
||||
#include "../../core/simd.h"
|
||||
#include "../../primitives/sse/prim_avxsse.h"
|
||||
|
||||
#if defined(SSE_AVX_INTRINSICS_ENABLED)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
static inline size_t nsc_encode_next_bgrx32(const BYTE* src, __m128i* r_val, __m128i* g_val,
|
||||
__m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
*b_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16), *(src + 12),
|
||||
*(src + 8), *(src + 4), *src);
|
||||
*g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17), *(src + 13),
|
||||
*(src + 9), *(src + 5), *(src + 1));
|
||||
*r_val = _mm_set_epi16(*(src + 30), *(src + 26), *(src + 22), *(src + 18), *(src + 14),
|
||||
*(src + 10), *(src + 6), *(src + 2));
|
||||
*a_val = _mm_set1_epi16(0xFF);
|
||||
return 32;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_bgra32(const BYTE* src, __m128i* r_val, __m128i* g_val,
|
||||
__m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
*b_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16), *(src + 12),
|
||||
*(src + 8), *(src + 4), *src);
|
||||
*g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17), *(src + 13),
|
||||
*(src + 9), *(src + 5), *(src + 1));
|
||||
*r_val = _mm_set_epi16(*(src + 30), *(src + 26), *(src + 22), *(src + 18), *(src + 14),
|
||||
*(src + 10), *(src + 6), *(src + 2));
|
||||
*a_val = _mm_set_epi16(*(src + 31), *(src + 27), *(src + 23), *(src + 19), *(src + 15),
|
||||
*(src + 11), *(src + 7), *(src + 3));
|
||||
return 32;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_rgbx32(const BYTE* src, __m128i* r_val, __m128i* g_val,
|
||||
__m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
*r_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16), *(src + 12),
|
||||
*(src + 8), *(src + 4), *src);
|
||||
*g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17), *(src + 13),
|
||||
*(src + 9), *(src + 5), *(src + 1));
|
||||
*b_val = _mm_set_epi16(*(src + 30), *(src + 26), *(src + 22), *(src + 18), *(src + 14),
|
||||
*(src + 10), *(src + 6), *(src + 2));
|
||||
*a_val = _mm_set1_epi16(0xFF);
|
||||
return 32;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_rgba32(const BYTE* src, __m128i* r_val, __m128i* g_val,
|
||||
__m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
*r_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16), *(src + 12),
|
||||
*(src + 8), *(src + 4), *src);
|
||||
*g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17), *(src + 13),
|
||||
*(src + 9), *(src + 5), *(src + 1));
|
||||
*b_val = _mm_set_epi16(*(src + 30), *(src + 26), *(src + 22), *(src + 18), *(src + 14),
|
||||
*(src + 10), *(src + 6), *(src + 2));
|
||||
*a_val = _mm_set_epi16(*(src + 31), *(src + 27), *(src + 23), *(src + 19), *(src + 15),
|
||||
*(src + 11), *(src + 7), *(src + 3));
|
||||
return 32;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_bgr24(const BYTE* src, __m128i* r_val, __m128i* g_val,
|
||||
__m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
*b_val = _mm_set_epi16(*(src + 21), *(src + 18), *(src + 15), *(src + 12), *(src + 9),
|
||||
*(src + 6), *(src + 3), *src);
|
||||
*g_val = _mm_set_epi16(*(src + 22), *(src + 19), *(src + 16), *(src + 13), *(src + 10),
|
||||
*(src + 7), *(src + 4), *(src + 1));
|
||||
*r_val = _mm_set_epi16(*(src + 23), *(src + 20), *(src + 17), *(src + 14), *(src + 11),
|
||||
*(src + 8), *(src + 5), *(src + 2));
|
||||
*a_val = _mm_set1_epi16(0xFF);
|
||||
return 24;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_rgb24(const BYTE* src, __m128i* r_val, __m128i* g_val,
|
||||
__m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
*r_val = _mm_set_epi16(*(src + 21), *(src + 18), *(src + 15), *(src + 12), *(src + 9),
|
||||
*(src + 6), *(src + 3), *src);
|
||||
*g_val = _mm_set_epi16(*(src + 22), *(src + 19), *(src + 16), *(src + 13), *(src + 10),
|
||||
*(src + 7), *(src + 4), *(src + 1));
|
||||
*b_val = _mm_set_epi16(*(src + 23), *(src + 20), *(src + 17), *(src + 14), *(src + 11),
|
||||
*(src + 8), *(src + 5), *(src + 2));
|
||||
*a_val = _mm_set1_epi16(0xFF);
|
||||
return 24;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_bgr16(const BYTE* src, __m128i* r_val, __m128i* g_val,
|
||||
__m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
*b_val = _mm_set_epi16(
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 15)) & 0xF8) | ((*(src + 15)) >> 5)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 13)) & 0xF8) | ((*(src + 13)) >> 5)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 11)) & 0xF8) | ((*(src + 11)) >> 5)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 9)) & 0xF8) | ((*(src + 9)) >> 5)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 7)) & 0xF8) | ((*(src + 7)) >> 5)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 5)) & 0xF8) | ((*(src + 5)) >> 5)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 3)) & 0xF8) | ((*(src + 3)) >> 5)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)));
|
||||
*g_val = _mm_set_epi16(
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 15)) & 0x07) << 5) | (((*(src + 14)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 13)) & 0x07) << 5) | (((*(src + 12)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 11)) & 0x07) << 5) | (((*(src + 10)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 9)) & 0x07) << 5) | (((*(src + 8)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 7)) & 0x07) << 5) | (((*(src + 6)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 5)) & 0x07) << 5) | (((*(src + 4)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 3)) & 0x07) << 5) | (((*(src + 2)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)));
|
||||
*r_val = _mm_set_epi16(
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 14)) & 0x1F) << 3) | (((*(src + 14)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 12)) & 0x1F) << 3) | (((*(src + 12)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 10)) & 0x1F) << 3) | (((*(src + 10)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 8)) & 0x1F) << 3) | (((*(src + 8)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 6)) & 0x1F) << 3) | (((*(src + 6)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 4)) & 0x1F) << 3) | (((*(src + 4)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 2)) & 0x1F) << 3) | (((*(src + 2)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, (((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)));
|
||||
*a_val = _mm_set1_epi16(0xFF);
|
||||
return 16;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_rgb16(const BYTE* src, __m128i* r_val, __m128i* g_val,
|
||||
__m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
*r_val = _mm_set_epi16(WINPR_ASSERTING_INT_CAST(INT16, ((src[15] & 0xF8) | (src[15] >> 5))),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((src[13] & 0xF8) | (src[13] >> 5))),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((src[11] & 0xF8) | (src[11] >> 5))),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((src[9] & 0xF8) | (src[9] >> 5))),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((src[7] & 0xF8) | (src[7] >> 5))),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((src[5] & 0xF8) | (src[5] >> 5))),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((src[3] & 0xF8) | (src[3] >> 5))),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, ((src[1] & 0xF8) | (src[1] >> 5))));
|
||||
*g_val = _mm_set_epi16(
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 15)) & 0x07) << 5) | (((*(src + 14)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 13)) & 0x07) << 5) | (((*(src + 12)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 11)) & 0x07) << 5) | (((*(src + 10)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 9)) & 0x07) << 5) | (((*(src + 8)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 7)) & 0x07) << 5) | (((*(src + 6)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 5)) & 0x07) << 5) | (((*(src + 4)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 3)) & 0x07) << 5) | (((*(src + 2)) & 0xE0) >> 3)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)));
|
||||
*b_val = _mm_set_epi16(
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 14)) & 0x1F) << 3) | (((*(src + 14)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 12)) & 0x1F) << 3) | (((*(src + 12)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 10)) & 0x1F) << 3) | (((*(src + 10)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 8)) & 0x1F) << 3) | (((*(src + 8)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 6)) & 0x1F) << 3) | (((*(src + 6)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 4)) & 0x1F) << 3) | (((*(src + 4)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16,
|
||||
(((*(src + 2)) & 0x1F) << 3) | (((*(src + 2)) >> 2) & 0x07)),
|
||||
WINPR_ASSERTING_INT_CAST(INT16, (((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)));
|
||||
*a_val = _mm_set1_epi16(0xFF);
|
||||
return 16;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_a4(const BYTE* src, const BYTE* palette, __m128i* r_val,
|
||||
__m128i* g_val, __m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
BYTE idx[8] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
for (int shift = 7; shift >= 0; shift--)
|
||||
{
|
||||
idx[shift] = ((*src) >> shift) & 1;
|
||||
idx[shift] |= (((*(src + 1)) >> shift) & 1) << 1;
|
||||
idx[shift] |= (((*(src + 2)) >> shift) & 1) << 2;
|
||||
idx[shift] |= (((*(src + 3)) >> shift) & 1) << 3;
|
||||
idx[shift] *= 3;
|
||||
}
|
||||
|
||||
*r_val = _mm_set_epi16(palette[idx[0]], palette[idx[1]], palette[idx[2]], palette[idx[3]],
|
||||
palette[idx[4]], palette[idx[5]], palette[idx[6]], palette[idx[7]]);
|
||||
*g_val = _mm_set_epi16(palette[idx[0] + 1], palette[idx[1] + 1], palette[idx[2] + 1],
|
||||
palette[idx[3] + 1], palette[idx[4] + 1], palette[idx[5] + 1],
|
||||
palette[idx[6] + 1], palette[idx[7] + 1]);
|
||||
*b_val = _mm_set_epi16(palette[idx[0] + 2], palette[idx[1] + 2], palette[idx[2] + 2],
|
||||
palette[idx[3] + 2], palette[idx[4] + 2], palette[idx[5] + 2],
|
||||
palette[idx[6] + 2], palette[idx[7] + 2]);
|
||||
*a_val = _mm_set1_epi16(0xFF);
|
||||
return 4;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_rgb8(const BYTE* src, const BYTE* palette, __m128i* r_val,
|
||||
__m128i* g_val, __m128i* b_val, __m128i* a_val)
|
||||
{
|
||||
*r_val = _mm_set_epi16(palette[(*(src + 7ULL)) * 3ULL], palette[(*(src + 6ULL)) * 3ULL],
|
||||
palette[(*(src + 5ULL)) * 3ULL], palette[(*(src + 4ULL)) * 3ULL],
|
||||
palette[(*(src + 3ULL)) * 3ULL], palette[(*(src + 2ULL)) * 3ULL],
|
||||
palette[(*(src + 1ULL)) * 3ULL], palette[(*src) * 3ULL]);
|
||||
*g_val = _mm_set_epi16(
|
||||
palette[(*(src + 7ULL)) * 3ULL + 1ULL], palette[(*(src + 6ULL)) * 3ULL + 1ULL],
|
||||
palette[(*(src + 5ULL)) * 3ULL + 1ULL], palette[(*(src + 4ULL)) * 3ULL + 1ULL],
|
||||
palette[(*(src + 3ULL)) * 3ULL + 1ULL], palette[(*(src + 2ULL)) * 3ULL + 1ULL],
|
||||
palette[(*(src + 1ULL)) * 3ULL + 1ULL], palette[(*src) * 3ULL + 1ULL]);
|
||||
*b_val = _mm_set_epi16(
|
||||
palette[(*(src + 7ULL)) * 3ULL + 2ULL], palette[(*(src + 6ULL)) * 3ULL + 2ULL],
|
||||
palette[(*(src + 5ULL)) * 3ULL + 2ULL], palette[(*(src + 4ULL)) * 3ULL + 2ULL],
|
||||
palette[(*(src + 3ULL)) * 3ULL + 2ULL], palette[(*(src + 2ULL)) * 3ULL + 2ULL],
|
||||
palette[(*(src + 1ULL)) * 3ULL + 2ULL], palette[(*src) * 3ULL + 2ULL]);
|
||||
*a_val = _mm_set1_epi16(0xFF);
|
||||
return 8;
|
||||
}
|
||||
|
||||
static inline size_t nsc_encode_next_rgba(UINT32 format, const BYTE* src, const BYTE* palette,
|
||||
__m128i* r_val, __m128i* g_val, __m128i* b_val,
|
||||
__m128i* a_val)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PIXEL_FORMAT_BGRX32:
|
||||
return nsc_encode_next_bgrx32(src, r_val, g_val, b_val, a_val);
|
||||
|
||||
case PIXEL_FORMAT_BGRA32:
|
||||
return nsc_encode_next_bgra32(src, r_val, g_val, b_val, a_val);
|
||||
|
||||
case PIXEL_FORMAT_RGBX32:
|
||||
return nsc_encode_next_rgbx32(src, r_val, g_val, b_val, a_val);
|
||||
|
||||
case PIXEL_FORMAT_RGBA32:
|
||||
return nsc_encode_next_rgba32(src, r_val, g_val, b_val, a_val);
|
||||
|
||||
case PIXEL_FORMAT_BGR24:
|
||||
return nsc_encode_next_bgr24(src, r_val, g_val, b_val, a_val);
|
||||
|
||||
case PIXEL_FORMAT_RGB24:
|
||||
return nsc_encode_next_rgb24(src, r_val, g_val, b_val, a_val);
|
||||
|
||||
case PIXEL_FORMAT_BGR16:
|
||||
return nsc_encode_next_bgr16(src, r_val, g_val, b_val, a_val);
|
||||
|
||||
case PIXEL_FORMAT_RGB16:
|
||||
return nsc_encode_next_rgb16(src, r_val, g_val, b_val, a_val);
|
||||
|
||||
case PIXEL_FORMAT_A4:
|
||||
return nsc_encode_next_a4(src, palette, r_val, g_val, b_val, a_val);
|
||||
|
||||
case PIXEL_FORMAT_RGB8:
|
||||
return nsc_encode_next_rgb8(src, palette, r_val, g_val, b_val, a_val);
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, const BYTE* data, UINT32 scanline)
|
||||
{
|
||||
size_t y = 0;
|
||||
|
||||
if (!context || !data || (scanline == 0))
|
||||
return FALSE;
|
||||
|
||||
const UINT16 tempWidth = ROUND_UP_TO(context->width, 8);
|
||||
const UINT16 rw = (context->ChromaSubsamplingLevel > 0 ? tempWidth : context->width);
|
||||
|
||||
const BYTE ccl = WINPR_ASSERTING_INT_CAST(BYTE, context->ColorLossLevel);
|
||||
|
||||
for (; y < context->height; y++)
|
||||
{
|
||||
const BYTE* src = data + (context->height - 1 - y) * scanline;
|
||||
BYTE* yplane = context->priv->PlaneBuffers[0] + y * rw;
|
||||
BYTE* coplane = context->priv->PlaneBuffers[1] + y * rw;
|
||||
BYTE* cgplane = context->priv->PlaneBuffers[2] + y * rw;
|
||||
BYTE* aplane = context->priv->PlaneBuffers[3] + y * context->width;
|
||||
|
||||
for (UINT16 x = 0; x < context->width; x += 8)
|
||||
{
|
||||
__m128i r_val = WINPR_C_ARRAY_INIT;
|
||||
__m128i g_val = WINPR_C_ARRAY_INIT;
|
||||
__m128i b_val = WINPR_C_ARRAY_INIT;
|
||||
__m128i a_val = WINPR_C_ARRAY_INIT;
|
||||
|
||||
const size_t rc = nsc_encode_next_rgba(context->format, src, context->palette, &r_val,
|
||||
&g_val, &b_val, &a_val);
|
||||
src += rc;
|
||||
|
||||
__m128i y_val = _mm_srai_epi16(r_val, 2);
|
||||
y_val = _mm_add_epi16(y_val, _mm_srai_epi16(g_val, 1));
|
||||
y_val = _mm_add_epi16(y_val, _mm_srai_epi16(b_val, 2));
|
||||
__m128i co_val = _mm_sub_epi16(r_val, b_val);
|
||||
co_val = _mm_srai_epi16(co_val, ccl);
|
||||
__m128i cg_val = _mm_sub_epi16(g_val, _mm_srai_epi16(r_val, 1));
|
||||
cg_val = _mm_sub_epi16(cg_val, _mm_srai_epi16(b_val, 1));
|
||||
cg_val = _mm_srai_epi16(cg_val, ccl);
|
||||
y_val = _mm_packus_epi16(y_val, y_val);
|
||||
STORE_SI128(yplane, y_val);
|
||||
co_val = _mm_packs_epi16(co_val, co_val);
|
||||
STORE_SI128(coplane, co_val);
|
||||
cg_val = _mm_packs_epi16(cg_val, cg_val);
|
||||
STORE_SI128(cgplane, cg_val);
|
||||
a_val = _mm_packus_epi16(a_val, a_val);
|
||||
STORE_SI128(aplane, a_val);
|
||||
yplane += 8;
|
||||
coplane += 8;
|
||||
cgplane += 8;
|
||||
aplane += 8;
|
||||
}
|
||||
|
||||
if (context->ChromaSubsamplingLevel > 0 && (context->width % 2) == 1)
|
||||
{
|
||||
context->priv->PlaneBuffers[0][y * rw + context->width] =
|
||||
context->priv->PlaneBuffers[0][y * rw + context->width - 1];
|
||||
context->priv->PlaneBuffers[1][y * rw + context->width] =
|
||||
context->priv->PlaneBuffers[1][y * rw + context->width - 1];
|
||||
context->priv->PlaneBuffers[2][y * rw + context->width] =
|
||||
context->priv->PlaneBuffers[2][y * rw + context->width - 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (context->ChromaSubsamplingLevel > 0 && (y % 2) == 1)
|
||||
{
|
||||
BYTE* yplane = context->priv->PlaneBuffers[0] + y * rw;
|
||||
BYTE* coplane = context->priv->PlaneBuffers[1] + y * rw;
|
||||
BYTE* cgplane = context->priv->PlaneBuffers[2] + y * rw;
|
||||
CopyMemory(yplane, yplane - rw, rw);
|
||||
CopyMemory(coplane, coplane - rw, rw);
|
||||
CopyMemory(cgplane, cgplane - rw, rw);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void nsc_encode_subsampling_sse2(NSC_CONTEXT* context)
|
||||
{
|
||||
BYTE* co_dst = nullptr;
|
||||
BYTE* cg_dst = nullptr;
|
||||
INT8* co_src0 = nullptr;
|
||||
INT8* co_src1 = nullptr;
|
||||
INT8* cg_src0 = nullptr;
|
||||
INT8* cg_src1 = nullptr;
|
||||
UINT32 tempWidth = 0;
|
||||
UINT32 tempHeight = 0;
|
||||
__m128i t;
|
||||
__m128i val;
|
||||
__m128i mask = _mm_set1_epi16(0xFF);
|
||||
tempWidth = ROUND_UP_TO(context->width, 8);
|
||||
tempHeight = ROUND_UP_TO(context->height, 2);
|
||||
|
||||
for (size_t y = 0; y < tempHeight >> 1; y++)
|
||||
{
|
||||
co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
|
||||
cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
|
||||
co_src0 = (INT8*)context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
|
||||
co_src1 = co_src0 + tempWidth;
|
||||
cg_src0 = (INT8*)context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
|
||||
cg_src1 = cg_src0 + tempWidth;
|
||||
|
||||
for (UINT32 x = 0; x < tempWidth >> 1; x += 8)
|
||||
{
|
||||
t = LOAD_SI128(co_src0);
|
||||
t = _mm_avg_epu8(t, LOAD_SI128(co_src1));
|
||||
val = _mm_and_si128(_mm_srli_si128(t, 1), mask);
|
||||
val = _mm_avg_epu16(val, _mm_and_si128(t, mask));
|
||||
val = _mm_packus_epi16(val, val);
|
||||
STORE_SI128(co_dst, val);
|
||||
co_dst += 8;
|
||||
co_src0 += 16;
|
||||
co_src1 += 16;
|
||||
t = LOAD_SI128(cg_src0);
|
||||
t = _mm_avg_epu8(t, LOAD_SI128(cg_src1));
|
||||
val = _mm_and_si128(_mm_srli_si128(t, 1), mask);
|
||||
val = _mm_avg_epu16(val, _mm_and_si128(t, mask));
|
||||
val = _mm_packus_epi16(val, val);
|
||||
STORE_SI128(cg_dst, val);
|
||||
cg_dst += 8;
|
||||
cg_src0 += 16;
|
||||
cg_src1 += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL nsc_encode_sse2(NSC_CONTEXT* WINPR_RESTRICT context, const BYTE* WINPR_RESTRICT data,
|
||||
UINT32 scanline)
|
||||
{
|
||||
if (!nsc_encode_argb_to_aycocg_sse2(context, data, scanline))
|
||||
return FALSE;
|
||||
|
||||
if (context->ChromaSubsamplingLevel > 0)
|
||||
nsc_encode_subsampling_sse2(context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void nsc_init_sse2_int(NSC_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
#if defined(SSE_AVX_INTRINSICS_ENABLED)
|
||||
WLog_VRB(PRIM_TAG, "SSE2/SSE3 optimizations");
|
||||
PROFILER_RENAME(context->priv->prof_nsc_encode, "nsc_encode_sse2")
|
||||
context->encode = nsc_encode_sse2;
|
||||
#else
|
||||
WLog_VRB(PRIM_TAG, "undefined WITH_SIMD or SSE2 intrinsics not available");
|
||||
WINPR_UNUSED(context);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* NSCodec Library - SSE2 Optimizations
|
||||
*
|
||||
* Copyright 2012 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 FREERDP_LIB_CODEC_NSC_SSE2_H
|
||||
#define FREERDP_LIB_CODEC_NSC_SSE2_H
|
||||
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL void nsc_init_sse2_int(NSC_CONTEXT* WINPR_RESTRICT context);
|
||||
static inline void nsc_init_sse2(NSC_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
if (!IsProcessorFeaturePresent(PF_SSE2_INSTRUCTIONS_AVAILABLE) ||
|
||||
!IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE))
|
||||
return;
|
||||
|
||||
nsc_init_sse2_int(context);
|
||||
}
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_NSC_SSE2_H */
|
||||
+470
@@ -0,0 +1,470 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX Codec Library - SSE2 Optimizations
|
||||
*
|
||||
* Copyright 2011 Stephen Erisman
|
||||
* Copyright 2011 Norbert Federa <norbert.federa@thincast.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 <winpr/assert.h>
|
||||
#include <winpr/cast.h>
|
||||
#include <winpr/platform.h>
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include "../rfx_types.h"
|
||||
#include "rfx_sse2.h"
|
||||
|
||||
#include "../../core/simd.h"
|
||||
#include "../../primitives/sse/prim_avxsse.h"
|
||||
|
||||
#if defined(SSE_AVX_INTRINSICS_ENABLED)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <xmmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __attribute__(...)
|
||||
#endif
|
||||
|
||||
#define CACHE_LINE_BYTES 64
|
||||
|
||||
#ifndef __clang__
|
||||
#define ATTRIBUTES __gnu_inline__, __always_inline__, __artificial__
|
||||
#else
|
||||
#define ATTRIBUTES __gnu_inline__, __always_inline__
|
||||
#endif
|
||||
|
||||
static inline void __attribute__((ATTRIBUTES)) mm_prefetch_buffer(char* WINPR_RESTRICT buffer,
|
||||
size_t num_bytes)
|
||||
{
|
||||
__m128i* buf = (__m128i*)buffer;
|
||||
|
||||
for (size_t i = 0; i < (num_bytes / sizeof(__m128i)); i += (CACHE_LINE_BYTES / sizeof(__m128i)))
|
||||
{
|
||||
_mm_prefetch((char*)(&buf[i]), _MM_HINT_NTA);
|
||||
}
|
||||
}
|
||||
|
||||
/* rfx_decode_ycbcr_to_rgb_sse2 code now resides in the primitives library. */
|
||||
/* rfx_encode_rgb_to_ycbcr_sse2 code now resides in the primitives library. */
|
||||
|
||||
static inline void __attribute__((ATTRIBUTES))
|
||||
rfx_quantization_decode_block_sse2(INT16* WINPR_RESTRICT buffer, const size_t buffer_size,
|
||||
const UINT32 factor)
|
||||
{
|
||||
__m128i* ptr = (__m128i*)buffer;
|
||||
const __m128i* buf_end = (__m128i*)(buffer + buffer_size);
|
||||
|
||||
if (factor == 0)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
const __m128i la = LOAD_SI128(ptr);
|
||||
const __m128i a = _mm_slli_epi16(la, WINPR_ASSERTING_INT_CAST(int, factor));
|
||||
|
||||
STORE_SI128(ptr, a);
|
||||
ptr++;
|
||||
} while (ptr < buf_end);
|
||||
}
|
||||
|
||||
static void rfx_quantization_decode_sse2(INT16* WINPR_RESTRICT buffer,
|
||||
const UINT32* WINPR_RESTRICT quantVals)
|
||||
{
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(quantVals);
|
||||
|
||||
mm_prefetch_buffer((char*)buffer, 4096 * sizeof(INT16));
|
||||
rfx_quantization_decode_block_sse2(&buffer[0], 1024, quantVals[8] - 1); /* HL1 */
|
||||
rfx_quantization_decode_block_sse2(&buffer[1024], 1024, quantVals[7] - 1); /* LH1 */
|
||||
rfx_quantization_decode_block_sse2(&buffer[2048], 1024, quantVals[9] - 1); /* HH1 */
|
||||
rfx_quantization_decode_block_sse2(&buffer[3072], 256, quantVals[5] - 1); /* HL2 */
|
||||
rfx_quantization_decode_block_sse2(&buffer[3328], 256, quantVals[4] - 1); /* LH2 */
|
||||
rfx_quantization_decode_block_sse2(&buffer[3584], 256, quantVals[6] - 1); /* HH2 */
|
||||
rfx_quantization_decode_block_sse2(&buffer[3840], 64, quantVals[2] - 1); /* HL3 */
|
||||
rfx_quantization_decode_block_sse2(&buffer[3904], 64, quantVals[1] - 1); /* LH3 */
|
||||
rfx_quantization_decode_block_sse2(&buffer[3968], 64, quantVals[3] - 1); /* HH3 */
|
||||
rfx_quantization_decode_block_sse2(&buffer[4032], 64, quantVals[0] - 1); /* LL3 */
|
||||
}
|
||||
|
||||
static inline void __attribute__((ATTRIBUTES))
|
||||
rfx_quantization_encode_block_sse2(INT16* WINPR_RESTRICT buffer, const unsigned buffer_size,
|
||||
const INT16 factor)
|
||||
{
|
||||
__m128i* ptr = (__m128i*)buffer;
|
||||
const __m128i* buf_end = (const __m128i*)(buffer + buffer_size);
|
||||
|
||||
if (factor == 0)
|
||||
return;
|
||||
|
||||
const __m128i half = _mm_set1_epi16(WINPR_ASSERTING_INT_CAST(INT16, 1 << (factor - 1)));
|
||||
|
||||
do
|
||||
{
|
||||
const __m128i la = LOAD_SI128(ptr);
|
||||
__m128i a = _mm_add_epi16(la, half);
|
||||
a = _mm_srai_epi16(a, factor);
|
||||
STORE_SI128(ptr, a);
|
||||
ptr++;
|
||||
} while (ptr < buf_end);
|
||||
}
|
||||
|
||||
static void rfx_quantization_encode_sse2(INT16* WINPR_RESTRICT buffer,
|
||||
const UINT32* WINPR_RESTRICT quantization_values)
|
||||
{
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(quantization_values);
|
||||
for (size_t x = 0; x < 10; x++)
|
||||
{
|
||||
WINPR_ASSERT(quantization_values[x] >= 6);
|
||||
WINPR_ASSERT(quantization_values[x] <= INT16_MAX + 6);
|
||||
}
|
||||
|
||||
mm_prefetch_buffer((char*)buffer, 4096 * sizeof(INT16));
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer, 1024, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[8] - 6)); /* HL1 */
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer + 1024, 1024, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[7] - 6)); /* LH1 */
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer + 2048, 1024, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[9] - 6)); /* HH1 */
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer + 3072, 256, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[5] - 6)); /* HL2 */
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer + 3328, 256, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[4] - 6)); /* LH2 */
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer + 3584, 256, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[6] - 6)); /* HH2 */
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer + 3840, 64, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[2] - 6)); /* HL3 */
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer + 3904, 64, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[1] - 6)); /* LH3 */
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer + 3968, 64, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[3] - 6)); /* HH3 */
|
||||
rfx_quantization_encode_block_sse2(
|
||||
buffer + 4032, 64, WINPR_ASSERTING_INT_CAST(INT16, quantization_values[0] - 6)); /* LL3 */
|
||||
rfx_quantization_encode_block_sse2(buffer, 4096, 5);
|
||||
}
|
||||
|
||||
static inline void __attribute__((ATTRIBUTES))
|
||||
rfx_dwt_2d_decode_block_horiz_sse2(INT16* WINPR_RESTRICT l, INT16* WINPR_RESTRICT h,
|
||||
INT16* WINPR_RESTRICT dst, size_t subband_width)
|
||||
{
|
||||
INT16* l_ptr = l;
|
||||
INT16* h_ptr = h;
|
||||
INT16* dst_ptr = dst;
|
||||
int first = 0;
|
||||
int last = 0;
|
||||
__m128i dst1;
|
||||
__m128i dst2;
|
||||
|
||||
for (size_t y = 0; y < subband_width; y++)
|
||||
{
|
||||
/* Even coefficients */
|
||||
for (size_t n = 0; n < subband_width; n += 8)
|
||||
{
|
||||
/* dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1); */
|
||||
__m128i l_n = LOAD_SI128(l_ptr);
|
||||
__m128i h_n = LOAD_SI128(h_ptr);
|
||||
__m128i h_n_m = LOAD_SI128(h_ptr - 1);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
first = _mm_extract_epi16(h_n_m, 1);
|
||||
h_n_m = _mm_insert_epi16(h_n_m, first, 0);
|
||||
}
|
||||
|
||||
__m128i tmp_n = _mm_add_epi16(h_n, h_n_m);
|
||||
tmp_n = _mm_add_epi16(tmp_n, _mm_set1_epi16(1));
|
||||
tmp_n = _mm_srai_epi16(tmp_n, 1);
|
||||
const __m128i dst_n = _mm_sub_epi16(l_n, tmp_n);
|
||||
STORE_SI128(l_ptr, dst_n);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
}
|
||||
|
||||
l_ptr -= subband_width;
|
||||
h_ptr -= subband_width;
|
||||
|
||||
/* Odd coefficients */
|
||||
for (size_t n = 0; n < subband_width; n += 8)
|
||||
{
|
||||
/* dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1); */
|
||||
__m128i h_n = LOAD_SI128(h_ptr);
|
||||
h_n = _mm_slli_epi16(h_n, 1);
|
||||
__m128i dst_n = LOAD_SI128(l_ptr);
|
||||
__m128i dst_n_p = LOAD_SI128(l_ptr + 1);
|
||||
|
||||
if (n == subband_width - 8)
|
||||
{
|
||||
last = _mm_extract_epi16(dst_n_p, 6);
|
||||
dst_n_p = _mm_insert_epi16(dst_n_p, last, 7);
|
||||
}
|
||||
|
||||
__m128i tmp_n = _mm_add_epi16(dst_n_p, dst_n);
|
||||
tmp_n = _mm_srai_epi16(tmp_n, 1);
|
||||
tmp_n = _mm_add_epi16(tmp_n, h_n);
|
||||
dst1 = _mm_unpacklo_epi16(dst_n, tmp_n);
|
||||
dst2 = _mm_unpackhi_epi16(dst_n, tmp_n);
|
||||
STORE_SI128(dst_ptr, dst1);
|
||||
STORE_SI128(dst_ptr + 8, dst2);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
dst_ptr += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __attribute__((ATTRIBUTES))
|
||||
rfx_dwt_2d_decode_block_vert_sse2(INT16* WINPR_RESTRICT l, INT16* WINPR_RESTRICT h,
|
||||
INT16* WINPR_RESTRICT dst, size_t subband_width)
|
||||
{
|
||||
INT16* l_ptr = l;
|
||||
INT16* h_ptr = h;
|
||||
INT16* dst_ptr = dst;
|
||||
const size_t total_width = subband_width + subband_width;
|
||||
|
||||
/* Even coefficients */
|
||||
for (size_t n = 0; n < subband_width; n++)
|
||||
{
|
||||
for (size_t x = 0; x < total_width; x += 8)
|
||||
{
|
||||
/* dst[2n] = l[n] - ((h[n-1] + h[n] + 1) >> 1); */
|
||||
const __m128i l_n = LOAD_SI128(l_ptr);
|
||||
const __m128i h_n = LOAD_SI128(h_ptr);
|
||||
__m128i tmp_n = _mm_add_epi16(h_n, _mm_set1_epi16(1));
|
||||
|
||||
if (n == 0)
|
||||
tmp_n = _mm_add_epi16(tmp_n, h_n);
|
||||
else
|
||||
{
|
||||
const __m128i h_n_m = LOAD_SI128(h_ptr - total_width);
|
||||
tmp_n = _mm_add_epi16(tmp_n, h_n_m);
|
||||
}
|
||||
|
||||
tmp_n = _mm_srai_epi16(tmp_n, 1);
|
||||
const __m128i dst_n = _mm_sub_epi16(l_n, tmp_n);
|
||||
STORE_SI128(dst_ptr, dst_n);
|
||||
l_ptr += 8;
|
||||
h_ptr += 8;
|
||||
dst_ptr += 8;
|
||||
}
|
||||
|
||||
dst_ptr += total_width;
|
||||
}
|
||||
|
||||
h_ptr = h;
|
||||
dst_ptr = dst + total_width;
|
||||
|
||||
/* Odd coefficients */
|
||||
for (size_t n = 0; n < subband_width; n++)
|
||||
{
|
||||
for (size_t x = 0; x < total_width; x += 8)
|
||||
{
|
||||
/* dst[2n + 1] = (h[n] << 1) + ((dst[2n] + dst[2n + 2]) >> 1); */
|
||||
__m128i h_n = LOAD_SI128(h_ptr);
|
||||
__m128i dst_n_m = LOAD_SI128(dst_ptr - total_width);
|
||||
h_n = _mm_slli_epi16(h_n, 1);
|
||||
__m128i tmp_n = dst_n_m;
|
||||
|
||||
if (n == subband_width - 1)
|
||||
tmp_n = _mm_add_epi16(tmp_n, dst_n_m);
|
||||
else
|
||||
{
|
||||
const __m128i dst_n_p = LOAD_SI128(dst_ptr + total_width);
|
||||
tmp_n = _mm_add_epi16(tmp_n, dst_n_p);
|
||||
}
|
||||
|
||||
tmp_n = _mm_srai_epi16(tmp_n, 1);
|
||||
const __m128i dst_n = _mm_add_epi16(tmp_n, h_n);
|
||||
STORE_SI128(dst_ptr, dst_n);
|
||||
h_ptr += 8;
|
||||
dst_ptr += 8;
|
||||
}
|
||||
|
||||
dst_ptr += total_width;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __attribute__((ATTRIBUTES))
|
||||
rfx_dwt_2d_decode_block_sse2(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT idwt,
|
||||
size_t subband_width)
|
||||
{
|
||||
mm_prefetch_buffer((char*)idwt, 4ULL * subband_width * sizeof(INT16));
|
||||
/* 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). */
|
||||
INT16* ll = buffer + 3ULL * subband_width * subband_width;
|
||||
INT16* hl = buffer;
|
||||
INT16* l_dst = idwt;
|
||||
rfx_dwt_2d_decode_block_horiz_sse2(ll, hl, l_dst, subband_width);
|
||||
INT16* lh = buffer + 1ULL * subband_width * subband_width;
|
||||
INT16* hh = buffer + 2ULL * subband_width * subband_width;
|
||||
INT16* h_dst = idwt + 2ULL * subband_width * subband_width;
|
||||
rfx_dwt_2d_decode_block_horiz_sse2(lh, hh, h_dst, subband_width);
|
||||
/* Inverse DWT in vertical direction, results are stored in original buffer. */
|
||||
rfx_dwt_2d_decode_block_vert_sse2(l_dst, h_dst, buffer, subband_width);
|
||||
}
|
||||
|
||||
static void rfx_dwt_2d_decode_sse2(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt_buffer)
|
||||
{
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(dwt_buffer);
|
||||
|
||||
mm_prefetch_buffer((char*)buffer, 4096 * sizeof(INT16));
|
||||
rfx_dwt_2d_decode_block_sse2(&buffer[3840], dwt_buffer, 8);
|
||||
rfx_dwt_2d_decode_block_sse2(&buffer[3072], dwt_buffer, 16);
|
||||
rfx_dwt_2d_decode_block_sse2(&buffer[0], dwt_buffer, 32);
|
||||
}
|
||||
|
||||
static inline void __attribute__((ATTRIBUTES))
|
||||
rfx_dwt_2d_encode_block_vert_sse2(INT16* WINPR_RESTRICT src, INT16* WINPR_RESTRICT l,
|
||||
INT16* WINPR_RESTRICT h, size_t subband_width)
|
||||
{
|
||||
const size_t total_width = subband_width << 1;
|
||||
|
||||
for (size_t n = 0; n < subband_width; n++)
|
||||
{
|
||||
for (size_t x = 0; x < total_width; x += 8)
|
||||
{
|
||||
__m128i src_2n = LOAD_SI128(src);
|
||||
__m128i src_2n_1 = LOAD_SI128(src + total_width);
|
||||
__m128i src_2n_2 = src_2n;
|
||||
|
||||
if (n < subband_width - 1)
|
||||
src_2n_2 = LOAD_SI128(src + 2ULL * total_width);
|
||||
|
||||
/* h[n] = (src[2n + 1] - ((src[2n] + src[2n + 2]) >> 1)) >> 1 */
|
||||
__m128i h_n = _mm_add_epi16(src_2n, src_2n_2);
|
||||
h_n = _mm_srai_epi16(h_n, 1);
|
||||
h_n = _mm_sub_epi16(src_2n_1, h_n);
|
||||
h_n = _mm_srai_epi16(h_n, 1);
|
||||
STORE_SI128(h, h_n);
|
||||
|
||||
__m128i h_n_m = h_n;
|
||||
if (n != 0)
|
||||
h_n_m = LOAD_SI128(h - total_width);
|
||||
|
||||
/* l[n] = src[2n] + ((h[n - 1] + h[n]) >> 1) */
|
||||
__m128i l_n = _mm_add_epi16(h_n_m, h_n);
|
||||
l_n = _mm_srai_epi16(l_n, 1);
|
||||
l_n = _mm_add_epi16(l_n, src_2n);
|
||||
STORE_SI128(l, l_n);
|
||||
src += 8;
|
||||
l += 8;
|
||||
h += 8;
|
||||
}
|
||||
|
||||
src += total_width;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __attribute__((ATTRIBUTES))
|
||||
rfx_dwt_2d_encode_block_horiz_sse2(INT16* WINPR_RESTRICT src, INT16* WINPR_RESTRICT l,
|
||||
INT16* WINPR_RESTRICT h, size_t subband_width)
|
||||
{
|
||||
for (size_t y = 0; y < subband_width; y++)
|
||||
{
|
||||
for (size_t n = 0; n < subband_width; n += 8)
|
||||
{
|
||||
/* The following 3 Set operations consumes more than half of the total DWT processing
|
||||
* time! */
|
||||
const INT16 src16 = (INT16)(((n + 8) == subband_width) ? src[14] : src[16]);
|
||||
__m128i src_2n =
|
||||
_mm_set_epi16(src[14], src[12], src[10], src[8], src[6], src[4], src[2], src[0]);
|
||||
__m128i src_2n_1 =
|
||||
_mm_set_epi16(src[15], src[13], src[11], src[9], src[7], src[5], src[3], src[1]);
|
||||
__m128i src_2n_2 =
|
||||
_mm_set_epi16(src16, src[14], src[12], src[10], src[8], src[6], src[4], src[2]);
|
||||
/* h[n] = (src[2n + 1] - ((src[2n] + src[2n + 2]) >> 1)) >> 1 */
|
||||
__m128i h_n = _mm_add_epi16(src_2n, src_2n_2);
|
||||
h_n = _mm_srai_epi16(h_n, 1);
|
||||
h_n = _mm_sub_epi16(src_2n_1, h_n);
|
||||
h_n = _mm_srai_epi16(h_n, 1);
|
||||
STORE_SI128(h, h_n);
|
||||
__m128i h_n_m = LOAD_SI128(h - 1);
|
||||
|
||||
if (n == 0)
|
||||
{
|
||||
int first = _mm_extract_epi16(h_n_m, 1);
|
||||
h_n_m = _mm_insert_epi16(h_n_m, first, 0);
|
||||
}
|
||||
|
||||
/* l[n] = src[2n] + ((h[n - 1] + h[n]) >> 1) */
|
||||
__m128i l_n = _mm_add_epi16(h_n_m, h_n);
|
||||
l_n = _mm_srai_epi16(l_n, 1);
|
||||
l_n = _mm_add_epi16(l_n, src_2n);
|
||||
STORE_SI128(l, l_n);
|
||||
src += 16;
|
||||
l += 8;
|
||||
h += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __attribute__((ATTRIBUTES))
|
||||
rfx_dwt_2d_encode_block_sse2(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt,
|
||||
size_t subband_width)
|
||||
{
|
||||
mm_prefetch_buffer((char*)dwt, 4ULL * subband_width * sizeof(INT16));
|
||||
/* DWT in vertical direction, results in 2 sub-bands in L, H order in tmp buffer dwt. */
|
||||
INT16* l_src = dwt;
|
||||
INT16* h_src = dwt + 2ULL * subband_width * subband_width;
|
||||
rfx_dwt_2d_encode_block_vert_sse2(buffer, l_src, h_src, subband_width);
|
||||
/* 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). */
|
||||
INT16* ll = buffer + 3ULL * subband_width * subband_width;
|
||||
INT16* hl = buffer;
|
||||
INT16* lh = buffer + 1ULL * subband_width * subband_width;
|
||||
INT16* hh = buffer + 2ULL * subband_width * subband_width;
|
||||
rfx_dwt_2d_encode_block_horiz_sse2(l_src, ll, hl, subband_width);
|
||||
rfx_dwt_2d_encode_block_horiz_sse2(h_src, lh, hh, subband_width);
|
||||
}
|
||||
|
||||
static void rfx_dwt_2d_encode_sse2(INT16* WINPR_RESTRICT buffer, INT16* WINPR_RESTRICT dwt_buffer)
|
||||
{
|
||||
WINPR_ASSERT(buffer);
|
||||
WINPR_ASSERT(dwt_buffer);
|
||||
|
||||
mm_prefetch_buffer((char*)buffer, 4096 * sizeof(INT16));
|
||||
rfx_dwt_2d_encode_block_sse2(buffer, dwt_buffer, 32);
|
||||
rfx_dwt_2d_encode_block_sse2(buffer + 3072, dwt_buffer, 16);
|
||||
rfx_dwt_2d_encode_block_sse2(buffer + 3840, dwt_buffer, 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
void rfx_init_sse2_int(RFX_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
#if defined(SSE_AVX_INTRINSICS_ENABLED)
|
||||
WLog_VRB(PRIM_TAG, "SSE2/SSE3 optimizations");
|
||||
PROFILER_RENAME(context->priv->prof_rfx_quantization_decode, "rfx_quantization_decode_sse2")
|
||||
PROFILER_RENAME(context->priv->prof_rfx_quantization_encode, "rfx_quantization_encode_sse2")
|
||||
PROFILER_RENAME(context->priv->prof_rfx_dwt_2d_decode, "rfx_dwt_2d_decode_sse2")
|
||||
PROFILER_RENAME(context->priv->prof_rfx_dwt_2d_encode, "rfx_dwt_2d_encode_sse2")
|
||||
context->quantization_decode = rfx_quantization_decode_sse2;
|
||||
context->quantization_encode = rfx_quantization_encode_sse2;
|
||||
context->dwt_2d_decode = rfx_dwt_2d_decode_sse2;
|
||||
context->dwt_2d_encode = rfx_dwt_2d_encode_sse2;
|
||||
#else
|
||||
WINPR_UNUSED(context);
|
||||
WLog_VRB(PRIM_TAG, "undefined WITH_SIMD or SSE2 intrinsics not available");
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RemoteFX Codec Library - SSE2 Optimizations
|
||||
*
|
||||
* Copyright 2011 Stephen Erisman
|
||||
*
|
||||
* 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 FREERDP_LIB_CODEC_RFX_SSE2_H
|
||||
#define FREERDP_LIB_CODEC_RFX_SSE2_H
|
||||
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/api.h>
|
||||
|
||||
FREERDP_LOCAL void rfx_init_sse2_int(RFX_CONTEXT* WINPR_RESTRICT context);
|
||||
|
||||
static inline void rfx_init_sse2(RFX_CONTEXT* WINPR_RESTRICT context)
|
||||
{
|
||||
if (!IsProcessorFeaturePresent(PF_SSE2_INSTRUCTIONS_AVAILABLE) ||
|
||||
!IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE))
|
||||
return;
|
||||
|
||||
rfx_init_sse2_int(context);
|
||||
}
|
||||
|
||||
#endif /* FREERDP_LIB_CODEC_RFX_SSE2_H */
|
||||
@@ -0,0 +1,88 @@
|
||||
set(MODULE_NAME "TestFreeRDPCodec")
|
||||
set(MODULE_PREFIX "TEST_FREERDP_CODEC")
|
||||
|
||||
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(TEST_COMMON TestFreeRDPHelpers.c TestFreeRDPHelpers.h)
|
||||
|
||||
set(TESTS
|
||||
TestFreeRDPRegion.c
|
||||
TestFreeRDPCodecColor.c
|
||||
TestFreeRDPCodecZGfx.c
|
||||
TestFreeRDPCodecPlanar.c
|
||||
TestFreeRDPCodecCopy.c
|
||||
TestFreeRDPCodecCursor.c
|
||||
TestFreeRDPCodecClear.c
|
||||
TestFreeRDPCodecInterleaved.c
|
||||
TestFreeRDPCodecProgressive.c
|
||||
TestFreeRDPCodecRemoteFX.c
|
||||
)
|
||||
|
||||
if(NOT BUILD_TESTING_NO_H264)
|
||||
list(APPEND TESTS TestFreeRDPCodecH264.c)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING_INTERNAL)
|
||||
list(APPEND TESTS TestFreeRDPCodecMppc.c TestFreeRDPCodecNCrush.c TestFreeRDPCodecXCrush.c)
|
||||
endif()
|
||||
|
||||
file(GLOB CURSOR_TESTCASES_C LIST_DIRECTORIES false RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cursor/*.c")
|
||||
file(GLOB CURSOR_TESTCASES_H LIST_DIRECTORIES false RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "cursor/*.h")
|
||||
|
||||
# Create a combined header for all testcases
|
||||
set(TESTCASE_HEADER "${CMAKE_CURRENT_BINARY_DIR}/testcases.h")
|
||||
write_file(${TESTCASE_HEADER} "#pragma once\n")
|
||||
foreach(header ${CURSOR_TESTCASES_H})
|
||||
write_file(${TESTCASE_HEADER} "#include <${header}>" APPEND)
|
||||
endforeach()
|
||||
|
||||
write_file(${TESTCASE_HEADER} "\nstatic const gdiPalette* testcase_palette[] = {" APPEND)
|
||||
foreach(header ${CURSOR_TESTCASES_H})
|
||||
get_filename_component(NAME ${header} NAME_WE)
|
||||
write_file(${TESTCASE_HEADER} "&${NAME}_palette," APPEND)
|
||||
endforeach()
|
||||
write_file(${TESTCASE_HEADER} "};\n" APPEND)
|
||||
|
||||
write_file(${TESTCASE_HEADER} "static const rdpPointer* testcase_pointer[] = {" APPEND)
|
||||
foreach(header ${CURSOR_TESTCASES_H})
|
||||
get_filename_component(NAME ${header} NAME_WE)
|
||||
write_file(${TESTCASE_HEADER} "&${NAME}_pointer," APPEND)
|
||||
endforeach()
|
||||
write_file(${TESTCASE_HEADER} "};\n" APPEND)
|
||||
|
||||
write_file(${TESTCASE_HEADER} "static const uint8_t* testcase_image_bgra32[] = {" APPEND)
|
||||
foreach(header ${CURSOR_TESTCASES_H})
|
||||
get_filename_component(NAME ${header} NAME_WE)
|
||||
write_file(${TESTCASE_HEADER} "${NAME}_image_bgra32," APPEND)
|
||||
endforeach()
|
||||
write_file(${TESTCASE_HEADER} "};" APPEND)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
create_test_sourcelist(SRCS ${DRIVER} ${TESTS})
|
||||
|
||||
add_compile_definitions(CMAKE_CURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
add_compile_definitions(CMAKE_CURRENT_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}")
|
||||
add_executable(${MODULE_NAME} ${SRCS} ${CURSOR_TESTCASES_H} ${CURSOR_TESTCASES_C} ${TESTCASE_HEADER} ${TEST_COMMON})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} freerdp winpr)
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
|
||||
|
||||
foreach(test ${TESTS})
|
||||
get_filename_component(TestName ${test} NAME_WE)
|
||||
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
|
||||
endforeach()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Test")
|
||||
|
||||
add_executable(img2bgra img2bgra.c)
|
||||
target_link_libraries(img2bgra winpr)
|
||||
|
||||
set(FUZZERS TestFuzzCodecs.c)
|
||||
|
||||
include(AddFuzzerTest)
|
||||
add_fuzzer_test("${FUZZERS}" "freerdp winpr")
|
||||
@@ -0,0 +1,91 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/platform.h>
|
||||
|
||||
#include <freerdp/codec/clear.h>
|
||||
|
||||
WINPR_PRAGMA_DIAG_PUSH
|
||||
WINPR_PRAGMA_DIAG_IGNORED_UNUSED_CONST_VAR
|
||||
/* [MS-RDPEGFX] 4.1.1.1 Example 1 */
|
||||
static const BYTE PREPARE_CLEAR_EXAMPLE_1[] = "\x03\xc3\x11\x00";
|
||||
static const BYTE TEST_CLEAR_EXAMPLE_1[] = "\x03\xc3\x11\x00";
|
||||
WINPR_PRAGMA_DIAG_POP
|
||||
|
||||
/* [MS-RDPEGFX] 4.1.1.1 Example 2 */
|
||||
static const BYTE TEST_CLEAR_EXAMPLE_2[] =
|
||||
"\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x82\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x4e\x00\x11\x00\x75\x00\x00\x00\x02\x0e\xff\xff\xff\x00"
|
||||
"\x00\x00\xdb\xff\xff\x00\x3a\x90\xff\xb6\x66\x66\xb6\xff\xb6\x66"
|
||||
"\x00\x90\xdb\xff\x00\x00\x3a\xdb\x90\x3a\x3a\x90\xdb\x66\x00\x00"
|
||||
"\xff\xff\xb6\x64\x64\x64\x11\x04\x11\x4c\x11\x4c\x11\x4c\x11\x4c"
|
||||
"\x11\x4c\x00\x47\x13\x00\x01\x01\x04\x00\x01\x00\x00\x47\x16\x00"
|
||||
"\x11\x02\x00\x47\x29\x00\x11\x01\x00\x49\x0a\x00\x01\x00\x04\x00"
|
||||
"\x01\x00\x00\x4a\x0a\x00\x09\x00\x01\x00\x00\x47\x05\x00\x01\x01"
|
||||
"\x1c\x00\x01\x00\x11\x4c\x11\x4c\x11\x4c\x00\x47\x0d\x4d\x00\x4d";
|
||||
|
||||
/* [MS-RDPEGFX] 4.1.1.1 Example 3 */
|
||||
static const BYTE TEST_CLEAR_EXAMPLE_3[] =
|
||||
"\x00\xdf\x0e\x00\x00\x00\x8b\x00\x00\x00\x00\x00\x00\x00\xfe\xfe"
|
||||
"\xfe\xff\x80\x05\xff\xff\xff\x40\xfe\xfe\xfe\x40\x00\x00\x3f\x00"
|
||||
"\x03\x00\x0b\x00\xfe\xfe\xfe\xc5\xd0\xc6\xd0\xc7\xd0\x68\xd4\x69"
|
||||
"\xd4\x6a\xd4\x6b\xd4\x6c\xd4\x6d\xd4\x1a\xd4\x1a\xd4\xa6\xd0\x6e"
|
||||
"\xd4\x6f\xd4\x70\xd4\x71\xd4\x72\xd4\x73\xd4\x74\xd4\x21\xd4\x22"
|
||||
"\xd4\x23\xd4\x24\xd4\x25\xd4\xd9\xd0\xda\xd0\xdb\xd0\xc5\xd0\xc5"
|
||||
"\xd0\xdc\xd0\xc2\xd0\x21\xd4\x22\xd4\x23\xd4\x24\xd4\x25\xd4\xc9"
|
||||
"\xd0\xca\xd0\x5a\xd4\x2b\xd1\x28\xd1\x2c\xd1\x75\xd4\x27\xd4\x28"
|
||||
"\xd4\x29\xd4\x2a\xd4\x1a\xd4\x1a\xd4\x1a\xd4\xb7\xd0\xb8\xd0\xb9"
|
||||
"\xd0\xba\xd0\xbb\xd0\xbc\xd0\xbd\xd0\xbe\xd0\xbf\xd0\xc0\xd0\xc1"
|
||||
"\xd0\xc2\xd0\xc3\xd0\xc4\xd0";
|
||||
|
||||
/* [MS-RDPEGFX] 4.1.1.1 Example 4 */
|
||||
static const BYTE TEST_CLEAR_EXAMPLE_4[] =
|
||||
"\x01\x0b\x78\x00\x00\x00\x00\x00\x46\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x00\x00\x06\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x0f\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\xff\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xb6\x66\xff\xff\xff\xff\xff\xff\xff\xb6\x66\xdb\x90\x3a\xff\xff"
|
||||
"\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff\x46\x91\x47\x91\x48\x91"
|
||||
"\x49\x91\x4a\x91\x1b\x91";
|
||||
|
||||
static BOOL test_ClearDecompressExample(UINT32 nr, UINT32 width, UINT32 height,
|
||||
const BYTE* pSrcData, const UINT32 SrcSize)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
int status = 0;
|
||||
BYTE* pDstData = calloc(4ULL * width, height);
|
||||
CLEAR_CONTEXT* clear = clear_context_new(FALSE);
|
||||
|
||||
if (!clear || !pDstData)
|
||||
goto fail;
|
||||
|
||||
status = clear_decompress(clear, pSrcData, SrcSize, width, height, pDstData,
|
||||
PIXEL_FORMAT_XRGB32, 0, 0, 0, width, height, nullptr);
|
||||
(void)printf("clear_decompress example %" PRIu32 " status: %d\n", nr, status);
|
||||
(void)fflush(stdout);
|
||||
rc = (status == 0);
|
||||
fail:
|
||||
clear_context_free(clear);
|
||||
free(pDstData);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecClear(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
/* Example 1 needs a filled glyph cache
|
||||
if (!test_ClearDecompressExample(1, 8, 9, TEST_CLEAR_EXAMPLE_1,
|
||||
sizeof(TEST_CLEAR_EXAMPLE_1)))
|
||||
return -1;
|
||||
*/
|
||||
if (!test_ClearDecompressExample(2, 78, 17, TEST_CLEAR_EXAMPLE_2, sizeof(TEST_CLEAR_EXAMPLE_2)))
|
||||
return -1;
|
||||
|
||||
if (!test_ClearDecompressExample(3, 64, 24, TEST_CLEAR_EXAMPLE_3, sizeof(TEST_CLEAR_EXAMPLE_3)))
|
||||
return -1;
|
||||
|
||||
if (!test_ClearDecompressExample(4, 7, 15, TEST_CLEAR_EXAMPLE_4, sizeof(TEST_CLEAR_EXAMPLE_4)))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2025 Thincast Technologies GmbH
|
||||
* Copyright 2025 Armin Novak <anovak@thincast.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 <winpr/wtypes.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t val;
|
||||
const char* str;
|
||||
} test_t;
|
||||
|
||||
#define XSTR(s) STR(s)
|
||||
#define STR(x) #x
|
||||
#define ENTRY(x) { x, #x }
|
||||
static const test_t testcases[] = { ENTRY(PIXEL_FORMAT_ARGB32),
|
||||
ENTRY(PIXEL_FORMAT_XRGB32),
|
||||
ENTRY(PIXEL_FORMAT_ABGR32),
|
||||
ENTRY(PIXEL_FORMAT_XBGR32),
|
||||
ENTRY(PIXEL_FORMAT_BGRA32),
|
||||
ENTRY(PIXEL_FORMAT_BGRX32),
|
||||
ENTRY(PIXEL_FORMAT_RGBA32),
|
||||
ENTRY(PIXEL_FORMAT_RGBX32),
|
||||
ENTRY(PIXEL_FORMAT_BGRX32_DEPTH30),
|
||||
ENTRY(PIXEL_FORMAT_RGBX32_DEPTH30),
|
||||
ENTRY(PIXEL_FORMAT_RGB24),
|
||||
ENTRY(PIXEL_FORMAT_BGR24),
|
||||
ENTRY(PIXEL_FORMAT_RGB16),
|
||||
ENTRY(PIXEL_FORMAT_BGR16),
|
||||
ENTRY(PIXEL_FORMAT_ARGB15),
|
||||
ENTRY(PIXEL_FORMAT_RGB15),
|
||||
ENTRY(PIXEL_FORMAT_ABGR15),
|
||||
ENTRY(PIXEL_FORMAT_BGR15),
|
||||
ENTRY(PIXEL_FORMAT_RGB8),
|
||||
ENTRY(PIXEL_FORMAT_A4),
|
||||
ENTRY(PIXEL_FORMAT_MONO) };
|
||||
#undef ENTRY
|
||||
#undef STR
|
||||
|
||||
int TestFreeRDPCodecColor(WINPR_ATTR_UNUSED int argc, WINPR_ATTR_UNUSED char* argv[])
|
||||
{
|
||||
const size_t count = ARRAYSIZE(testcases);
|
||||
for (size_t x = 0; x < count; x++)
|
||||
{
|
||||
const test_t* cur = &testcases[x];
|
||||
|
||||
const char* cmp = cur->str;
|
||||
const uint32_t val = FreeRDPGetColorFromatFromName(cmp);
|
||||
if (val != cur->val)
|
||||
return -1;
|
||||
|
||||
const char* str = FreeRDPGetColorFormatName(cur->val);
|
||||
if (!str || (strcmp(str, cmp) != 0))
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#define TEST_RUNS 2
|
||||
|
||||
static BOOL TestFreeRDPImageCopy(UINT32 w, UINT32 h, UINT32 srcFormat, UINT32 dstFormat,
|
||||
size_t runs)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const size_t sbpp = FreeRDPGetBytesPerPixel(srcFormat);
|
||||
const size_t dbpp = FreeRDPGetBytesPerPixel(dstFormat);
|
||||
const size_t srcStep = w * sbpp;
|
||||
const size_t dstStep = w * dbpp;
|
||||
char* src = calloc(h, srcStep);
|
||||
char* dst = calloc(h, dstStep);
|
||||
if (!src || !dst)
|
||||
goto fail;
|
||||
|
||||
for (size_t x = 0; x < runs; x++)
|
||||
{
|
||||
if (winpr_RAND_pseudo(src, h * srcStep) < 0)
|
||||
goto fail;
|
||||
const UINT64 start = winpr_GetUnixTimeNS();
|
||||
rc = freerdp_image_copy(dst, dstFormat, dstStep, 0, 0, w, h, src, srcFormat, srcStep, 0, 0,
|
||||
nullptr, 0);
|
||||
const UINT64 end = winpr_GetUnixTimeNS();
|
||||
|
||||
double ms = (double)(end - start);
|
||||
ms /= 1000000.0;
|
||||
|
||||
(void)fprintf(stdout,
|
||||
"[%s] copied %" PRIu32 "x%" PRIu32 " [%-20s] -> [%-20s] in %lf ms [%s]\n",
|
||||
__func__, w, h, FreeRDPGetColorFormatName(srcFormat),
|
||||
FreeRDPGetColorFormatName(dstFormat), ms, rc ? "success" : "failure");
|
||||
if (!rc)
|
||||
break;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(src);
|
||||
free(dst);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL TestFreeRDPImageCopy_no_overlap(UINT32 w, UINT32 h, UINT32 srcFormat, UINT32 dstFormat,
|
||||
size_t runs)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const size_t sbpp = FreeRDPGetBytesPerPixel(srcFormat);
|
||||
const size_t dbpp = FreeRDPGetBytesPerPixel(dstFormat);
|
||||
const size_t srcStep = w * sbpp;
|
||||
const size_t dstStep = w * dbpp;
|
||||
char* src = calloc(h, srcStep);
|
||||
char* dst = calloc(h, dstStep);
|
||||
if (!src || !dst)
|
||||
goto fail;
|
||||
|
||||
for (size_t x = 0; x < runs; x++)
|
||||
{
|
||||
if (winpr_RAND_pseudo(src, h * srcStep) < 0)
|
||||
goto fail;
|
||||
const UINT64 start = winpr_GetUnixTimeNS();
|
||||
rc = freerdp_image_copy_no_overlap(dst, dstFormat, dstStep, 0, 0, w, h, src, srcFormat,
|
||||
srcStep, 0, 0, nullptr, 0);
|
||||
const UINT64 end = winpr_GetUnixTimeNS();
|
||||
|
||||
double ms = (double)(end - start);
|
||||
ms /= 1000000.0;
|
||||
|
||||
(void)fprintf(stdout,
|
||||
"[%s] copied %" PRIu32 "x%" PRIu32 " [%-20s] -> [%-20s] in %lf ms [%s]\n",
|
||||
__func__, w, h, FreeRDPGetColorFormatName(srcFormat),
|
||||
FreeRDPGetColorFormatName(dstFormat), ms, rc ? "success" : "failure");
|
||||
if (!rc)
|
||||
break;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(src);
|
||||
free(dst);
|
||||
return rc;
|
||||
}
|
||||
int TestFreeRDPCodecCopy(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
UINT32 width = 192;
|
||||
UINT32 height = 108;
|
||||
const UINT32 formats[] = {
|
||||
PIXEL_FORMAT_ABGR15, PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_BGR16,
|
||||
PIXEL_FORMAT_BGR24, PIXEL_FORMAT_RGB15, PIXEL_FORMAT_RGB16, PIXEL_FORMAT_RGB24,
|
||||
PIXEL_FORMAT_ABGR32, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_XRGB32,
|
||||
PIXEL_FORMAT_BGRA32, PIXEL_FORMAT_RGBA32, PIXEL_FORMAT_BGRX32, PIXEL_FORMAT_RGBX32,
|
||||
};
|
||||
|
||||
if (argc == 3)
|
||||
{
|
||||
errno = 0;
|
||||
width = strtoul(argv[1], nullptr, 0);
|
||||
height = strtoul(argv[2], nullptr, 0);
|
||||
if ((errno != 0) || (width == 0) || (height == 0))
|
||||
{
|
||||
char buffer[128] = WINPR_C_ARRAY_INIT;
|
||||
(void)fprintf(stderr, "%s failed: width=%" PRIu32 ", height=%" PRIu32 ", errno=%s\n",
|
||||
__func__, width, height, winpr_strerror(errno, buffer, sizeof(buffer)));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
for (size_t x = 0; x < ARRAYSIZE(formats); x++)
|
||||
{
|
||||
const UINT32 SrcFormat = formats[x];
|
||||
for (size_t y = 0; y < ARRAYSIZE(formats); y++)
|
||||
{
|
||||
const UINT32 DstFormat = formats[y];
|
||||
if (!TestFreeRDPImageCopy(width, height, SrcFormat, DstFormat, TEST_RUNS))
|
||||
return -1;
|
||||
if (!TestFreeRDPImageCopy_no_overlap(width, height, SrcFormat, DstFormat, TEST_RUNS))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/image.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include "testcases.h"
|
||||
|
||||
static BOOL run_testcase(size_t x, const gdiPalette* palette, const rdpPointer* pointer,
|
||||
const uint8_t* ref)
|
||||
{
|
||||
WINPR_ASSERT(palette);
|
||||
WINPR_ASSERT(pointer);
|
||||
WINPR_ASSERT(ref);
|
||||
|
||||
WLog_INFO("test", "running cursor test case %" PRIuz, x);
|
||||
BOOL rc = FALSE;
|
||||
const uint32_t format = PIXEL_FORMAT_BGRA32;
|
||||
const size_t width = pointer->width;
|
||||
const size_t height = pointer->height;
|
||||
const size_t xorBpp = pointer->xorBpp;
|
||||
const size_t bpp = FreeRDPGetBytesPerPixel(format);
|
||||
const size_t stride = width * bpp;
|
||||
|
||||
uint8_t* bmp = calloc(stride, height);
|
||||
if (!bmp)
|
||||
goto fail;
|
||||
|
||||
const BOOL result = freerdp_image_copy_from_pointer_data(
|
||||
bmp, format, 0, 0, 0, width, height, pointer->xorMaskData, pointer->lengthXorMask,
|
||||
pointer->andMaskData, pointer->lengthAndMask, xorBpp, palette);
|
||||
if (!result)
|
||||
goto fail;
|
||||
|
||||
rc = TRUE;
|
||||
for (size_t y = 0; y < height; y++)
|
||||
{
|
||||
const uint8_t* linea = &bmp[y * stride];
|
||||
const uint8_t* lineb = &ref[y * stride];
|
||||
for (size_t x = 0; x < stride; x++)
|
||||
{
|
||||
const uint8_t a = linea[x];
|
||||
const uint8_t b = lineb[x];
|
||||
if (a != b)
|
||||
{
|
||||
printf("xxx: %" PRIuz "x%" PRIuz ": color %" PRIuz " diff 0x%02" PRIx8
|
||||
"<-->0x%02" PRIx8 "\n",
|
||||
x / 4, y, x % 4, a, b);
|
||||
rc = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fail:
|
||||
free(bmp);
|
||||
WLog_INFO("test", "cursor test case %" PRIuz ": %s", x, rc ? "success" : "failure");
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecCursor(WINPR_ATTR_UNUSED int argc, WINPR_ATTR_UNUSED char* argv[])
|
||||
{
|
||||
const size_t palette_len = ARRAYSIZE(testcase_palette);
|
||||
const size_t pointer_len = ARRAYSIZE(testcase_pointer);
|
||||
const size_t bmp_len = ARRAYSIZE(testcase_image_bgra32);
|
||||
WINPR_ASSERT(palette_len == pointer_len);
|
||||
WINPR_ASSERT(palette_len == bmp_len);
|
||||
|
||||
int rc = 0;
|
||||
for (size_t x = 0; x < palette_len; x++)
|
||||
{
|
||||
const gdiPalette* palette = testcase_palette[x];
|
||||
const rdpPointer* pointer = testcase_pointer[x];
|
||||
const uint8_t* bmp = testcase_image_bgra32[x];
|
||||
|
||||
if (!run_testcase(x, palette, pointer, bmp))
|
||||
rc = -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <winpr/sysinfo.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
static const char* print_ns(UINT64 start, UINT64 end, char* buffer, size_t len)
|
||||
{
|
||||
const UINT64 diff = end - start;
|
||||
const unsigned ns = diff % 1000;
|
||||
const unsigned us = (diff / 1000) % 1000;
|
||||
const unsigned ms = (diff / 1000000) % 1000;
|
||||
const unsigned s = (diff / 1000000000ULL) % 1000;
|
||||
(void)_snprintf(buffer, len, "%03u %03u %03u %03uns", s, ms, us, ns);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static BOOL testContextOptions(BOOL compressor, uint32_t width, uint32_t height)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const UINT64 start = winpr_GetUnixTimeNS();
|
||||
H264_CONTEXT* h264 = h264_context_new(FALSE);
|
||||
if (!h264)
|
||||
return FALSE;
|
||||
|
||||
struct optpair_s
|
||||
{
|
||||
H264_CONTEXT_OPTION opt;
|
||||
uint32_t val;
|
||||
};
|
||||
const struct optpair_s optpair[] = { { H264_CONTEXT_OPTION_RATECONTROL, H264_RATECONTROL_VBR },
|
||||
{ H264_CONTEXT_OPTION_BITRATE, 2323 },
|
||||
{ H264_CONTEXT_OPTION_FRAMERATE, 23 },
|
||||
{ H264_CONTEXT_OPTION_QP, 21 },
|
||||
{ H264_CONTEXT_OPTION_USAGETYPE, 23 } };
|
||||
for (size_t x = 0; x < ARRAYSIZE(optpair); x++)
|
||||
{
|
||||
const struct optpair_s* cur = &optpair[x];
|
||||
if (!h264_context_set_option(h264, cur->opt, cur->val))
|
||||
goto fail;
|
||||
}
|
||||
if (!h264_context_reset(h264, width, height))
|
||||
goto fail;
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
h264_context_free(h264);
|
||||
const UINT64 end = winpr_GetUnixTimeNS();
|
||||
|
||||
char buffer[64] = WINPR_C_ARRAY_INIT;
|
||||
printf("[%s] %" PRIu32 "x%" PRIu32 " took %s\n", __func__, width, height,
|
||||
print_ns(start, end, buffer, sizeof(buffer)));
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void* allocRGB(uint32_t format, uint32_t width, uint32_t height, uint32_t* pstride)
|
||||
{
|
||||
const size_t bpp = FreeRDPGetBytesPerPixel(format);
|
||||
const size_t stride = bpp * width + 32;
|
||||
WINPR_ASSERT(pstride);
|
||||
*pstride = WINPR_ASSERTING_INT_CAST(uint32_t, stride);
|
||||
|
||||
uint8_t* rgb = calloc(stride, height);
|
||||
if (!rgb)
|
||||
return nullptr;
|
||||
|
||||
for (size_t x = 0; x < height; x++)
|
||||
{
|
||||
if (winpr_RAND(&rgb[x * stride], width * bpp) < 0)
|
||||
{
|
||||
free(rgb);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return rgb;
|
||||
}
|
||||
|
||||
static BOOL compareRGB(const uint8_t* src, const uint8_t* dst, uint32_t format, size_t width,
|
||||
size_t stride, size_t height)
|
||||
{
|
||||
const size_t bpp = FreeRDPGetBytesPerPixel(format);
|
||||
for (size_t y = 0; y < height; y++)
|
||||
{
|
||||
const uint8_t* csrc = &src[y * stride];
|
||||
const uint8_t* cdst = &dst[y * stride];
|
||||
const int rc = memcmp(csrc, cdst, width * bpp);
|
||||
// TODO: Both, AVC420 encoding and decoding are lossy.
|
||||
// TODO: Find a proper error margin to check for
|
||||
#if 0
|
||||
if (rc != 0)
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL testEncode(uint32_t format, uint32_t width, uint32_t height)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
void* src = nullptr;
|
||||
void* out = nullptr;
|
||||
RDPGFX_H264_METABLOCK meta = WINPR_C_ARRAY_INIT;
|
||||
H264_CONTEXT* h264 = h264_context_new(TRUE);
|
||||
H264_CONTEXT* h264dec = h264_context_new(FALSE);
|
||||
if (!h264 || !h264dec)
|
||||
goto fail;
|
||||
|
||||
if (!h264_context_reset(h264, width, height))
|
||||
goto fail;
|
||||
if (!h264_context_reset(h264dec, width, height))
|
||||
goto fail;
|
||||
|
||||
uint32_t stride = 0;
|
||||
uint32_t ostride = 0;
|
||||
src = allocRGB(format, width, height, &stride);
|
||||
out = allocRGB(format, width, height, &ostride);
|
||||
if (!src || !out || (stride < width) || (stride != ostride))
|
||||
goto fail;
|
||||
|
||||
const RECTANGLE_16 rect = { .left = 0, .top = 0, .right = width, .bottom = height };
|
||||
uint32_t dstsize = 0;
|
||||
uint8_t* dst = nullptr;
|
||||
if (avc420_compress(h264, src, format, stride, width, height, &rect, &dst, &dstsize, &meta) < 0)
|
||||
goto fail;
|
||||
if ((dstsize == 0) || !dst)
|
||||
goto fail;
|
||||
|
||||
if (avc420_decompress(h264dec, dst, dstsize, out, format, stride, width, height, &rect, 1) < 0)
|
||||
goto fail;
|
||||
|
||||
rc = compareRGB(src, out, format, width, stride, height);
|
||||
fail:
|
||||
h264_context_free(h264);
|
||||
h264_context_free(h264dec);
|
||||
free_h264_metablock(&meta);
|
||||
free(src);
|
||||
free(out);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecH264(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
UINT32 width = 124;
|
||||
UINT32 height = 54;
|
||||
const UINT32 formats[] = {
|
||||
PIXEL_FORMAT_ABGR15, PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_BGR16,
|
||||
PIXEL_FORMAT_BGR24, PIXEL_FORMAT_RGB15, PIXEL_FORMAT_RGB16, PIXEL_FORMAT_RGB24,
|
||||
PIXEL_FORMAT_ABGR32, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_XRGB32,
|
||||
PIXEL_FORMAT_BGRA32, PIXEL_FORMAT_RGBA32, PIXEL_FORMAT_BGRX32, PIXEL_FORMAT_RGBX32,
|
||||
};
|
||||
|
||||
if (argc == 3)
|
||||
{
|
||||
errno = 0;
|
||||
width = strtoul(argv[1], nullptr, 0);
|
||||
height = strtoul(argv[2], nullptr, 0);
|
||||
if ((errno != 0) || (width == 0) || (height == 0))
|
||||
{
|
||||
char buffer[128] = WINPR_C_ARRAY_INIT;
|
||||
(void)fprintf(stderr, "%s failed: width=%" PRIu32 ", height=%" PRIu32 ", errno=%s\n",
|
||||
__func__, width, height, winpr_strerror(errno, buffer, sizeof(buffer)));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(WITH_MEDIACODEC) && !defined(WITH_MEDIA_FOUNDATION) && !defined(WITH_OPENH264) && \
|
||||
!defined(WITH_VIDEO_FFMPEG)
|
||||
(void)fprintf(stderr, "[%s] skipping, no H264 encoder/decoder support compiled in\n", __func__);
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if (!testContextOptions(FALSE, width, height))
|
||||
return -1;
|
||||
if (!testContextOptions(TRUE, width, height))
|
||||
return -1;
|
||||
|
||||
for (size_t x = 0; x < ARRAYSIZE(formats); x++)
|
||||
{
|
||||
const UINT32 SrcFormat = formats[x];
|
||||
for (size_t y = 0; y < ARRAYSIZE(formats); y++)
|
||||
{
|
||||
if (!testEncode(SrcFormat, width, height))
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,454 @@
|
||||
|
||||
#include <freerdp/config.h>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/json.h>
|
||||
#include <winpr/path.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/codec/interleaved.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <freerdp/utils/profiler.h>
|
||||
|
||||
#include "TestFreeRDPHelpers.h"
|
||||
|
||||
// #define CREATE_TEST_OUTPUT
|
||||
|
||||
static bool run_encode_decode_single(UINT16 bpp, BITMAP_INTERLEAVED_CONTEXT* encoder,
|
||||
BITMAP_INTERLEAVED_CONTEXT* decoder
|
||||
#if defined(WITH_PROFILER)
|
||||
,
|
||||
PROFILER* profiler_comp, PROFILER* profiler_decomp
|
||||
#endif
|
||||
)
|
||||
{
|
||||
bool rc2 = false;
|
||||
bool rc = 0;
|
||||
const UINT32 w = 64;
|
||||
const UINT32 h = 64;
|
||||
const UINT32 x = 0;
|
||||
const UINT32 y = 0;
|
||||
const UINT32 format = PIXEL_FORMAT_RGBX32;
|
||||
const UINT32 bstep = FreeRDPGetBytesPerPixel(format);
|
||||
const size_t step = (13ULL + w) * 4ULL;
|
||||
const size_t SrcSize = step * h;
|
||||
const int maxDiff = 4 * ((bpp < 24) ? 2 : 1);
|
||||
UINT32 DstSize = SrcSize;
|
||||
BYTE* pSrcData = calloc(1, SrcSize);
|
||||
BYTE* pDstData = calloc(1, SrcSize);
|
||||
BYTE* tmp = calloc(1, SrcSize);
|
||||
|
||||
if (!pSrcData || !pDstData || !tmp)
|
||||
goto fail;
|
||||
|
||||
if (winpr_RAND(pSrcData, SrcSize) < 0)
|
||||
goto fail;
|
||||
|
||||
if (!bitmap_interleaved_context_reset(encoder) || !bitmap_interleaved_context_reset(decoder))
|
||||
goto fail;
|
||||
|
||||
PROFILER_ENTER(profiler_comp)
|
||||
rc = interleaved_compress(encoder, tmp, &DstSize, w, h, pSrcData, format, step, x, y, nullptr,
|
||||
bpp);
|
||||
PROFILER_EXIT(profiler_comp)
|
||||
|
||||
if (!rc)
|
||||
goto fail;
|
||||
|
||||
PROFILER_ENTER(profiler_decomp)
|
||||
rc = interleaved_decompress(decoder, tmp, DstSize, w, h, bpp, pDstData, format, step, x, y, w,
|
||||
h, nullptr);
|
||||
PROFILER_EXIT(profiler_decomp)
|
||||
|
||||
if (!rc)
|
||||
goto fail;
|
||||
|
||||
for (UINT32 i = 0; i < h; i++)
|
||||
{
|
||||
const BYTE* srcLine = &pSrcData[i * step];
|
||||
const BYTE* dstLine = &pDstData[i * step];
|
||||
|
||||
for (UINT32 j = 0; j < w; j++)
|
||||
{
|
||||
BYTE r = 0;
|
||||
BYTE g = 0;
|
||||
BYTE b = 0;
|
||||
BYTE dr = 0;
|
||||
BYTE dg = 0;
|
||||
BYTE db = 0;
|
||||
const UINT32 srcColor = FreeRDPReadColor(&srcLine[1ULL * j * bstep], format);
|
||||
const UINT32 dstColor = FreeRDPReadColor(&dstLine[1ULL * j * bstep], format);
|
||||
FreeRDPSplitColor(srcColor, format, &r, &g, &b, nullptr, nullptr);
|
||||
FreeRDPSplitColor(dstColor, format, &dr, &dg, &db, nullptr, nullptr);
|
||||
|
||||
if (abs(r - dr) > maxDiff)
|
||||
goto fail;
|
||||
|
||||
if (abs(g - dg) > maxDiff)
|
||||
goto fail;
|
||||
|
||||
if (abs(b - db) > maxDiff)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
rc2 = true;
|
||||
fail:
|
||||
free(pSrcData);
|
||||
free(pDstData);
|
||||
free(tmp);
|
||||
return rc2;
|
||||
}
|
||||
|
||||
static const char* get_profiler_name(bool encode, UINT16 bpp)
|
||||
{
|
||||
switch (bpp)
|
||||
{
|
||||
case 24:
|
||||
if (encode)
|
||||
return "interleaved_compress 24bpp";
|
||||
else
|
||||
return "interleaved_decompress 24bpp";
|
||||
|
||||
case 16:
|
||||
if (encode)
|
||||
return "interleaved_compress 16bpp";
|
||||
else
|
||||
return "interleaved_decompress 16bpp";
|
||||
|
||||
case 15:
|
||||
if (encode)
|
||||
return "interleaved_compress 15bpp";
|
||||
else
|
||||
return "interleaved_decompress 15bpp";
|
||||
|
||||
default:
|
||||
return "configuration error!";
|
||||
}
|
||||
}
|
||||
|
||||
static bool run_encode_decode(UINT16 bpp, BITMAP_INTERLEAVED_CONTEXT* encoder,
|
||||
BITMAP_INTERLEAVED_CONTEXT* decoder)
|
||||
{
|
||||
bool rc = false;
|
||||
PROFILER_DEFINE(profiler_comp)
|
||||
PROFILER_DEFINE(profiler_decomp)
|
||||
PROFILER_CREATE(profiler_comp, get_profiler_name(true, bpp))
|
||||
PROFILER_CREATE(profiler_decomp, get_profiler_name(false, bpp))
|
||||
|
||||
for (UINT32 x = 0; x < 50; x++)
|
||||
{
|
||||
if (!run_encode_decode_single(bpp, encoder, decoder
|
||||
#if defined(WITH_PROFILER)
|
||||
,
|
||||
profiler_comp, profiler_decomp
|
||||
#endif
|
||||
))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = true;
|
||||
fail:
|
||||
PROFILER_PRINT_HEADER
|
||||
PROFILER_PRINT(profiler_comp)
|
||||
PROFILER_PRINT(profiler_decomp)
|
||||
PROFILER_PRINT_FOOTER
|
||||
PROFILER_FREE(profiler_comp)
|
||||
PROFILER_FREE(profiler_decomp)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool TestColorConversion(void)
|
||||
{
|
||||
const UINT32 formats[] = { PIXEL_FORMAT_RGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_ABGR15,
|
||||
PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_BGR16, PIXEL_FORMAT_RGB16 };
|
||||
|
||||
/* Check color conversion 15/16 -> 32bit maps to proper values */
|
||||
for (UINT32 x = 0; x < ARRAYSIZE(formats); x++)
|
||||
{
|
||||
const UINT32 dstFormat = PIXEL_FORMAT_RGBA32;
|
||||
const UINT32 format = formats[x];
|
||||
const UINT32 colorLow = FreeRDPGetColor(format, 0, 0, 0, 255);
|
||||
const UINT32 colorHigh = FreeRDPGetColor(format, 255, 255, 255, 255);
|
||||
const UINT32 colorLow32 = FreeRDPConvertColor(colorLow, format, dstFormat, nullptr);
|
||||
const UINT32 colorHigh32 = FreeRDPConvertColor(colorHigh, format, dstFormat, nullptr);
|
||||
BYTE r = 0;
|
||||
BYTE g = 0;
|
||||
BYTE b = 0;
|
||||
BYTE a = 0;
|
||||
FreeRDPSplitColor(colorLow32, dstFormat, &r, &g, &b, &a, nullptr);
|
||||
if ((r != 0) || (g != 0) || (b != 0))
|
||||
return false;
|
||||
|
||||
FreeRDPSplitColor(colorHigh32, dstFormat, &r, &g, &b, &a, nullptr);
|
||||
if ((r != 255) || (g != 255) || (b != 255))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool RunEncoderTest(const char* name, uint32_t format, uint32_t width, uint32_t height,
|
||||
uint32_t step, uint32_t bpp)
|
||||
{
|
||||
bool rc = false;
|
||||
void* data = nullptr;
|
||||
void* encdata = nullptr;
|
||||
BITMAP_INTERLEAVED_CONTEXT* encoder = bitmap_interleaved_context_new(true);
|
||||
if (!encoder)
|
||||
goto fail;
|
||||
|
||||
size_t srclen = 0;
|
||||
data = test_codec_helper_read_data("interleaved", "bmp", name, &srclen);
|
||||
if (!data)
|
||||
goto fail;
|
||||
|
||||
encdata = calloc(srclen, 1);
|
||||
if (!encdata)
|
||||
goto fail;
|
||||
|
||||
for (size_t x = 0; x < 42; x++)
|
||||
{
|
||||
uint32_t enclen = WINPR_ASSERTING_INT_CAST(uint32_t, srclen);
|
||||
if (!interleaved_compress(encoder, encdata, &enclen, width, height, data, format, step, 0,
|
||||
0, nullptr, bpp))
|
||||
goto fail;
|
||||
|
||||
char encname[128] = WINPR_C_ARRAY_INIT;
|
||||
(void)_snprintf(encname, sizeof(encname), "enc-%" PRIu32, bpp);
|
||||
#if defined(CREATE_TEST_OUTPUT)
|
||||
test_codec_helper_write_data("interleaved", encname, name, encdata, enclen);
|
||||
#else
|
||||
if (!test_codec_helper_compare("interleaved", encname, name, encdata, enclen))
|
||||
goto fail;
|
||||
#endif
|
||||
}
|
||||
|
||||
rc = true;
|
||||
|
||||
fail:
|
||||
free(data);
|
||||
free(encdata);
|
||||
bitmap_interleaved_context_free(encoder);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool RunDecoderTest(const char* name, uint32_t format, uint32_t width, uint32_t height,
|
||||
uint32_t step, uint32_t bpp)
|
||||
{
|
||||
bool rc = false;
|
||||
void* data = nullptr;
|
||||
void* decdata = nullptr;
|
||||
BITMAP_INTERLEAVED_CONTEXT* decoder = bitmap_interleaved_context_new(false);
|
||||
if (!decoder)
|
||||
goto fail;
|
||||
|
||||
char encname[128] = WINPR_C_ARRAY_INIT;
|
||||
(void)_snprintf(encname, sizeof(encname), "enc-%" PRIu32, bpp);
|
||||
|
||||
size_t srclen = 0;
|
||||
data = test_codec_helper_read_data("interleaved", encname, name, &srclen);
|
||||
if (!data)
|
||||
goto fail;
|
||||
|
||||
const size_t declen = 1ULL * step * height;
|
||||
decdata = calloc(step, height);
|
||||
if (!decdata)
|
||||
goto fail;
|
||||
|
||||
for (size_t x = 0; x < 42; x++)
|
||||
{
|
||||
if (!interleaved_decompress(decoder, data, WINPR_ASSERTING_INT_CAST(uint32_t, srclen),
|
||||
width, height, bpp, decdata, format, step, 0, 0, width, height,
|
||||
nullptr))
|
||||
goto fail;
|
||||
|
||||
char decname[128] = WINPR_C_ARRAY_INIT;
|
||||
(void)_snprintf(decname, sizeof(decname), "dec-%s", encname);
|
||||
#if defined(CREATE_TEST_OUTPUT)
|
||||
test_codec_helper_write_data("interleaved", decname, name, decdata, declen);
|
||||
#else
|
||||
if (!test_codec_helper_compare("interleaved", decname, name, decdata, declen))
|
||||
goto fail;
|
||||
#endif
|
||||
}
|
||||
|
||||
rc = true;
|
||||
|
||||
fail:
|
||||
free(data);
|
||||
free(decdata);
|
||||
bitmap_interleaved_context_free(decoder);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* The encoder expects a JSON that describes a test cast:
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* "name": "somestring",
|
||||
* "format": "somestring",
|
||||
* "width": <someint>,
|
||||
* "height": <someint>,
|
||||
* "step": <someint>,
|
||||
* "bpp": <someint>
|
||||
* },
|
||||
* {...},
|
||||
* ...
|
||||
* ]
|
||||
*/
|
||||
static bool isObjectValid(const WINPR_JSON* obj)
|
||||
{
|
||||
if (!obj || !WINPR_JSON_IsObject(obj))
|
||||
return false;
|
||||
|
||||
const char* strvalues[] = { "name", "format" };
|
||||
for (size_t x = 0; x < ARRAYSIZE(strvalues); x++)
|
||||
{
|
||||
const char* val = strvalues[x];
|
||||
|
||||
if (!WINPR_JSON_HasObjectItem(obj, val))
|
||||
return false;
|
||||
|
||||
WINPR_JSON* jval = WINPR_JSON_GetObjectItem(obj, val);
|
||||
if (!jval)
|
||||
return false;
|
||||
|
||||
if (!WINPR_JSON_IsString(jval))
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* values[] = { "width", "height", "step" };
|
||||
for (size_t x = 0; x < ARRAYSIZE(values); x++)
|
||||
{
|
||||
const char* val = values[x];
|
||||
if (!WINPR_JSON_HasObjectItem(obj, val))
|
||||
return false;
|
||||
WINPR_JSON* jval = WINPR_JSON_GetObjectItem(obj, val);
|
||||
if (!jval)
|
||||
return false;
|
||||
if (!WINPR_JSON_IsNumber(jval))
|
||||
return false;
|
||||
const double dval = WINPR_JSON_GetNumberValue(jval);
|
||||
if (dval <= 0.0)
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
const char* val = "bpp";
|
||||
|
||||
if (!WINPR_JSON_HasObjectItem(obj, val))
|
||||
return false;
|
||||
|
||||
WINPR_JSON* jval = WINPR_JSON_GetObjectItem(obj, val);
|
||||
if (!jval)
|
||||
return false;
|
||||
|
||||
if (!WINPR_JSON_IsArray(jval))
|
||||
return false;
|
||||
|
||||
for (size_t x = 0; x < WINPR_JSON_GetArraySize(jval); x++)
|
||||
{
|
||||
WINPR_JSON* aval = WINPR_JSON_GetArrayItem(jval, x);
|
||||
if (!jval || !WINPR_JSON_IsNumber(aval))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestEncoder(void)
|
||||
{
|
||||
bool rc = false;
|
||||
WINPR_JSON* json = nullptr;
|
||||
char* file = nullptr;
|
||||
char* path = GetCombinedPath(CMAKE_CURRENT_SOURCE_DIR, "interleaved");
|
||||
if (!path)
|
||||
goto fail;
|
||||
file = GetCombinedPath(path, "encoder.json");
|
||||
if (!file)
|
||||
goto fail;
|
||||
|
||||
json = WINPR_JSON_ParseFromFile(file);
|
||||
if (!json)
|
||||
goto fail;
|
||||
|
||||
if (!WINPR_JSON_IsArray(json))
|
||||
goto fail;
|
||||
|
||||
for (size_t x = 0; x < WINPR_JSON_GetArraySize(json); x++)
|
||||
{
|
||||
WINPR_JSON* obj = WINPR_JSON_GetArrayItem(json, x);
|
||||
if (!isObjectValid(obj))
|
||||
goto fail;
|
||||
|
||||
const char* name = WINPR_JSON_GetStringValue(WINPR_JSON_GetObjectItem(obj, "name"));
|
||||
const uint32_t format = WINPR_ASSERTING_INT_CAST(
|
||||
uint32_t, FreeRDPGetColorFromatFromName(
|
||||
WINPR_JSON_GetStringValue(WINPR_JSON_GetObjectItem(obj, "format"))));
|
||||
const uint32_t width = WINPR_ASSERTING_INT_CAST(
|
||||
uint32_t, WINPR_JSON_GetNumberValue(WINPR_JSON_GetObjectItem(obj, "width")));
|
||||
const uint32_t height = WINPR_ASSERTING_INT_CAST(
|
||||
uint32_t, WINPR_JSON_GetNumberValue(WINPR_JSON_GetObjectItem(obj, "height")));
|
||||
const uint32_t step = WINPR_ASSERTING_INT_CAST(
|
||||
uint32_t, WINPR_JSON_GetNumberValue(WINPR_JSON_GetObjectItem(obj, "step")));
|
||||
|
||||
WINPR_JSON* jbpp = WINPR_JSON_GetObjectItem(obj, "bpp");
|
||||
for (size_t x = 0; x < WINPR_JSON_GetArraySize(jbpp); x++)
|
||||
{
|
||||
const uint32_t bpp = WINPR_ASSERTING_INT_CAST(
|
||||
uint32_t, WINPR_JSON_GetNumberValue(WINPR_JSON_GetArrayItem(jbpp, x)));
|
||||
if (!RunEncoderTest(name, format, width, height, step, bpp))
|
||||
goto fail;
|
||||
if (!RunDecoderTest(name, format, width, height, step, bpp))
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
rc = true;
|
||||
fail:
|
||||
WINPR_JSON_Delete(json);
|
||||
free(path);
|
||||
free(file);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecInterleaved(int argc, char* argv[])
|
||||
{
|
||||
BITMAP_INTERLEAVED_CONTEXT* encoder = nullptr;
|
||||
BITMAP_INTERLEAVED_CONTEXT* decoder = nullptr;
|
||||
int rc = -1;
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
encoder = bitmap_interleaved_context_new(true);
|
||||
decoder = bitmap_interleaved_context_new(false);
|
||||
|
||||
if (!encoder || !decoder)
|
||||
goto fail;
|
||||
|
||||
if (!run_encode_decode(24, encoder, decoder))
|
||||
goto fail;
|
||||
|
||||
if (!run_encode_decode(16, encoder, decoder))
|
||||
goto fail;
|
||||
|
||||
if (!run_encode_decode(15, encoder, decoder))
|
||||
goto fail;
|
||||
|
||||
if (!TestColorConversion())
|
||||
goto fail;
|
||||
|
||||
if (!TestEncoder())
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
bitmap_interleaved_context_free(encoder);
|
||||
bitmap_interleaved_context_free(decoder);
|
||||
return rc;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,122 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include "../ncrush.h"
|
||||
|
||||
static const BYTE TEST_BELLS_DATA[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!";
|
||||
|
||||
static const BYTE TEST_BELLS_NCRUSH[] =
|
||||
"\xfb\x1d\x7e\xe4\xda\xc7\x1d\x70\xf8\xa1\x6b\x1f\x7d\xc0\xbe\x6b"
|
||||
"\xef\xb5\xef\x21\x87\xd0\xc5\xe1\x85\x71\xd4\x10\x16\xe7\xda\xfb"
|
||||
"\x1d\x7e\xe4\xda\x47\x1f\xb0\xef\xbe\xbd\xff\x2f";
|
||||
|
||||
static BOOL test_NCrushCompressBells(void)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
int status = 0;
|
||||
UINT32 Flags = 0;
|
||||
const BYTE* pDstData = nullptr;
|
||||
BYTE OutputBuffer[65536] = WINPR_C_ARRAY_INIT;
|
||||
const UINT32 SrcSize = sizeof(TEST_BELLS_DATA) - 1;
|
||||
const BYTE* pSrcData = TEST_BELLS_DATA;
|
||||
const UINT32 expectedSize = sizeof(TEST_BELLS_NCRUSH) - 1;
|
||||
UINT32 DstSize = sizeof(OutputBuffer);
|
||||
NCRUSH_CONTEXT* ncrush = ncrush_context_new(TRUE);
|
||||
|
||||
if (!ncrush)
|
||||
return rc;
|
||||
|
||||
status = ncrush_compress(ncrush, pSrcData, SrcSize, OutputBuffer, &pDstData, &DstSize, &Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
printf("status: %d Flags: 0x%08" PRIX32 " DstSize: %" PRIu32 "\n", status, Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("NCrushCompressBells: output size mismatch: Actual: %" PRIu32 ", Expected: %" PRIu32
|
||||
"\n",
|
||||
DstSize, expectedSize);
|
||||
printf("Actual\n");
|
||||
BitDump(__func__, WLOG_INFO, pDstData, DstSize * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__func__, WLOG_INFO, TEST_BELLS_NCRUSH, expectedSize * 8, 0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_BELLS_NCRUSH, DstSize) != 0)
|
||||
{
|
||||
printf("NCrushCompressBells: output mismatch\n");
|
||||
printf("Actual\n");
|
||||
BitDump(__func__, WLOG_INFO, pDstData, DstSize * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__func__, WLOG_INFO, TEST_BELLS_NCRUSH, expectedSize * 8, 0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
ncrush_context_free(ncrush);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL test_NCrushDecompressBells(void)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
int status = 0;
|
||||
UINT32 Flags = 0;
|
||||
const BYTE* pSrcData = nullptr;
|
||||
UINT32 SrcSize = 0;
|
||||
UINT32 DstSize = 0;
|
||||
UINT32 expectedSize = 0;
|
||||
const BYTE* pDstData = nullptr;
|
||||
NCRUSH_CONTEXT* ncrush = ncrush_context_new(FALSE);
|
||||
|
||||
if (!ncrush)
|
||||
return rc;
|
||||
|
||||
SrcSize = sizeof(TEST_BELLS_NCRUSH) - 1;
|
||||
pSrcData = (const BYTE*)TEST_BELLS_NCRUSH;
|
||||
Flags = PACKET_COMPRESSED | 2;
|
||||
expectedSize = sizeof(TEST_BELLS_DATA) - 1;
|
||||
status = ncrush_decompress(ncrush, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
printf("Flags: 0x%08" PRIX32 " DstSize: %" PRIu32 "\n", Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("NCrushDecompressBells: output size mismatch: Actual: %" PRIu32
|
||||
", Expected: %" PRIu32 "\n",
|
||||
DstSize, expectedSize);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_BELLS_DATA, DstSize) != 0)
|
||||
{
|
||||
printf("NCrushDecompressBells: output mismatch\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
ncrush_context_free(ncrush);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecNCrush(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (!test_NCrushCompressBells())
|
||||
return -1;
|
||||
|
||||
if (!test_NCrushDecompressBells())
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
#include <winpr/path.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/codec/planar.h>
|
||||
|
||||
#include "TestFreeRDPHelpers.h"
|
||||
|
||||
static const UINT32 colorFormatList[] = {
|
||||
PIXEL_FORMAT_RGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_RGB16, PIXEL_FORMAT_BGR16,
|
||||
PIXEL_FORMAT_RGB24, PIXEL_FORMAT_BGR24, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_ABGR32,
|
||||
PIXEL_FORMAT_XRGB32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_RGBX32, PIXEL_FORMAT_BGRX32
|
||||
|
||||
};
|
||||
static const UINT32 colorFormatCount = sizeof(colorFormatList) / sizeof(colorFormatList[0]);
|
||||
|
||||
static BOOL CompareBitmap(const BYTE* srcA, UINT32 srcAFormat, const BYTE* srcB, UINT32 srcBFormat,
|
||||
UINT32 width, UINT32 height)
|
||||
{
|
||||
double maxDiff = NAN;
|
||||
const UINT32 srcABits = FreeRDPGetBitsPerPixel(srcAFormat);
|
||||
const UINT32 srcBBits = FreeRDPGetBitsPerPixel(srcBFormat);
|
||||
UINT32 diff = WINPR_ASSERTING_INT_CAST(uint32_t, fabs((double)srcABits - srcBBits));
|
||||
|
||||
/* No support for 8bpp */
|
||||
if ((srcABits < 15) || (srcBBits < 15))
|
||||
return FALSE;
|
||||
|
||||
/* Compare with following granularity:
|
||||
* 32 --> 24 bpp: Each color channel has 8bpp, no difference expected
|
||||
* 24/32 --> 15/16 bpp: 8bit per channel against 5/6bit per channel, +/- 3bit
|
||||
* 16 --> 15bpp: 5/6bit per channel against 5 bit per channel, +/- 1bit
|
||||
*/
|
||||
switch (diff)
|
||||
{
|
||||
case 1:
|
||||
maxDiff = 2 * 2.0;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
case 9:
|
||||
case 16:
|
||||
case 17:
|
||||
maxDiff = 2 * 8.0;
|
||||
break;
|
||||
|
||||
default:
|
||||
maxDiff = 0.0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((srcABits == 32) || (srcBBits == 32))
|
||||
{
|
||||
if (diff == 8)
|
||||
maxDiff = 0.0;
|
||||
}
|
||||
|
||||
for (size_t y = 0; y < height; y++)
|
||||
{
|
||||
const BYTE* lineA = &srcA[y * width * FreeRDPGetBytesPerPixel(srcAFormat)];
|
||||
const BYTE* lineB = &srcB[y * width * FreeRDPGetBytesPerPixel(srcBFormat)];
|
||||
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
BYTE sR = 0;
|
||||
BYTE sG = 0;
|
||||
BYTE sB = 0;
|
||||
BYTE sA = 0;
|
||||
BYTE dR = 0;
|
||||
BYTE dG = 0;
|
||||
BYTE dB = 0;
|
||||
BYTE dA = 0;
|
||||
const BYTE* a = &lineA[x * FreeRDPGetBytesPerPixel(srcAFormat)];
|
||||
const BYTE* b = &lineB[x * FreeRDPGetBytesPerPixel(srcBFormat)];
|
||||
UINT32 colorA = FreeRDPReadColor(a, srcAFormat);
|
||||
UINT32 colorB = FreeRDPReadColor(b, srcBFormat);
|
||||
FreeRDPSplitColor(colorA, srcAFormat, &sR, &sG, &sB, &sA, nullptr);
|
||||
FreeRDPSplitColor(colorB, srcBFormat, &dR, &dG, &dB, &dA, nullptr);
|
||||
|
||||
if (fabs((double)sR - dR) > maxDiff)
|
||||
return FALSE;
|
||||
|
||||
if (fabs((double)sG - dG) > maxDiff)
|
||||
return FALSE;
|
||||
|
||||
if (fabs((double)sB - dB) > maxDiff)
|
||||
return FALSE;
|
||||
|
||||
if (fabs((double)sA - dA) > maxDiff)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL RunTestPlanar(BITMAP_PLANAR_CONTEXT* encplanar, BITMAP_PLANAR_CONTEXT* decplanar,
|
||||
const char* name, const UINT32 srcFormat, const UINT32 dstFormat,
|
||||
const UINT32 width, const UINT32 height)
|
||||
{
|
||||
WINPR_ASSERT(encplanar);
|
||||
WINPR_ASSERT(decplanar);
|
||||
BOOL rc = FALSE;
|
||||
UINT32 dstSize = 0;
|
||||
size_t srclen = 0;
|
||||
(void)printf("---------------------- start %s [%s] ----------------------\n", __func__, name);
|
||||
BYTE* srcBitmap = test_codec_helper_read_data("planar", "bmp", name, &srclen);
|
||||
if (!srcBitmap)
|
||||
return FALSE;
|
||||
|
||||
BYTE* compressedBitmap = freerdp_bitmap_compress_planar(encplanar, srcBitmap, srcFormat, width,
|
||||
height, 0, nullptr, &dstSize);
|
||||
BYTE* decompressedBitmap =
|
||||
(BYTE*)calloc(height, 1ULL * width * FreeRDPGetBytesPerPixel(dstFormat));
|
||||
|
||||
if (!test_codec_helper_compare("planar", "enc", name, compressedBitmap, dstSize))
|
||||
goto fail;
|
||||
|
||||
(void)printf("%s [%s] --> [%s]: ", __func__, FreeRDPGetColorFormatName(srcFormat),
|
||||
FreeRDPGetColorFormatName(dstFormat));
|
||||
|
||||
if (!compressedBitmap || !decompressedBitmap)
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_bitmap_decompress_planar(decplanar, compressedBitmap, dstSize, width, height,
|
||||
decompressedBitmap, dstFormat, 0, 0, 0, width, height,
|
||||
FALSE))
|
||||
{
|
||||
(void)printf("failed to decompress experimental bitmap 01: width: %" PRIu32
|
||||
" height: %" PRIu32 "\n",
|
||||
width, height);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!compare("dec", name, decompressedBitmap,
|
||||
1ull * width * height * FreeRDPGetBytesPerPixel(dstFormat)))
|
||||
goto fail;
|
||||
|
||||
if (!CompareBitmap(decompressedBitmap, dstFormat, srcBitmap, srcFormat, width, height))
|
||||
{
|
||||
printf("FAIL");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
free(srcBitmap);
|
||||
free(compressedBitmap);
|
||||
free(decompressedBitmap);
|
||||
(void)printf("\n");
|
||||
(void)printf("%s [%s]: %s\n", __func__, name, rc ? "SUCCESS" : "FAILED");
|
||||
(void)printf("---------------------- end %s [%s] ----------------------\n", __func__, name);
|
||||
(void)fflush(stdout);
|
||||
(void)fflush(stderr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL RunTestPlanarSingleColor(BITMAP_PLANAR_CONTEXT* planar, const UINT32 srcFormat,
|
||||
const UINT32 dstFormat)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
(void)printf("%s: [%s] --> [%s]: ", __func__, FreeRDPGetColorFormatName(srcFormat),
|
||||
FreeRDPGetColorFormatName(dstFormat));
|
||||
(void)fflush(stdout);
|
||||
(void)fflush(stderr);
|
||||
|
||||
for (UINT32 j = 0; j < 32; j += 8)
|
||||
{
|
||||
for (UINT32 i = 4; i < 32; i += 8)
|
||||
{
|
||||
UINT32 compressedSize = 0;
|
||||
const UINT32 fill = j;
|
||||
const UINT32 color = FreeRDPGetColor(srcFormat, (fill >> 8) & 0xF, (fill >> 4) & 0xF,
|
||||
(fill) & 0xF, 0xFF);
|
||||
const UINT32 width = i;
|
||||
const UINT32 height = i;
|
||||
BOOL failed = TRUE;
|
||||
const UINT32 srcSize = width * height * FreeRDPGetBytesPerPixel(srcFormat);
|
||||
const UINT32 dstSize = width * height * FreeRDPGetBytesPerPixel(dstFormat);
|
||||
BYTE* compressedBitmap = nullptr;
|
||||
BYTE* bmp = malloc(srcSize);
|
||||
BYTE* decompressedBitmap = (BYTE*)malloc(dstSize);
|
||||
|
||||
if (!bmp || !decompressedBitmap)
|
||||
goto fail_loop;
|
||||
|
||||
for (size_t y = 0; y < height; y++)
|
||||
{
|
||||
BYTE* line = &bmp[y * width * FreeRDPGetBytesPerPixel(srcFormat)];
|
||||
|
||||
for (size_t x = 0; x < width; x++)
|
||||
{
|
||||
FreeRDPWriteColor(line, srcFormat, color);
|
||||
line += FreeRDPGetBytesPerPixel(srcFormat);
|
||||
}
|
||||
}
|
||||
|
||||
compressedBitmap = freerdp_bitmap_compress_planar(planar, bmp, srcFormat, width, height,
|
||||
0, nullptr, &compressedSize);
|
||||
|
||||
if (!compressedBitmap)
|
||||
goto fail_loop;
|
||||
|
||||
if (!freerdp_bitmap_decompress_planar(planar, compressedBitmap, compressedSize, width,
|
||||
height, decompressedBitmap, dstFormat, 0, 0, 0,
|
||||
width, height, FALSE))
|
||||
goto fail_loop;
|
||||
|
||||
if (!CompareBitmap(decompressedBitmap, dstFormat, bmp, srcFormat, width, height))
|
||||
goto fail_loop;
|
||||
|
||||
failed = FALSE;
|
||||
fail_loop:
|
||||
free(bmp);
|
||||
free(compressedBitmap);
|
||||
free(decompressedBitmap);
|
||||
|
||||
if (failed)
|
||||
{
|
||||
printf("FAIL");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
(void)printf("\n");
|
||||
(void)printf("%s [%s->%s]: %s\n", __func__, FreeRDPGetColorFormatName(srcFormat),
|
||||
FreeRDPGetColorFormatName(dstFormat), rc ? "SUCCESS" : "FAILED");
|
||||
(void)fflush(stdout);
|
||||
(void)fflush(stderr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL TestPlanar(const UINT32 format)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const DWORD planarFlags = PLANAR_FORMAT_HEADER_NA | PLANAR_FORMAT_HEADER_RLE;
|
||||
BITMAP_PLANAR_CONTEXT* encplanar = freerdp_bitmap_planar_context_new(planarFlags, 64, 64);
|
||||
BITMAP_PLANAR_CONTEXT* decplanar = freerdp_bitmap_planar_context_new(planarFlags, 64, 64);
|
||||
|
||||
if (!encplanar || !decplanar)
|
||||
goto fail;
|
||||
|
||||
if (!RunTestPlanar(encplanar, decplanar, "TEST_RLE_BITMAP_EXPERIMENTAL_01", PIXEL_FORMAT_RGBX32,
|
||||
format, 64, 64))
|
||||
goto fail;
|
||||
|
||||
if (!RunTestPlanar(encplanar, decplanar, "TEST_RLE_BITMAP_EXPERIMENTAL_02", PIXEL_FORMAT_RGBX32,
|
||||
format, 64, 64))
|
||||
goto fail;
|
||||
|
||||
if (!RunTestPlanar(encplanar, decplanar, "TEST_RLE_BITMAP_EXPERIMENTAL_03", PIXEL_FORMAT_RGBX32,
|
||||
format, 64, 64))
|
||||
goto fail;
|
||||
|
||||
if (!RunTestPlanar(encplanar, decplanar, "TEST_RLE_UNCOMPRESSED_BITMAP_16BPP",
|
||||
PIXEL_FORMAT_RGB16, format, 32, 32))
|
||||
goto fail;
|
||||
|
||||
for (UINT32 x = 0; x < colorFormatCount; x++)
|
||||
{
|
||||
if (!RunTestPlanarSingleColor(encplanar, format, colorFormatList[x]))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
freerdp_bitmap_planar_context_free(encplanar);
|
||||
freerdp_bitmap_planar_context_free(decplanar);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static UINT32 prand(UINT32 max)
|
||||
{
|
||||
UINT32 tmp = 0;
|
||||
if (max <= 1)
|
||||
return 1;
|
||||
if (winpr_RAND(&tmp, sizeof(tmp)) < 0)
|
||||
{
|
||||
(void)fprintf(stderr, "winpr_RAND failed, retry...\n");
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
exit(-1);
|
||||
}
|
||||
return tmp % (max - 1) + 1;
|
||||
}
|
||||
|
||||
static BOOL FuzzPlanar(void)
|
||||
{
|
||||
(void)printf("---------------------- start %s ----------------------\n", __func__);
|
||||
BOOL rc = FALSE;
|
||||
const DWORD planarFlags = PLANAR_FORMAT_HEADER_NA | PLANAR_FORMAT_HEADER_RLE;
|
||||
BITMAP_PLANAR_CONTEXT* planar = freerdp_bitmap_planar_context_new(planarFlags, 64, 64);
|
||||
|
||||
if (!planar)
|
||||
goto fail;
|
||||
|
||||
for (UINT32 x = 0; x < 100; x++)
|
||||
{
|
||||
BYTE data[0x10000] = WINPR_C_ARRAY_INIT;
|
||||
size_t dataSize = 0x10000;
|
||||
BYTE dstData[0x10000] = WINPR_C_ARRAY_INIT;
|
||||
|
||||
UINT32 DstFormat = 0;
|
||||
UINT32 nDstStep = 0;
|
||||
UINT32 nXDst = 0;
|
||||
UINT32 nYDst = 0;
|
||||
UINT32 nDstWidth = 0;
|
||||
UINT32 nDstHeight = 0;
|
||||
BOOL invalid = TRUE;
|
||||
do
|
||||
{
|
||||
switch (prand(17) - 1)
|
||||
{
|
||||
case 0:
|
||||
DstFormat = PIXEL_FORMAT_RGB8;
|
||||
break;
|
||||
case 1:
|
||||
DstFormat = PIXEL_FORMAT_BGR15;
|
||||
break;
|
||||
case 2:
|
||||
DstFormat = PIXEL_FORMAT_RGB15;
|
||||
break;
|
||||
case 3:
|
||||
DstFormat = PIXEL_FORMAT_ABGR15;
|
||||
break;
|
||||
case 4:
|
||||
DstFormat = PIXEL_FORMAT_ABGR15;
|
||||
break;
|
||||
case 5:
|
||||
DstFormat = PIXEL_FORMAT_BGR16;
|
||||
break;
|
||||
case 6:
|
||||
DstFormat = PIXEL_FORMAT_RGB16;
|
||||
break;
|
||||
case 7:
|
||||
DstFormat = PIXEL_FORMAT_BGR24;
|
||||
break;
|
||||
case 8:
|
||||
DstFormat = PIXEL_FORMAT_RGB24;
|
||||
break;
|
||||
case 9:
|
||||
DstFormat = PIXEL_FORMAT_BGRA32;
|
||||
break;
|
||||
case 10:
|
||||
DstFormat = PIXEL_FORMAT_BGRX32;
|
||||
break;
|
||||
case 11:
|
||||
DstFormat = PIXEL_FORMAT_RGBA32;
|
||||
break;
|
||||
case 12:
|
||||
DstFormat = PIXEL_FORMAT_RGBX32;
|
||||
break;
|
||||
case 13:
|
||||
DstFormat = PIXEL_FORMAT_ABGR32;
|
||||
break;
|
||||
case 14:
|
||||
DstFormat = PIXEL_FORMAT_XBGR32;
|
||||
break;
|
||||
case 15:
|
||||
DstFormat = PIXEL_FORMAT_ARGB32;
|
||||
break;
|
||||
case 16:
|
||||
DstFormat = PIXEL_FORMAT_XRGB32;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
nDstStep = prand(sizeof(dstData));
|
||||
nXDst = prand(nDstStep);
|
||||
nYDst = prand(sizeof(dstData) / nDstStep);
|
||||
nDstWidth = prand(nDstStep / FreeRDPGetBytesPerPixel(DstFormat));
|
||||
nDstHeight = prand(sizeof(dstData) / nDstStep);
|
||||
invalid = nXDst * FreeRDPGetBytesPerPixel(DstFormat) + (nYDst + nDstHeight) * nDstStep >
|
||||
sizeof(dstData);
|
||||
} while (invalid);
|
||||
printf("DstFormat=%s, nXDst=%" PRIu32 ", nYDst=%" PRIu32 ", nDstWidth=%" PRIu32
|
||||
", nDstHeight=%" PRIu32 ", nDstStep=%" PRIu32 ", total size=%" PRIuz "\n",
|
||||
FreeRDPGetColorFormatName(DstFormat), nXDst, nYDst, nDstWidth, nDstHeight, nDstStep,
|
||||
sizeof(dstData));
|
||||
freerdp_planar_switch_bgr(planar, ((prand(2) % 2) != 0));
|
||||
freerdp_bitmap_decompress_planar(planar, data, dataSize, prand(4096), prand(4096), dstData,
|
||||
DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight,
|
||||
((prand(2) % 2) != 0));
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
freerdp_bitmap_planar_context_free(planar);
|
||||
(void)printf("\n");
|
||||
(void)printf("%s: %s\n", __func__, rc ? "SUCCESS" : "FAILED");
|
||||
(void)printf("---------------------- end %s ----------------------\n", __func__);
|
||||
(void)fflush(stdout);
|
||||
(void)fflush(stderr);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecPlanar(int argc, char* argv[])
|
||||
{
|
||||
int rc = -1;
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (!FuzzPlanar())
|
||||
goto fail;
|
||||
|
||||
for (UINT32 x = 0; x < colorFormatCount; x++)
|
||||
{
|
||||
if (!TestPlanar(colorFormatList[x]))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
printf("test returned %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,886 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
|
||||
static BYTE encodeHeaderSample[] = {
|
||||
/* as in 4.2.2 */
|
||||
0xc0, 0xcc, 0x0c, 0x00, 0x00, 0x00, 0xca, 0xac, 0xcc, 0xca, 0x00, 0x01, 0xc3, 0xcc, 0x0d, 0x00,
|
||||
0x00, 0x00, 0x01, 0xff, 0x00, 0x40, 0x00, 0x28, 0xa8, 0xc1, 0xcc, 0x0a, 0x00, 0x00, 0x00, 0x01,
|
||||
0x01, 0x00, 0x01, 0xc2, 0xcc, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x40, 0x00, 0x40, 0x00
|
||||
};
|
||||
|
||||
static BYTE encodeDataSample[] = {
|
||||
/* FRAME_BEGIN as in 4.2.3 */
|
||||
0xc4, 0xcc, 0x0e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
|
||||
|
||||
/* REGION as in 4.2.3 */
|
||||
0xc6, 0xcc, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00, 0xcd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
|
||||
0x00, 0x40, 0x00, 0xc1, 0xca, 0x01, 0x00,
|
||||
|
||||
/* TILESET as in 4.2.4.1 */
|
||||
0xc7, 0xcc, 0x3e, 0x0b, 0x00, 0x00, 0x01, 0x00, 0xc2, 0xca, 0x00, 0x00, 0x51, 0x50, 0x01, 0x40,
|
||||
0x01, 0x00, 0x23, 0x0b, 0x00, 0x00, 0x66, 0x66, 0x77, 0x88, 0x98, 0xc3, 0xca, 0x23, 0x0b, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, 0x03, 0xcf, 0x03, 0x93, 0x03, 0xc0, 0x01,
|
||||
0x01, 0x15, 0x48, 0x99, 0xc7, 0x41, 0xa1, 0x12, 0x68, 0x11, 0xdc, 0x22, 0x29, 0x74, 0xef, 0xfd,
|
||||
0x20, 0x92, 0xe0, 0x4e, 0xa8, 0x69, 0x3b, 0xfd, 0x41, 0x83, 0xbf, 0x28, 0x53, 0x0c, 0x1f, 0xe2,
|
||||
0x54, 0x0c, 0x77, 0x7c, 0xa3, 0x05, 0x7c, 0x30, 0xd0, 0x9c, 0xe8, 0x09, 0x39, 0x1a, 0x5d, 0xff,
|
||||
0xe2, 0x01, 0x22, 0x13, 0x80, 0x90, 0x87, 0xd2, 0x9f, 0xfd, 0xfd, 0x50, 0x09, 0x0d, 0x24, 0xa0,
|
||||
0x8f, 0xab, 0xfe, 0x3c, 0x04, 0x84, 0xc6, 0x9c, 0xde, 0xf8, 0x80, 0xc3, 0x22, 0x50, 0xaf, 0x4c,
|
||||
0x2a, 0x7f, 0xfe, 0xe0, 0x5c, 0xa9, 0x52, 0x8a, 0x06, 0x7d, 0x3d, 0x09, 0x03, 0x65, 0xa3, 0xaf,
|
||||
0xd2, 0x61, 0x1f, 0x72, 0x04, 0x50, 0x8d, 0x3e, 0x16, 0x4a, 0x3f, 0xff, 0xfd, 0x41, 0x42, 0x87,
|
||||
0x24, 0x37, 0x06, 0x17, 0x2e, 0x56, 0x05, 0x9c, 0x1c, 0xb3, 0x84, 0x6a, 0xff, 0xfb, 0x43, 0x8b,
|
||||
0xa3, 0x7a, 0x32, 0x43, 0x28, 0xe1, 0x1f, 0x50, 0x54, 0xfc, 0xca, 0xa5, 0xdf, 0xff, 0x08, 0x04,
|
||||
0x48, 0x15, 0x61, 0xd9, 0x76, 0x43, 0xf8, 0x2a, 0x07, 0xe9, 0x65, 0xf7, 0xc6, 0x89, 0x2d, 0x40,
|
||||
0xa1, 0xc3, 0x35, 0x8d, 0xf5, 0xed, 0xf5, 0x91, 0xae, 0x2f, 0xcc, 0x01, 0xce, 0x03, 0x48, 0xc0,
|
||||
0x8d, 0x63, 0xf4, 0xfd, 0x50, 0x20, 0x2d, 0x0c, 0x9b, 0xb0, 0x8d, 0x13, 0xc0, 0x8a, 0x09, 0x52,
|
||||
0x1b, 0x02, 0x6e, 0x42, 0x3b, 0xd0, 0x13, 0x4e, 0x84, 0x01, 0x26, 0x88, 0x6a, 0x04, 0x84, 0x34,
|
||||
0x2a, 0xa5, 0x00, 0xba, 0x54, 0x48, 0x58, 0xea, 0x54, 0x02, 0xb4, 0x1d, 0xa7, 0xfa, 0x47, 0x82,
|
||||
0xec, 0x7a, 0x77, 0xfd, 0x00, 0x92, 0x66, 0x62, 0x04, 0xa6, 0x9b, 0xff, 0xf6, 0x80, 0xc0, 0x69,
|
||||
0x01, 0xc2, 0x3e, 0x90, 0x14, 0x20, 0x2f, 0xfc, 0x40, 0x96, 0x59, 0x58, 0x0c, 0xb1, 0x13, 0x68,
|
||||
0x20, 0x2e, 0xb5, 0xf5, 0xdf, 0xff, 0xf8, 0xfc, 0x56, 0x88, 0x60, 0x24, 0x53, 0xb5, 0x41, 0x46,
|
||||
0x5f, 0xf8, 0xf1, 0x7e, 0xde, 0x4a, 0x08, 0x97, 0xe0, 0x55, 0x03, 0x8f, 0xe5, 0x75, 0x61, 0x03,
|
||||
0xf2, 0xe1, 0x90, 0x01, 0xa2, 0x8e, 0x88, 0x04, 0x98, 0x05, 0x93, 0x6b, 0xff, 0xea, 0xc0, 0x60,
|
||||
0xa1, 0x88, 0x04, 0x49, 0xbf, 0xf7, 0xff, 0x8c, 0xb4, 0x59, 0x90, 0x80, 0x30, 0x64, 0x53, 0xff,
|
||||
0xf5, 0xc4, 0x48, 0xda, 0xda, 0xcb, 0x80, 0x38, 0x61, 0x57, 0xb2, 0xaf, 0x00, 0xe8, 0x7b, 0x46,
|
||||
0xe6, 0xd8, 0x02, 0x03, 0x8a, 0x06, 0x18, 0x14, 0x32, 0x83, 0xd0, 0x8a, 0xee, 0xbc, 0x81, 0xb4,
|
||||
0x28, 0xc4, 0x7f, 0xf9, 0xa1, 0x69, 0x00, 0x91, 0xc5, 0x51, 0xff, 0xfe, 0x3f, 0xe9, 0xf1, 0x70,
|
||||
0x30, 0x24, 0x10, 0xa7, 0xcb, 0x1f, 0x8a, 0x24, 0x93, 0xed, 0x83, 0x00, 0x36, 0x20, 0xd1, 0x50,
|
||||
0xe7, 0xd8, 0xad, 0x58, 0x20, 0x09, 0x22, 0x80, 0xd0, 0xca, 0x5d, 0x1a, 0xd7, 0xf1, 0x60, 0x75,
|
||||
0x2a, 0xf2, 0xd7, 0xf8, 0xc0, 0x32, 0x45, 0x86, 0x00, 0x43, 0x01, 0xfe, 0x80, 0xf7, 0x42, 0x81,
|
||||
0x74, 0x84, 0x4c, 0xa1, 0x60, 0x4c, 0xcb, 0x14, 0x58, 0x01, 0x4d, 0x18, 0xa1, 0xaa, 0x47, 0x0e,
|
||||
0x11, 0x1a, 0x40, 0x7d, 0x41, 0x02, 0xe3, 0x30, 0xcd, 0x33, 0x81, 0x34, 0x06, 0x46, 0x83, 0xa2,
|
||||
0x47, 0x1c, 0x04, 0xaa, 0x20, 0x12, 0xa2, 0x8b, 0x81, 0xc4, 0x9c, 0xa0, 0x2e, 0x06, 0x32, 0xf8,
|
||||
0x86, 0x85, 0x01, 0xe8, 0x70, 0xf9, 0x46, 0x09, 0x6a, 0xbf, 0xe0, 0xf5, 0xa4, 0xc8, 0x78, 0xe7,
|
||||
0xd2, 0x97, 0x0b, 0xbc, 0x3c, 0x97, 0xff, 0xd5, 0x40, 0x94, 0xb2, 0xc1, 0x18, 0x18, 0x11, 0x1f,
|
||||
0x43, 0xc1, 0x18, 0xc3, 0x83, 0x7f, 0x9a, 0x31, 0xc4, 0x8e, 0x70, 0x56, 0xda, 0xf6, 0x17, 0xde,
|
||||
0xd1, 0x02, 0x0d, 0x42, 0x21, 0x13, 0xdc, 0x3a, 0x3c, 0x40, 0x9e, 0xf4, 0x01, 0x43, 0xea, 0x0c,
|
||||
0x46, 0x73, 0xa2, 0x7b, 0x0c, 0x80, 0xff, 0xe4, 0xad, 0x2e, 0x09, 0xb4, 0x63, 0xb0, 0x8c, 0x54,
|
||||
0x59, 0xfa, 0xac, 0x76, 0x36, 0x10, 0x05, 0xf0, 0x98, 0x88, 0x83, 0x42, 0x00, 0x20, 0x71, 0xcc,
|
||||
0xc1, 0xa9, 0x97, 0x3e, 0x5a, 0x0d, 0x04, 0x50, 0x92, 0x23, 0x20, 0x0d, 0x0a, 0x1c, 0x57, 0xd7,
|
||||
0xff, 0x10, 0xf2, 0x03, 0x0f, 0x58, 0x1b, 0xa5, 0x11, 0xf8, 0xf1, 0xb4, 0x12, 0xdb, 0x1a, 0x48,
|
||||
0x56, 0x1f, 0xe3, 0xc7, 0x50, 0xe9, 0x16, 0xb4, 0xbc, 0xb0, 0x40, 0x93, 0xea, 0xb5, 0x5b, 0x2f,
|
||||
0xfc, 0x50, 0x0a, 0x6f, 0xcc, 0x25, 0xe0, 0x06, 0xab, 0x5f, 0x24, 0xfe, 0x8b, 0xcb, 0x42, 0x43,
|
||||
0x7e, 0x69, 0x02, 0x25, 0xc7, 0x38, 0x00, 0x6e, 0xe5, 0x80, 0xa8, 0xa4, 0x30, 0x44, 0x15, 0x8f,
|
||||
0xe9, 0x0c, 0xd3, 0xa6, 0xc2, 0x14, 0x34, 0x4a, 0xfe, 0x03, 0x7f, 0x06, 0xa5, 0x91, 0x02, 0x54,
|
||||
0xf1, 0xa1, 0xa1, 0x53, 0xbf, 0x11, 0xf2, 0x8f, 0x83, 0x67, 0x80, 0x09, 0x08, 0x12, 0x3f, 0xfd,
|
||||
0x44, 0x91, 0xc2, 0x83, 0x30, 0x50, 0x07, 0x02, 0x82, 0x4d, 0x31, 0x34, 0x06, 0x41, 0x79, 0x6f,
|
||||
0xf0, 0xcc, 0x03, 0x79, 0x00, 0x2c, 0x05, 0x24, 0xec, 0x8d, 0x29, 0x15, 0xaf, 0x44, 0xc8, 0xeb,
|
||||
0x4f, 0xe1, 0xfd, 0xf1, 0x41, 0x48, 0x81, 0x08, 0xaf, 0xfe, 0x51, 0x48, 0xce, 0xe7, 0xf9, 0xb6,
|
||||
0x0a, 0x30, 0x83, 0x11, 0xf0, 0x0c, 0x3b, 0xd2, 0xa6, 0x24, 0x24, 0xef, 0x25, 0xfa, 0x5a, 0x3e,
|
||||
0x92, 0x3e, 0x79, 0x0e, 0x35, 0x61, 0xc8, 0xaa, 0x1c, 0x2e, 0x9a, 0x27, 0x7f, 0xff, 0xf0, 0x7d,
|
||||
0x30, 0x5b, 0xbc, 0x91, 0xff, 0xfe, 0x43, 0x24, 0x28, 0x66, 0xa7, 0x70, 0x99, 0x28, 0x6e, 0x2b,
|
||||
0x18, 0x2b, 0xd4, 0xa1, 0x77, 0x3b, 0x96, 0x9f, 0xf7, 0xeb, 0xbe, 0x1f, 0x04, 0x34, 0x75, 0x84,
|
||||
0x31, 0x42, 0x4c, 0x65, 0xaa, 0x09, 0x50, 0xa0, 0xc4, 0x51, 0x31, 0xd3, 0x26, 0x3a, 0x1b, 0xf4,
|
||||
0x6e, 0x4a, 0x4e, 0x17, 0x25, 0x84, 0x78, 0x7d, 0x2c, 0x3f, 0x46, 0x18, 0xca, 0x5f, 0xf9, 0xe5,
|
||||
0x38, 0x2f, 0xd8, 0x71, 0x94, 0x94, 0xe2, 0xcc, 0xa3, 0x15, 0xb0, 0xda, 0xa9, 0xcb, 0x58, 0xe4,
|
||||
0x18, 0x77, 0x93, 0x8a, 0x51, 0xc6, 0x23, 0xc4, 0x4e, 0x6d, 0xd9, 0x14, 0x1e, 0x9b, 0x8d, 0xbc,
|
||||
0xcb, 0x9d, 0xc4, 0x18, 0x05, 0xf5, 0xa9, 0x29, 0xf8, 0x6d, 0x29, 0x38, 0xc7, 0x44, 0xe5, 0x3a,
|
||||
0xcd, 0xba, 0x61, 0x98, 0x4a, 0x57, 0x02, 0x96, 0x42, 0x02, 0xd9, 0x37, 0x11, 0xde, 0x2d, 0xd4,
|
||||
0x3f, 0xfe, 0x61, 0xe7, 0x33, 0xd7, 0x89, 0x4a, 0xdd, 0xb0, 0x34, 0x47, 0xf4, 0xdc, 0xad, 0xaa,
|
||||
0xc9, 0x9d, 0x7e, 0x6d, 0x4b, 0xcc, 0xdc, 0x17, 0x89, 0x57, 0xfd, 0xbb, 0x37, 0x75, 0x47, 0x5a,
|
||||
0xec, 0x2c, 0x6e, 0x3c, 0x15, 0x92, 0x54, 0x64, 0x2c, 0xab, 0x9e, 0xab, 0x2b, 0xdd, 0x3c, 0x66,
|
||||
0xa0, 0x8f, 0x47, 0x5e, 0x93, 0x1a, 0x37, 0x16, 0xf4, 0x89, 0x23, 0x00, 0x00, 0xb0, 0x33, 0x56,
|
||||
0xfa, 0x14, 0x1e, 0xff, 0x48, 0x7a, 0x7e, 0x0f, 0x10, 0x1f, 0xf4, 0x91, 0xc8, 0x10, 0x56, 0x84,
|
||||
0xff, 0x08, 0xec, 0xb4, 0xac, 0x0e, 0x0f, 0xff, 0xad, 0xc5, 0xe0, 0x1a, 0x2f, 0x82, 0x04, 0x9f,
|
||||
0x91, 0xc2, 0x0e, 0xfe, 0x48, 0x36, 0x79, 0x01, 0x42, 0x14, 0xff, 0xfe, 0x30, 0xf0, 0x08, 0x18,
|
||||
0xf1, 0x81, 0x45, 0x9a, 0x60, 0xc1, 0x79, 0xf0, 0x14, 0x12, 0x10, 0xce, 0xea, 0x31, 0x5a, 0xff,
|
||||
0xfc, 0x20, 0x13, 0x82, 0x2f, 0xc9, 0x02, 0x1f, 0x81, 0xcb, 0x00, 0xe1, 0x10, 0xd2, 0xb4, 0xbe,
|
||||
0x87, 0xff, 0xb0, 0x1e, 0x27, 0x81, 0xb7, 0x04, 0x06, 0x3c, 0xc2, 0x04, 0xf6, 0x06, 0x0e, 0x28,
|
||||
0xbc, 0x40, 0xbf, 0x12, 0x1e, 0x86, 0xd4, 0x6a, 0x7f, 0x18, 0x1b, 0x96, 0x85, 0x4c, 0x16, 0x80,
|
||||
0xdf, 0x2c, 0xa5, 0x8d, 0x86, 0xa3, 0x4a, 0x8a, 0xb4, 0x1b, 0xa1, 0x38, 0xa9, 0xd5, 0xff, 0xff,
|
||||
0xea, 0x06, 0x20, 0xd2, 0x95, 0x1e, 0xf4, 0x2f, 0xb2, 0x12, 0x0e, 0x61, 0x78, 0x4a, 0x17, 0x52,
|
||||
0x5d, 0xe4, 0x25, 0x1f, 0xfe, 0xc0, 0xb3, 0x1f, 0xff, 0xff, 0xec, 0x02, 0x82, 0x80, 0x90, 0x41,
|
||||
0x88, 0xde, 0x48, 0x2c, 0x42, 0x52, 0x0b, 0x2f, 0x43, 0x7e, 0x50, 0x78, 0xf2, 0x67, 0x78, 0x41,
|
||||
0x34, 0x3d, 0xc8, 0x0f, 0x67, 0xa1, 0xeb, 0x21, 0xfe, 0xc0, 0x1f, 0x22, 0x60, 0x41, 0x6c, 0x00,
|
||||
0x92, 0x4b, 0x60, 0x10, 0xd0, 0x0d, 0x01, 0x35, 0x05, 0x0e, 0x87, 0xa2, 0xa0, 0x5d, 0x1f, 0xa3,
|
||||
0xaf, 0x7f, 0xf1, 0xbe, 0x8f, 0xcd, 0xa5, 0x00, 0x1c, 0x10, 0x40, 0x15, 0x76, 0x81, 0x05, 0xef,
|
||||
0xee, 0x00, 0x60, 0x84, 0x00, 0x99, 0x40, 0x4a, 0x82, 0x17, 0xe9, 0xfc, 0xc4, 0x7f, 0xff, 0xfd,
|
||||
0x04, 0x80, 0x06, 0x06, 0xdc, 0xaf, 0xa7, 0x7e, 0x94, 0x75, 0x74, 0x01, 0x00, 0xe0, 0x91, 0x00,
|
||||
0x85, 0x7f, 0x8e, 0xd6, 0x0b, 0x20, 0x21, 0x30, 0xca, 0x62, 0x8e, 0x07, 0x04, 0xe9, 0x45, 0x40,
|
||||
0x5f, 0x47, 0x4a, 0x30, 0x15, 0x41, 0xcb, 0xdf, 0xff, 0xfc, 0xbf, 0xc3, 0xb4, 0x46, 0x6a, 0x01,
|
||||
0x40, 0xd0, 0xa7, 0x34, 0x18, 0x24, 0x1c, 0x2a, 0x45, 0xfe, 0xa8, 0x05, 0x08, 0x61, 0xfd, 0xa8,
|
||||
0x80, 0x71, 0x01, 0x25, 0x9c, 0xc1, 0x47, 0x17, 0x37, 0x02, 0x7a, 0x15, 0xff, 0xf3, 0x01, 0x45,
|
||||
0x7f, 0xd6, 0x80, 0x60, 0x83, 0x67, 0xf8, 0x9d, 0x2f, 0xf4, 0xdd, 0x8c, 0x30, 0x01, 0x51, 0x42,
|
||||
0xbc, 0x43, 0x7a, 0x6b, 0x9f, 0x84, 0x1e, 0x00, 0x48, 0xc1, 0xe0, 0xb7, 0xe0, 0x7e, 0x99, 0xf2,
|
||||
0x4a, 0xe9, 0x40, 0x02, 0x81, 0xc3, 0x00, 0x24, 0x3a, 0xc5, 0x52, 0x0f, 0x91, 0xc8, 0x68, 0x25,
|
||||
0x40, 0x99, 0xa4, 0x25, 0x1a, 0x04, 0xd0, 0xa2, 0x91, 0xdd, 0xeb, 0x93, 0x00, 0x21, 0x49, 0x24,
|
||||
0x8b, 0x40, 0x75, 0x38, 0x14, 0xa1, 0xfd, 0x3f, 0x88, 0x25, 0xbf, 0x32, 0x00, 0xe3, 0x19, 0xfc,
|
||||
0xb9, 0xf8, 0x6f, 0x81, 0xc0, 0x01, 0xb3, 0x93, 0x20, 0x09, 0x08, 0x25, 0x84, 0xe1, 0x34, 0xd4,
|
||||
0x1b, 0x48, 0x88, 0x11, 0xa0, 0x15, 0x59, 0xd7, 0x07, 0x81, 0x81, 0x3b, 0xa1, 0x40, 0x2e, 0x2f,
|
||||
0x48, 0x70, 0x09, 0xc4, 0x76, 0x49, 0x0f, 0x2e, 0x50, 0x2e, 0x46, 0x19, 0xa4, 0x16, 0xa2, 0x1b,
|
||||
0x84, 0xa2, 0x89, 0x58, 0xfc, 0x4f, 0x3f, 0x40, 0x90, 0x4c, 0xa3, 0x01, 0x32, 0x09, 0x02, 0x80,
|
||||
0x9c, 0x91, 0x13, 0x2c, 0xba, 0xde, 0x5d, 0x99, 0xf2, 0xff, 0xff, 0x3d, 0x5a, 0x1f, 0xa9, 0x02,
|
||||
0x90, 0x8f, 0xf3, 0x08, 0xbd, 0x01, 0xf8, 0xd0, 0x2a, 0x95, 0x41, 0x0c, 0x40, 0x0a, 0x20, 0xc4,
|
||||
0xd4, 0xcc, 0x6b, 0x0f, 0xf0, 0x80, 0xb1, 0x5d, 0x28, 0x3d, 0x08, 0xc2, 0xf8, 0x31, 0x02, 0x49,
|
||||
0x88, 0x14, 0x28, 0xed, 0xe8, 0x86, 0x3b, 0x00, 0x9f, 0x95, 0x06, 0x37, 0x15, 0xa4, 0x59, 0xc8,
|
||||
0x80, 0xb6, 0x10, 0xf0, 0xe5, 0xb8, 0x18, 0x00, 0x56, 0x1c, 0xff, 0x95, 0x21, 0x0e, 0x7f, 0x2b,
|
||||
0xc5, 0x08, 0x59, 0x10, 0xe1, 0x46, 0x31, 0x8d, 0xec, 0xe0, 0xa1, 0x99, 0xbb, 0x21, 0xff, 0xfe,
|
||||
0x30, 0x10, 0xd0, 0x05, 0xe3, 0x08, 0x50, 0xfc, 0xf3, 0x0e, 0x00, 0x8d, 0x68, 0x8e, 0x07, 0xa6,
|
||||
0x80, 0x34, 0x42, 0xed, 0x1f, 0x88, 0x00, 0xf0, 0x8a, 0x21, 0xae, 0xf7, 0xfb, 0x80, 0x28, 0x86,
|
||||
0x0f, 0xff, 0xff, 0x82, 0xea, 0x47, 0x95, 0x91, 0xe0, 0x04, 0x01, 0x44, 0x0c, 0x29, 0xff, 0x0e,
|
||||
0x33, 0xe8, 0xc0, 0x54, 0x04, 0x23, 0xfc, 0x81, 0x5b, 0xf0, 0x3c, 0x07, 0x10, 0x70, 0x30, 0xd8,
|
||||
0x21, 0x6f, 0xef, 0xde, 0x46, 0x09, 0x43, 0xfa, 0x5f, 0xff, 0x0d, 0x72, 0x30, 0xdd, 0x00, 0xdb,
|
||||
0xe4, 0x48, 0x24, 0x97, 0x08, 0x46, 0xb1, 0x49, 0xc4, 0x4d, 0x80, 0x12, 0x60, 0xff, 0xa4, 0xa6,
|
||||
0xff, 0xf6, 0x8c, 0x00, 0x40, 0x05, 0x02, 0xb4, 0x0f, 0xf0, 0x3e, 0xfc, 0x84, 0x38, 0x81, 0x94,
|
||||
0x8b, 0xfe, 0x49, 0xef, 0xc0, 0x10, 0x49, 0x88, 0x28, 0xa2, 0x1c, 0x2a, 0x8b, 0x64, 0xd4, 0x86,
|
||||
0xd7, 0xff, 0xff, 0xff, 0xeb, 0x91, 0x6b, 0x11, 0x10, 0x00, 0x69, 0x4c, 0xbf, 0xb4, 0x1c, 0xd8,
|
||||
0x00, 0x07, 0x16, 0x80, 0x60, 0x0a, 0x1c, 0x82, 0x42, 0x27, 0x82, 0x43, 0xc9, 0x0a, 0x64, 0x20,
|
||||
0x5a, 0x5f, 0x4e, 0xbf, 0x8c, 0x38, 0x82, 0x36, 0x02, 0x07, 0x72, 0x79, 0x07, 0x23, 0xb4, 0xbb,
|
||||
0x57, 0x5f, 0xe8, 0x04, 0xdd, 0x39, 0xe9, 0x07, 0x95, 0xbe, 0x04, 0x2b, 0xdd, 0x8e, 0x22, 0xdc,
|
||||
0x14, 0x2c, 0x61, 0xa3, 0xa9, 0xcd, 0x4f, 0x82, 0x5d, 0xa0, 0x44, 0xdf, 0xf4, 0x96, 0xff, 0xf5,
|
||||
0x2b, 0xff, 0xfe, 0x01, 0x19, 0xd2, 0xa2, 0x9e, 0x43, 0xa5, 0x7f, 0xf0, 0x4c, 0x4c, 0x2b, 0x3c,
|
||||
0x33, 0xe2, 0x55, 0xff, 0x04, 0x06, 0x29, 0x2c, 0x0d, 0x22, 0x5d, 0x7c, 0x93, 0xba, 0x18, 0xaf,
|
||||
0xf9, 0x32, 0xa6, 0xc3, 0x99, 0x46, 0x79, 0xe3, 0x06, 0xa6, 0x38, 0x8b, 0x92, 0x22, 0x4b, 0xdb,
|
||||
0x1b, 0x36, 0x20, 0xb0, 0x6c, 0x20, 0xce, 0x37, 0x42, 0xe1, 0x66, 0xd4, 0x49, 0x34, 0x42, 0x8b,
|
||||
0xfa, 0x9c, 0x12, 0x99, 0xdc, 0x06, 0x87, 0xfa, 0x46, 0xf8, 0x2f, 0x04, 0xa9, 0xd8, 0x82, 0x07,
|
||||
0xa6, 0x30, 0x0f, 0xc0, 0xdf, 0x35, 0xe8, 0x90, 0xf0, 0xff, 0xff, 0xa8, 0xe0, 0xd7, 0x02, 0x60,
|
||||
0x1a, 0xc3, 0x20, 0x28, 0xa2, 0x31, 0x29, 0x3c, 0xeb, 0x04, 0xa5, 0xdd, 0x48, 0x0e, 0x82, 0xa4,
|
||||
0xb6, 0x56, 0x22, 0x06, 0x57, 0xe0, 0xda, 0x10, 0x27, 0x31, 0x0e, 0x11, 0x77, 0xfe, 0x02, 0x60,
|
||||
0x16, 0x48, 0x81, 0x8c, 0x0d, 0x05, 0x17, 0x7f, 0xcb, 0xbb, 0x7e, 0x25, 0x2a, 0x41, 0xfd, 0x8a,
|
||||
0x7f, 0xc9, 0x36, 0x7c, 0xe0, 0x98, 0x7e, 0x92, 0xef, 0x7e, 0x06, 0x03, 0x13, 0x3e, 0x20, 0x3a,
|
||||
0xbf, 0x4c, 0xc3, 0x0f, 0x2e, 0x80, 0x74, 0xbf, 0x39, 0x3c, 0xf0, 0xa6, 0xb2, 0xe9, 0x3f, 0x41,
|
||||
0x55, 0x1f, 0x2c, 0xf5, 0xd2, 0x7e, 0x8c, 0xae, 0x4e, 0xaa, 0x61, 0x3c, 0xbc, 0x3f, 0xc4, 0xc7,
|
||||
0x36, 0xdc, 0x23, 0xc8, 0xb8, 0x52, 0xe2, 0x8a, 0x80, 0x18, 0x00, 0x00, 0xb2, 0x46, 0xa2, 0x56,
|
||||
0x0d, 0x12, 0x94, 0xaa, 0xbd, 0x01, 0x07, 0xff, 0xfa, 0x34, 0x0c, 0x5f, 0xf8, 0x0c, 0x12, 0x50,
|
||||
0xaf, 0xd6, 0xd1, 0x89, 0x40, 0xa4, 0xff, 0xe0, 0xce, 0xc4, 0x49, 0x25, 0x9d, 0xc1, 0xff, 0x7e,
|
||||
0x60, 0x24, 0x5d, 0xcc, 0x10, 0xc0, 0xbe, 0x5a, 0x12, 0xd3, 0xc3, 0xfe, 0x2d, 0x40, 0x7c, 0x28,
|
||||
0x9e, 0x71, 0x01, 0xd2, 0x6e, 0x86, 0x0b, 0xc8, 0xf2, 0x9b, 0x45, 0x08, 0x4c, 0x04, 0x52, 0x7e,
|
||||
0xf2, 0x7e, 0xd9, 0xcc, 0x0b, 0x1c, 0x20, 0x80, 0xae, 0xaf, 0xfe, 0xb0, 0x6d, 0x23, 0xf2, 0x41,
|
||||
0xe3, 0x2e, 0x20, 0x11, 0x4b, 0x74, 0x89, 0xdd, 0xff, 0xa8, 0x38, 0xa3, 0x95, 0x82, 0x15, 0xf0,
|
||||
0xd0, 0xd5, 0xf1, 0x92, 0x8e, 0xee, 0xc0, 0x26, 0x81, 0xe9, 0x47, 0xff, 0xee, 0x0d, 0x20, 0x34,
|
||||
0x31, 0x3a, 0xef, 0x40, 0xb2, 0x29, 0x47, 0x19, 0x7f, 0x04, 0x27, 0xf1, 0x90, 0x85, 0x09, 0x86,
|
||||
0x7d, 0x42, 0xe2, 0x54, 0x5d, 0x5f, 0xe8, 0x0e, 0xd0, 0x2c, 0xaa, 0x16, 0xbf, 0x04, 0xa7, 0xf8,
|
||||
0xa2, 0x46, 0x0b, 0x08, 0x7a, 0x79, 0xe9, 0x28, 0x62, 0x7c, 0x33, 0xf4, 0x0b, 0x14, 0x82, 0xfa,
|
||||
0x61, 0xeb, 0xc1, 0xff, 0x4c, 0xa4, 0x11, 0x7f, 0x03, 0x68, 0x44, 0xc1, 0x1f, 0x81, 0x3a, 0x6c,
|
||||
0x77, 0x95, 0x02, 0x2b, 0x53, 0x80, 0xe5, 0x10, 0x1e, 0x90, 0xe8, 0xfd, 0x1f, 0xa6, 0x40, 0x0b,
|
||||
0x13, 0xff, 0x4e, 0x4d, 0x7f, 0x52, 0xe8, 0xaf, 0x9a, 0xc1, 0x80, 0x0f, 0x0a, 0x14, 0x02, 0x3c,
|
||||
0xc0, 0x09, 0x13, 0xe7, 0xdc, 0xc0, 0x1a, 0x28, 0xa0, 0xe4, 0x83, 0x8e, 0x03, 0x88, 0xd5, 0xaf,
|
||||
0x1a, 0xbd, 0x91, 0x00, 0xb7, 0x4e, 0xba, 0xdf, 0xf8, 0xdb, 0xcc, 0x02, 0x43, 0xc4, 0x14, 0x2a,
|
||||
0x3f, 0xc8, 0x0d, 0x09, 0x1c, 0x44, 0xf4, 0x01, 0x3c, 0xca, 0x28, 0x56, 0x80, 0xa6, 0x85, 0x00,
|
||||
0xea, 0x3e, 0x8f, 0xeb, 0x9f, 0xfc, 0x6e, 0x07, 0xc4, 0xe0, 0x30, 0x78, 0xa0, 0x1e, 0x6f, 0x54,
|
||||
0x78, 0x51, 0xff, 0x56, 0x4a, 0x01, 0x47, 0x02, 0x4c, 0x21, 0x3b, 0xfb, 0x90, 0x0a, 0xcc, 0x1d,
|
||||
0xd2, 0x47, 0xff, 0xfc, 0x70, 0x18, 0x22, 0xc0, 0xb9, 0x2f, 0xe9, 0x7f, 0x91, 0xd3, 0x66, 0x2f,
|
||||
0x80, 0x2c, 0x24, 0xa7, 0xfa, 0x84, 0x51, 0xab, 0x6b, 0x72, 0x00, 0xab, 0x33, 0x04, 0xcf, 0x43,
|
||||
0xff, 0x17, 0x51, 0x84, 0x0c, 0x01, 0x50, 0x10, 0x8f, 0x90, 0x34, 0x41, 0x44, 0x84, 0x8e, 0x08,
|
||||
0x19, 0x04, 0x48, 0x50, 0x84, 0x38, 0x3d, 0x02, 0x52, 0xf9, 0x7c, 0xd2, 0xd0, 0x1f, 0x13, 0x42,
|
||||
0xa0, 0x21, 0x41, 0xc4, 0x02, 0x02, 0x3d, 0x09, 0xc8, 0xfd, 0x60, 0x7d, 0x35, 0x4f, 0x7f, 0xff,
|
||||
0xf9, 0x97, 0x6a, 0xd8, 0x00, 0xc3, 0x83, 0x00, 0x09, 0x50, 0x4b, 0x90, 0x8a, 0xc7, 0x94, 0x4d,
|
||||
0x47, 0xc1, 0x62, 0x32, 0x28, 0x24, 0x09, 0x52, 0x2e, 0x2e, 0x1c, 0x96, 0x44, 0xa0, 0x09, 0xc8,
|
||||
0xce, 0x64, 0xa9, 0x1c, 0x19, 0x0e, 0x52, 0x3e, 0x3e, 0x19, 0x93, 0xa0, 0x36, 0x26, 0x22, 0x08,
|
||||
0x9a, 0x00, 0xdd, 0x66, 0x3a, 0x93, 0xd5, 0x89, 0xd1, 0x40, 0x06, 0xd4, 0xa8, 0x22, 0x73, 0x7b,
|
||||
0x3d, 0x3f, 0xe3, 0x04, 0x94, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x56, 0x77, 0xac, 0xe0, 0xc4, 0x06,
|
||||
0x1f, 0xb8, 0xa5, 0x80, 0xfd, 0x68, 0x1c, 0x32, 0x16, 0x03, 0xde, 0x71, 0x2a, 0x3d, 0x14, 0x19,
|
||||
0xbe, 0xc2, 0x88, 0xd9, 0x24, 0x92, 0x5f, 0xc5, 0x90, 0x0a, 0x85, 0xc2, 0x3f, 0x87, 0x03, 0xa8,
|
||||
0x26, 0x17, 0xc4, 0x06, 0x86, 0x12, 0x87, 0x76, 0x0a, 0x48, 0x16, 0xed, 0x96, 0x93, 0xec, 0x1b,
|
||||
0x30, 0x73, 0xe8, 0x1a, 0x3f, 0xff, 0x4d, 0xce, 0x40, 0xf3, 0x0c, 0x51, 0x4b, 0x84, 0x9e, 0x67,
|
||||
0x2b, 0x15, 0x40, 0x1a, 0xa0, 0xfc, 0x10, 0x0f, 0xd8, 0x81, 0x35, 0x87, 0xff, 0x98, 0x0f, 0x40,
|
||||
0x00, 0xba, 0xc0, 0x71, 0xe2, 0x00, 0x18, 0x28, 0xb3, 0x82, 0xcc, 0x80, 0x6a, 0xa0, 0x43, 0xff,
|
||||
0x2d, 0xd6, 0x04, 0x8a, 0x68, 0xff, 0xff, 0xff, 0xfc, 0x1a, 0xf3, 0x1a, 0x2a, 0x06, 0xc0, 0x01,
|
||||
0x40, 0x0c, 0x30, 0xc1, 0xd0, 0xd7, 0x4f, 0xcb, 0x74, 0x1f, 0x07, 0xd3, 0xb4, 0x0d, 0x88, 0x98,
|
||||
0xea, 0xda, 0x9f, 0xce, 0x2b, 0x3c, 0x55, 0xb3, 0x40, 0x14, 0xff, 0xff, 0xff, 0xea, 0xdb, 0x9b,
|
||||
0x92, 0xd8, 0x68, 0x08, 0x0b, 0x41, 0x09, 0x26, 0x40, 0x8c, 0xf1, 0xb0, 0x9a, 0x98, 0xc0, 0x80,
|
||||
0x8b, 0xf0, 0x3d, 0xe7, 0xec, 0x19, 0x68, 0x21, 0x03, 0x29, 0x7f, 0xe1, 0x6d, 0x4c, 0x0f, 0x01,
|
||||
0xd1, 0x51, 0x01, 0x1a, 0x50, 0x2a, 0x59, 0x27, 0x80, 0xc1, 0x6e, 0x33, 0xf1, 0x80, 0xe1, 0x49,
|
||||
0x08, 0xe9, 0x17, 0xff, 0xff, 0xff, 0x80, 0x5a, 0x10, 0x10, 0x36, 0x5e, 0xca, 0xf8, 0x3a, 0x00,
|
||||
0x1e, 0xb0, 0x06, 0x84, 0x01, 0xf3, 0x07, 0x1b, 0x4a, 0xc0, 0x1e, 0x21, 0x43, 0x8e, 0xa5, 0x55,
|
||||
0x77, 0xc7, 0x65, 0x7c, 0xc2, 0xdf, 0x5e, 0x0c, 0x42, 0x20, 0xd2, 0x48, 0x61, 0xc8, 0x1c, 0x65,
|
||||
0xf8, 0xfe, 0x4c, 0x88, 0x71, 0x1f, 0x82, 0x50, 0x81, 0xa3, 0x54, 0x09, 0x13, 0x28, 0x52, 0xf5,
|
||||
0xe0, 0x82, 0xc3, 0x06, 0x7f, 0xfa, 0x2c, 0xcf, 0xf8, 0xf4, 0x7f, 0xff, 0xfd, 0x01, 0x49, 0xa4,
|
||||
0xb8, 0xde, 0x62, 0x84, 0xfe, 0xed, 0x65, 0x1f, 0x3c, 0x3c, 0xb2, 0x50, 0x76, 0x30, 0x5b, 0x03,
|
||||
0xc0, 0x08, 0xa6, 0x64, 0x90, 0xc8, 0xcd, 0x14, 0x6e, 0x69, 0x46, 0x7a, 0xc6, 0x1c, 0x87, 0xd7,
|
||||
0x48, 0x7b, 0x49, 0x05, 0x2d, 0x5e, 0x7f, 0xcb, 0x67, 0xf0, 0xd9, 0x0d, 0x1e, 0x9e, 0x53, 0xb7,
|
||||
0x64, 0xa5, 0xa5, 0x10, 0x39, 0x06, 0x11, 0x3f, 0xb1, 0xa9, 0xa6, 0xe8, 0x4d, 0x47, 0x77, 0xda,
|
||||
0x43, 0x76, 0x89, 0x45, 0x09, 0x70, 0xc2, 0x38, 0x0f, 0x09, 0x6f, 0xe7, 0x2d, 0x82, 0x35, 0x07,
|
||||
0xfe, 0x64, 0x18, 0x2e, 0xb8, 0x04, 0x42, 0x54, 0x80, 0x43, 0x12, 0x6c, 0x9a, 0x55, 0xc9, 0x0a,
|
||||
0xa0, 0x79, 0x47, 0x52, 0x65, 0x2a, 0xff, 0x50, 0x11, 0xc9, 0x4e, 0xfe, 0x5b, 0x30, 0xa4, 0xe8,
|
||||
0x30, 0x63, 0xff, 0x21, 0x12, 0x1b, 0xdc, 0x1c, 0x01, 0x41, 0x51, 0x1f, 0xff, 0xfa, 0xc3, 0xe3,
|
||||
0x55, 0xf1, 0x66, 0xe2, 0xd5, 0x78, 0x5e, 0xfa, 0x4d, 0xf2, 0x61, 0x01, 0x26, 0x15, 0xa9, 0xf9,
|
||||
0xd9, 0x32, 0x41, 0x90, 0x36, 0x4e, 0xae, 0xe3, 0x0b, 0x16, 0x56, 0x8c, 0x6e, 0x42, 0x5d, 0xd8,
|
||||
0x1e, 0xfe, 0x1d, 0x40, 0x3a, 0x50, 0x9f, 0x09, 0x14, 0xeb, 0x6e, 0x48, 0x7a, 0x91, 0x88, 0x7b,
|
||||
0x7d, 0x8f, 0x72, 0x42, 0x39, 0xb0, 0x1c, 0x65, 0x18, 0x23, 0x8b, 0x60, 0x30, 0x00,
|
||||
|
||||
/* FRAME_END as in 4.2.3 */
|
||||
0xc5, 0xcc, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00
|
||||
};
|
||||
|
||||
static UINT32 srefImage
|
||||
[] = { /* 4.2.4.4 Inverse Color Conversion */
|
||||
0x00229cdf, 0x00249de0, 0x00259fe2, 0x002ca5e8, 0x00229cdf, 0x00229ce0, 0x00239de0,
|
||||
0x00229ce0, 0x00229cdf, 0x00229cdf, 0x00239ce0, 0x00249ce0, 0x00249ce0, 0x00219ce3,
|
||||
0x001e9ce6, 0x00209ae2, 0x002299dd, 0x002199de, 0x00209adf, 0x00209ae0, 0x001f9be0,
|
||||
0x001e9ae0, 0x001d99e0, 0x001c98e0, 0x001b97df, 0x001e96dc, 0x002194d9, 0x001f93dd,
|
||||
0x001d93e0, 0x001b94dc, 0x001895d8, 0x001c92db, 0x00208fde, 0x001b91de, 0x001693df,
|
||||
0x001793df, 0x001992df, 0x001891df, 0x00178fdf, 0x00178edf, 0x00168dde, 0x00158cdd,
|
||||
0x00148cdc, 0x00128cda, 0x00118cd9, 0x00118bd9, 0x00128ada, 0x001289da, 0x001288db,
|
||||
0x001187da, 0x001186da, 0x001085da, 0x000f85d9, 0x000f84d9, 0x000e83d9, 0x000d82d8,
|
||||
0x000d82d8, 0x000d81d8, 0x000d80d7, 0x000d7fd7, 0x000d7ed6, 0x000d7ed6, 0x000d7ed6,
|
||||
0x000d7ed6, 0x00259fe1, 0x0027a1e2, 0x0029a2e3, 0x002ba4e6, 0x00249fe1, 0x00249fe1,
|
||||
0x00249fe1, 0x00249ee1, 0x00239ee1, 0x00249ee1, 0x00249ee1, 0x00259de1, 0x00259de2,
|
||||
0x00249de2, 0x00229de2, 0x00229ce1, 0x00229bdf, 0x00219ce0, 0x00209ce1, 0x00209ce2,
|
||||
0x00209ce2, 0x00209ae0, 0x002199de, 0x001f99df, 0x001d98e0, 0x001e97e0, 0x001f97e0,
|
||||
0x001d96df, 0x001c95de, 0x001c94e0, 0x001c94e1, 0x001d93e1, 0x001d92e0, 0x001b93de,
|
||||
0x001a94dc, 0x001a93de, 0x001a93e0, 0x001992e0, 0x001891df, 0x00188fdf, 0x00178edf,
|
||||
0x00168ede, 0x00158edd, 0x00148ddc, 0x00138ddb, 0x00138cdb, 0x00138bdb, 0x00128adb,
|
||||
0x001289db, 0x001288db, 0x001187db, 0x001186db, 0x001085db, 0x000f84da, 0x000e83d9,
|
||||
0x000e83d9, 0x000e83d9, 0x000e82d9, 0x000e81d8, 0x000e80d8, 0x000d7fd7, 0x000d7fd7,
|
||||
0x000d7fd7, 0x000d7fd7, 0x0027a3e3, 0x002aa4e3, 0x002ea6e3, 0x002aa4e3, 0x0026a2e3,
|
||||
0x0026a1e3, 0x0025a1e3, 0x0025a0e3, 0x0025a0e3, 0x0025a0e3, 0x00259fe3, 0x00269fe3,
|
||||
0x00269ee4, 0x00279ee1, 0x00279edf, 0x00259ee0, 0x00239ee1, 0x00219ee2, 0x00209ee4,
|
||||
0x00209de4, 0x00219de3, 0x00229be0, 0x002499dc, 0x002299de, 0x001f98e0, 0x001d99e4,
|
||||
0x001b9ae7, 0x001c98e2, 0x001c96dc, 0x001e94e3, 0x002092ea, 0x001d94e6, 0x001a96e2,
|
||||
0x001c96de, 0x001d95da, 0x001c94de, 0x001b94e1, 0x001a93e0, 0x001a92e0, 0x001991e0,
|
||||
0x001890e0, 0x001790df, 0x00178fde, 0x00168fde, 0x00158edd, 0x00148ddd, 0x00138cdc,
|
||||
0x00138bdc, 0x00128adc, 0x001289dc, 0x001188dc, 0x001187dd, 0x001086dd, 0x000f85db,
|
||||
0x000e83d9, 0x000e84da, 0x000f84da, 0x000e83da, 0x000e82d9, 0x000e81d9, 0x000e80d8,
|
||||
0x000e80d8, 0x000e80d8, 0x000e80d8, 0x002aa7e5, 0x002da7e4, 0x0031a8e3, 0x002ca6e3,
|
||||
0x0027a4e4, 0x0027a3e4, 0x0027a3e4, 0x0027a3e4, 0x0026a2e4, 0x0026a2e4, 0x0027a1e5,
|
||||
0x0027a0e5, 0x0027a0e6, 0x0026a0e5, 0x0025a0e4, 0x00259fe4, 0x00259ee3, 0x00239ee5,
|
||||
0x00229fe6, 0x00229fe5, 0x00229fe4, 0x0013a5e6, 0x001b9fe8, 0x0016a0e8, 0x0011a0e7,
|
||||
0x00129fef, 0x00139ef7, 0x001b99ec, 0x00179ae2, 0x00149ce4, 0x001d98e5, 0x001c97e6,
|
||||
0x001b96e7, 0x001c98dc, 0x001d97df, 0x001c96e1, 0x001c94e2, 0x001b94e1, 0x001b93e1,
|
||||
0x001a93e0, 0x001a92e0, 0x001991e0, 0x001890e0, 0x001790df, 0x00168fdf, 0x00158ede,
|
||||
0x00158dde, 0x00148cdd, 0x00138bdc, 0x00128add, 0x001289dd, 0x001188de, 0x001187de,
|
||||
0x000f85dc, 0x000d83da, 0x000f85db, 0x001086db, 0x000f84db, 0x000f83da, 0x000e82da,
|
||||
0x000e81da, 0x000e81da, 0x000e81da, 0x000e81da, 0x002caae7, 0x0030aae5, 0x0034abe3,
|
||||
0x002ea8e4, 0x0029a6e5, 0x0028a6e5, 0x0028a5e5, 0x0028a5e5, 0x0028a5e6, 0x0028a4e6,
|
||||
0x0028a3e7, 0x0028a2e7, 0x0028a1e8, 0x0025a2e9, 0x0023a3ea, 0x0025a0e8, 0x00279ee6,
|
||||
0x00259fe7, 0x0023a0e9, 0x0018a4f5, 0x000ea7ff, 0x001ba6de, 0x00558ebb, 0x006f839c,
|
||||
0x0089797e, 0x008d797c, 0x00917979, 0x007f7b94, 0x005687af, 0x00229bd6, 0x0004a4fd,
|
||||
0x00109df4, 0x001c97eb, 0x001c9ada, 0x001c98e4, 0x001c97e3, 0x001d95e2, 0x001c95e2,
|
||||
0x001c94e2, 0x001c94e1, 0x001b94e1, 0x001a93e1, 0x001a92e1, 0x001991e1, 0x001890e1,
|
||||
0x00178fe0, 0x00158edf, 0x00148dde, 0x00138cdd, 0x00128bde, 0x00128adf, 0x001289df,
|
||||
0x001188e0, 0x000f85dd, 0x000d83da, 0x000f85db, 0x001187dd, 0x001086dc, 0x000f84dc,
|
||||
0x000e83db, 0x000e81db, 0x000e81db, 0x000e81db, 0x000e81db, 0x0030abe5, 0x0036afe8,
|
||||
0x0034abe4, 0x002faae5, 0x002ba8e6, 0x0036aee8, 0x0026a6e8, 0x0029a7e7, 0x002ca8e7,
|
||||
0x002da7e6, 0x002fa5e5, 0x002ca5e7, 0x0029a4e9, 0x002ba5e5, 0x002ca5e2, 0x0010aaef,
|
||||
0x0013adf6, 0x0023a3f8, 0x006091a5, 0x00a6755d, 0x00ec5915, 0x00ff490c, 0x00fa5504,
|
||||
0x00ff590f, 0x00ff5d1b, 0x00ff6116, 0x00fa6412, 0x00ff550f, 0x00ff4b0d, 0x00fb4918,
|
||||
0x00f54823, 0x008e737e, 0x00269eda, 0x0006a2ff, 0x001d97e2, 0x001799ea, 0x001c97e4,
|
||||
0x001a98e4, 0x001898e4, 0x001a96e3, 0x001b95e3, 0x001a94e2, 0x001a93e0, 0x001992e1,
|
||||
0x001891e2, 0x001790e1, 0x00168fe0, 0x00158fdf, 0x00138ede, 0x00138ddf, 0x00138ce0,
|
||||
0x00128be0, 0x001189e0, 0x001087de, 0x000f85db, 0x00138ae0, 0x000f87dc, 0x000f86dc,
|
||||
0x000f85dc, 0x000f84dc, 0x000e83db, 0x000e83db, 0x000e83db, 0x000e83db, 0x0034abe2,
|
||||
0x003cb4ec, 0x0034ace5, 0x0031abe6, 0x002daae8, 0x0044b6eb, 0x0024a7ea, 0x0029aaea,
|
||||
0x002face9, 0x0032a9e6, 0x0035a7e3, 0x0030a7e6, 0x002ba8ea, 0x0025aaf0, 0x0020adf6,
|
||||
0x004d8ba7, 0x00b8674c, 0x00ff5510, 0x00f7650c, 0x00f86313, 0x00fa611b, 0x00f0671f,
|
||||
0x00fc6222, 0x00fb6926, 0x00f96f29, 0x00f67122, 0x00f3721b, 0x00f26b20, 0x00f16424,
|
||||
0x00ff5622, 0x00ff531f, 0x00ff4b17, 0x00ff440e, 0x00b1615b, 0x001f95e0, 0x00129bf0,
|
||||
0x001c9ae5, 0x00189ae6, 0x00159be7, 0x001898e6, 0x001b95e5, 0x001b95e2, 0x001995e0,
|
||||
0x001994e1, 0x001892e2, 0x001792e1, 0x001691e0, 0x001590df, 0x00148fdf, 0x00148fe0,
|
||||
0x00148fe1, 0x00128de1, 0x00108be0, 0x001189de, 0x001186dd, 0x00178fe4, 0x000e87db,
|
||||
0x000e87dc, 0x000f87dd, 0x000f85dc, 0x000e84dc, 0x000e84dc, 0x000e84dc, 0x000e84dc,
|
||||
0x0036b1eb, 0x0036b4f0, 0x002eafed, 0x002caeec, 0x002aadec, 0x0041b4ef, 0x0029abe9,
|
||||
0x002cabe8, 0x002fabe7, 0x0031abe6, 0x0032aae6, 0x002faae7, 0x002ca9e8, 0x0025a7eb,
|
||||
0x00946a5f, 0x00ff3e06, 0x00f95618, 0x00e27312, 0x00f87329, 0x00f77427, 0x00f77626,
|
||||
0x00f27628, 0x00f8712b, 0x00f9772e, 0x00f97e30, 0x00f77f2e, 0x00f5812b, 0x00f57b2c,
|
||||
0x00f5752d, 0x00fd6a2b, 0x00fb652a, 0x00f65e2c, 0x00f1572e, 0x00ff4810, 0x00ff460f,
|
||||
0x00817680, 0x0002a7f1, 0x002496ea, 0x00199be4, 0x001b98e4, 0x001d96e5, 0x001b96e2,
|
||||
0x001a96e0, 0x001995e1, 0x001794e3, 0x001793e2, 0x001692e1, 0x001691e0, 0x001590df,
|
||||
0x001591e1, 0x001591e3, 0x00138fe1, 0x00108ce0, 0x00128be0, 0x00158ae0, 0x00168de2,
|
||||
0x000f89dd, 0x000f88dd, 0x000f88dd, 0x000f86dd, 0x000f85dc, 0x000f85dc, 0x000f85dc,
|
||||
0x000f85dc, 0x005fc1e7, 0x0057bee8, 0x004fbbe9, 0x004ebae6, 0x004ebae3, 0x0051b6ee,
|
||||
0x002eaee8, 0x002eade6, 0x002fabe5, 0x002face7, 0x002eade9, 0x002eace7, 0x002daae5,
|
||||
0x0015b2ff, 0x00ec4310, 0x00f15016, 0x00f75d1c, 0x00f87123, 0x00f9862a, 0x00f6882d,
|
||||
0x00f48b31, 0x00f48532, 0x00f47f33, 0x00f78535, 0x00fa8c37, 0x00f88e39, 0x00f7903a,
|
||||
0x00f88b38, 0x00f98635, 0x00f87e35, 0x00f77635, 0x00f76d34, 0x00f76532, 0x00f85e31,
|
||||
0x00f95730, 0x00ff5125, 0x00f65237, 0x0003a5fd, 0x001e9be1, 0x001e98e3, 0x001f96e5,
|
||||
0x001c97e2, 0x001a97df, 0x001896e1, 0x001795e4, 0x001794e3, 0x001793e2, 0x001692e1,
|
||||
0x001692e0, 0x001693e2, 0x001794e4, 0x001391e2, 0x000f8ee0, 0x00148ee1, 0x00198ee3,
|
||||
0x00148ce1, 0x000f8bde, 0x000f8ade, 0x000f89de, 0x000f88dd, 0x000f86dd, 0x000f86dd,
|
||||
0x000f86dd, 0x000f86dd, 0x003cb6ee, 0x0036b4ef, 0x0030b2f0, 0x0030b1ee, 0x002fb1ec,
|
||||
0x0038b0ef, 0x002eaee9, 0x002faee8, 0x0031ade6, 0x002fafe8, 0x002eb1ea, 0x0031adec,
|
||||
0x0029afee, 0x0030aac8, 0x00ff3d05, 0x00fa501a, 0x00f96021, 0x00f87428, 0x00f7882f,
|
||||
0x00fa9638, 0x00f59b38, 0x00f5973b, 0x00f6923e, 0x00f89440, 0x00fa9742, 0x00fa9a44,
|
||||
0x00fa9d46, 0x00f99845, 0x00f89444, 0x00f98d43, 0x00fa8641, 0x00f97d3f, 0x00f9743d,
|
||||
0x00f77039, 0x00f56d35, 0x00ff6122, 0x00bf6c63, 0x00129eef, 0x00229ae8, 0x001c99ed,
|
||||
0x00179ce4, 0x001498f0, 0x001b94e1, 0x001a96e2, 0x001998e3, 0x001897e4, 0x001896e5,
|
||||
0x001895e4, 0x001993e2, 0x001792e1, 0x001590df, 0x001692e2, 0x001793e5, 0x001490e4,
|
||||
0x00128ee2, 0x00118de3, 0x00108de3, 0x00118bde, 0x001289d9, 0x000f88e2, 0x000c89dd,
|
||||
0x001085e0, 0x000987e4, 0x000987e4, 0x0040b5e9, 0x003bb4e9, 0x0037b2ea, 0x0037b2e9,
|
||||
0x0038b1e8, 0x0033b0ea, 0x002eaeeb, 0x0030afe9, 0x0033afe8, 0x0030b2ea, 0x002eb5ec,
|
||||
0x0034aff2, 0x0025b4f7, 0x008d7f86, 0x00f64f00, 0x00ed5c1e, 0x00fa6326, 0x00f7762d,
|
||||
0x00f58a35, 0x00fea242, 0x00f7ab3f, 0x00f7a843, 0x00f7a548, 0x00f9a34a, 0x00faa24c,
|
||||
0x00fba64f, 0x00fcaa52, 0x00f9a652, 0x00f7a252, 0x00fa9c50, 0x00fd974e, 0x00fc8d4b,
|
||||
0x00fb8348, 0x00f68341, 0x00f1823a, 0x00f5732c, 0x00718cac, 0x00179af0, 0x002599ef,
|
||||
0x002697e9, 0x00269bc6, 0x001696f1, 0x001d91e3, 0x001c96e3, 0x001b9be3, 0x001a99e6,
|
||||
0x001998e9, 0x001b97e7, 0x001c95e5, 0x001891df, 0x00138dda, 0x001992e2, 0x001e98ea,
|
||||
0x001592e6, 0x000b8de2, 0x000e8ee5, 0x00108fe9, 0x00128cdf, 0x001489d4, 0x000e88e6,
|
||||
0x00088cdc, 0x001184e4, 0x000488ec, 0x000488ec, 0x003eb6ea, 0x003bb5eb, 0x0038b4eb,
|
||||
0x0038b4eb, 0x0038b3eb, 0x0035b2eb, 0x0033b1ec, 0x0034b1eb, 0x0035b1ea, 0x0032b3e9,
|
||||
0x0030b5e9, 0x0034b0f0, 0x0023b6f8, 0x00c56044, 0x00f9540c, 0x00f26322, 0x00f77029,
|
||||
0x00f77d2f, 0x00f78b35, 0x00fba142, 0x00f6b046, 0x00fbb44f, 0x00f7b051, 0x00f9af54,
|
||||
0x00fbad56, 0x00fcb25a, 0x00feb75d, 0x00fab35f, 0x00f6b061, 0x00faac5d, 0x00fda95a,
|
||||
0x00fb9f55, 0x00f99551, 0x00f7914b, 0x00f68d45, 0x00ff7e23, 0x001ba5f0, 0x00129ef4,
|
||||
0x002896f1, 0x00239fb1, 0x006c9600, 0x003c9c82, 0x00179ef8, 0x00169cf4, 0x00149de3,
|
||||
0x00169ae5, 0x001897e7, 0x001995e6, 0x001a93e5, 0x001993e3, 0x001793e0, 0x001c98e6,
|
||||
0x001a95e5, 0x001692e5, 0x00138fe5, 0x00138ceb, 0x00138be3, 0x000087e4, 0x00007cf5,
|
||||
0x001a86d3, 0x000d8cf1, 0x00008fe2, 0x000d85ea, 0x000886f1, 0x003cb7ec, 0x003bb7ed,
|
||||
0x003ab6ed, 0x0039b6ed, 0x0038b5ed, 0x0037b5ed, 0x0037b4ed, 0x0037b3ed, 0x0036b3ec,
|
||||
0x0034b4e9, 0x0031b5e5, 0x0035b1ef, 0x0021b8fa, 0x00fd4203, 0x00fc581e, 0x00f86a26,
|
||||
0x00f47c2d, 0x00f78431, 0x00f98c36, 0x00f8a041, 0x00f6b54d, 0x00fec05b, 0x00f6bc5a,
|
||||
0x00f8ba5d, 0x00fbb861, 0x00fdbe65, 0x00ffc469, 0x00fbc16c, 0x00f5bd70, 0x00fabc6b,
|
||||
0x00febb66, 0x00fab160, 0x00f6a75a, 0x00f89f55, 0x00fa984f, 0x00df956f, 0x0008a6fc,
|
||||
0x00259ddb, 0x00159ff3, 0x004aa172, 0x0069a90d, 0x0062a406, 0x005a981b, 0x0034969b,
|
||||
0x000e99ff, 0x001297f2, 0x001695e4, 0x001793e5, 0x001892e5, 0x001995e6, 0x001a98e7,
|
||||
0x00209deb, 0x001593df, 0x001892e4, 0x001a91e9, 0x002095eb, 0x00259dd1, 0x00d0f772,
|
||||
0x00c1f396, 0x000083f1, 0x001782a0, 0x003c7e2f, 0x001787cc, 0x000b8ada, 0x003db9ed,
|
||||
0x003cb8ed, 0x003bb8ed, 0x003ab7ed, 0x0039b7ed, 0x0039b7ed, 0x0039b6ed, 0x003ab6ed,
|
||||
0x003ab6ed, 0x0037b4ed, 0x0034b2ec, 0x0035abf3, 0x006e96b3, 0x00ff4601, 0x00f86520,
|
||||
0x00f67329, 0x00f58131, 0x00f78b37, 0x00f9953e, 0x00f8a649, 0x00f8b854, 0x00fcc260,
|
||||
0x00f8c465, 0x00f9c36a, 0x00fac26e, 0x00fac773, 0x00facb77, 0x00fbcb7b, 0x00fccb7e,
|
||||
0x00fac87b, 0x00f8c578, 0x00f9bc72, 0x00fbb46d, 0x00f6b069, 0x00feaa57, 0x0094a0a5,
|
||||
0x0013a1f3, 0x00219df0, 0x00199eff, 0x0071c124, 0x0079b826, 0x0072b21e, 0x006aaa24,
|
||||
0x0067a125, 0x00649a19, 0x00419d72, 0x001f9fcb, 0x001994ff, 0x001399f1, 0x00199cf4,
|
||||
0x001ea0f8, 0x001b9cff, 0x001193f6, 0x001293f1, 0x001393ec, 0x000083ff, 0x0072cca0,
|
||||
0x00cbf982, 0x00d0ffac, 0x0079a046, 0x00337700, 0x003a7c03, 0x000d8de2, 0x000d8edb,
|
||||
0x003fbbee, 0x003ebaed, 0x003db9ed, 0x003cb9ed, 0x003bb8ed, 0x003bb8ed, 0x003cb9ee,
|
||||
0x003cb9ee, 0x003db9ef, 0x003ab4f1, 0x0037aff3, 0x0032b3fe, 0x00b48f7d, 0x00ff5907,
|
||||
0x00f37122, 0x00f57c2b, 0x00f68735, 0x00f7923d, 0x00f89d45, 0x00f9ac50, 0x00f9bb5a,
|
||||
0x00f9c465, 0x00facd71, 0x00facd76, 0x00facd7b, 0x00f7cf80, 0x00f4d286, 0x00fcd689,
|
||||
0x00ffd98c, 0x00fbd48b, 0x00f3cf8a, 0x00f9c885, 0x00ffc17f, 0x00f5c27d, 0x00ffbc5e,
|
||||
0x0048abdc, 0x001e9deb, 0x001ea2e8, 0x001da8e5, 0x0099d31c, 0x008acb22, 0x0082c427,
|
||||
0x007abc2c, 0x0075b429, 0x0070ad25, 0x006dab17, 0x006ba908, 0x005ea912, 0x00519f54,
|
||||
0x00489b6d, 0x003e9887, 0x003b9592, 0x00389880, 0x00449663, 0x00509446, 0x0083b43c,
|
||||
0x004f851b, 0x00afe187, 0x009fcc83, 0x00368011, 0x0043821c, 0x0032853c, 0x000492f9,
|
||||
0x001092dd, 0x0040bcee, 0x003fbcee, 0x003ebbee, 0x003dbaed, 0x003cbaed, 0x003cb9ed,
|
||||
0x003cb9ec, 0x003cb9ec, 0x003cb8ec, 0x003fb4f0, 0x0043aff5, 0x000ebbe9, 0x00ffb897,
|
||||
0x00f7814d, 0x00f57623, 0x00f6812e, 0x00f88c39, 0x00f89943, 0x00f8a64d, 0x00f8b257,
|
||||
0x00f9bd60, 0x00fac96d, 0x00fbd47b, 0x00fad681, 0x00fad788, 0x00fbd98e, 0x00fbda93,
|
||||
0x00fae5a1, 0x00fed692, 0x00fadea0, 0x00f9db98, 0x00fad694, 0x00fbd090, 0x00ffd285,
|
||||
0x00ffc778, 0x00009afd, 0x0026a8f2, 0x0020a4f8, 0x0053bea5, 0x00a4da31, 0x009dd638,
|
||||
0x0097d03a, 0x0091ca3d, 0x008bc539, 0x0085c035, 0x007dbe31, 0x0074bc2d, 0x0076b81c,
|
||||
0x0077b027, 0x0072ab25, 0x006da724, 0x006ba328, 0x0068a31f, 0x0058951a, 0x0078b745,
|
||||
0x00bbf181, 0x0073ad4c, 0x00417c15, 0x00508b1e, 0x0043861c, 0x00498614, 0x0017868b,
|
||||
0x000b90f6, 0x00168ee8, 0x0042beef, 0x0041bdee, 0x0040bcee, 0x003fbced, 0x003ebbed,
|
||||
0x003dbaec, 0x003db9eb, 0x003cb8ea, 0x003bb7e9, 0x0039b9f0, 0x0037bbf7, 0x0050b5dc,
|
||||
0x00ff9744, 0x00fec49d, 0x00f87a24, 0x00f88530, 0x00f9913d, 0x00f8a049, 0x00f7af55,
|
||||
0x00f8b85d, 0x00f9c065, 0x00face75, 0x00fcdb85, 0x00fbde8d, 0x00fae195, 0x00fee29b,
|
||||
0x00ffe2a0, 0x00fbe9a4, 0x00ffbe6b, 0x00fdde9f, 0x00ffe8a6, 0x00fbe3a3, 0x00f8dea0,
|
||||
0x00fdd899, 0x00b6bdab, 0x00119ff1, 0x001ea4e9, 0x001a9fff, 0x0089d465, 0x00b0e245,
|
||||
0x00b0e04e, 0x00acdc4e, 0x00a7d94e, 0x00a1d649, 0x009ad345, 0x0097ce3d, 0x0094c935,
|
||||
0x008dc534, 0x0086c133, 0x007bbc32, 0x006fb731, 0x006db330, 0x006cae2e, 0x007eba3f,
|
||||
0x0070a531, 0x007bb54f, 0x00579a20, 0x005c9f2b, 0x00519425, 0x0080b965, 0x00609a1d,
|
||||
0x000390e3, 0x00118ef2, 0x001c89f2, 0x0044c0ef, 0x0043bfef, 0x0042beee, 0x0040bdee,
|
||||
0x003fbcee, 0x003fbbed, 0x0040baeb, 0x003eb9ed, 0x003cb9ee, 0x0037b9eb, 0x0027bcf7,
|
||||
0x00949c8f, 0x00fb9637, 0x00f9bc7c, 0x00f9b585, 0x00f7994a, 0x00f69b43, 0x00f6a64e,
|
||||
0x00f7b259, 0x00f8bc66, 0x00fac672, 0x00fad380, 0x00fae08d, 0x00f9e698, 0x00f9eba2,
|
||||
0x00feeaa6, 0x00ffeaab, 0x00fcefa9, 0x00faba62, 0x00fbdc99, 0x00fff4b9, 0x00fbecb2,
|
||||
0x00f7e6ab, 0x00ffe5a3, 0x0064b1d1, 0x00199ff0, 0x00269fe9, 0x000499f2, 0x00e3f051,
|
||||
0x00d5ef58, 0x00c0e364, 0x00bde165, 0x00bae065, 0x00b5de5d, 0x00b0dc56, 0x00aad74e,
|
||||
0x00a3d346, 0x009bd043, 0x0093cd3f, 0x008cc93e, 0x0084c63c, 0x0081c139, 0x007dbc36,
|
||||
0x008bc746, 0x0089c245, 0x0063a02c, 0x0065aa2c, 0x005ea42d, 0x00509626, 0x00a4cf98,
|
||||
0x00d9eadd, 0x00b9ddff, 0x00389ef4, 0x00008fd4, 0x0046c1ef, 0x0044c0ef, 0x0043bfef,
|
||||
0x0042beef, 0x0040bdef, 0x0042bced, 0x0043baec, 0x0040baf0, 0x003dbaf4, 0x0035b8e7,
|
||||
0x0017bdf7, 0x00d97f50, 0x00f79147, 0x00f7a554, 0x00ffdbba, 0x00f8a24d, 0x00f3a549,
|
||||
0x00f5ad53, 0x00f7b55e, 0x00f9c16f, 0x00fbcc7f, 0x00f9d88a, 0x00f8e595, 0x00f8eda2,
|
||||
0x00f8f5ae, 0x00fff3b2, 0x00fff2b6, 0x00fef5ae, 0x00f4b659, 0x00f9db93, 0x00feffcd,
|
||||
0x00fbf6c1, 0x00f7edb6, 0x00fff2ac, 0x0013a4f7, 0x0016a5f0, 0x0018a5e8, 0x0056b4cd,
|
||||
0x00f1f271, 0x00d5ef84, 0x00cfe67b, 0x00cde77c, 0x00cbe77c, 0x00c9e672, 0x00c7e567,
|
||||
0x00bce15f, 0x00b1dd57, 0x00a9dc51, 0x00a0da4b, 0x009dd749, 0x009ad447, 0x0094cf43,
|
||||
0x008fcb3f, 0x0088c43c, 0x0082be39, 0x0072b430, 0x0063a928, 0x0059a028, 0x004e9827,
|
||||
0x00a0c479, 0x00fffbf7, 0x007fd3f5, 0x00038fe2, 0x000e89e2, 0x0048c3ef, 0x0046c2ef,
|
||||
0x0045c1f0, 0x0043c0f0, 0x0042bff0, 0x0042beee, 0x0043bdec, 0x0041bcef, 0x003fbcf2,
|
||||
0x002fc0fe, 0x0036bdfc, 0x00f54c00, 0x00ff8a52, 0x00faa65e, 0x00fdc48e, 0x00fbc185,
|
||||
0x00f5ae50, 0x00f7b65e, 0x00f9be6c, 0x00fac978, 0x00fbd485, 0x00fede98, 0x00ffe8aa,
|
||||
0x00fdeeae, 0x00f9f5b2, 0x00fcf6ba, 0x00fff7c2, 0x00fcf0b2, 0x00f7cc6e, 0x00fbde91,
|
||||
0x00fdfcca, 0x00fffbd1, 0x00fffdc8, 0x00cae4c8, 0x0016a1f2, 0x001da4ef, 0x0012a1f1,
|
||||
0x009fd5b9, 0x00eaf28c, 0x00dcf095, 0x00d9eb90, 0x00d9ec93, 0x00d9ec95, 0x00d6eb8c,
|
||||
0x00d4ea83, 0x00c9e779, 0x00bfe36f, 0x00b8e368, 0x00b1e262, 0x00afe05e, 0x00addf5a,
|
||||
0x00a3d952, 0x0099d449, 0x008ecb41, 0x0084c33a, 0x0075b833, 0x0066ac2c, 0x005da329,
|
||||
0x00559927, 0x004b9421, 0x002499b9, 0x001593fe, 0x000993d8, 0x000f90d8, 0x004ac5ef,
|
||||
0x0048c4f0, 0x0046c2f0, 0x0045c1f1, 0x0043c0f1, 0x0043bfef, 0x0043bfed, 0x0042beee,
|
||||
0x0041bdf0, 0x0038bbf0, 0x0072a1b8, 0x00ff5d1e, 0x00f97931, 0x00f5a151, 0x00f9ad61,
|
||||
0x00fee0bd, 0x00f8b758, 0x00fabf69, 0x00fcc87a, 0x00fcd282, 0x00fcdc8b, 0x00fbde8f,
|
||||
0x00fbe193, 0x00fbeba4, 0x00fbf5b5, 0x00faf8c2, 0x00f9fcce, 0x00f9ecb7, 0x00fae183,
|
||||
0x00fee290, 0x00fbfac8, 0x00fdf8d8, 0x00fffccb, 0x008bcedc, 0x00189fee, 0x0025a3ee,
|
||||
0x000b9dfb, 0x00e8f6a5, 0x00e4f1a6, 0x00e4f0a6, 0x00e4efa6, 0x00e5f1aa, 0x00e6f2ad,
|
||||
0x00e3f1a6, 0x00e0ef9e, 0x00d7ec93, 0x00cde987, 0x00c8ea80, 0x00c2eb78, 0x00c1ea73,
|
||||
0x00c0e96e, 0x00b1e360, 0x00a3dd53, 0x0094d247, 0x0086c83b, 0x0078bc35, 0x0069b030,
|
||||
0x0062a52b, 0x005b9b27, 0x0057920a, 0x000995fc, 0x000d96e5, 0x001091eb, 0x001091eb,
|
||||
0x004ac5f0, 0x0049c4f0, 0x0047c3f1, 0x0045c2f1, 0x0044c1f2, 0x0041c1f2, 0x003fc1f2,
|
||||
0x003fbff1, 0x003fbcf0, 0x0032c3fe, 0x00be7f6e, 0x00fe6526, 0x00f67b35, 0x00f59a4d,
|
||||
0x00f8ab5c, 0x00fbd0a0, 0x00f7c783, 0x00fec16b, 0x00fdd17f, 0x00fbdb87, 0x00f9e590,
|
||||
0x00f8ed9a, 0x00f7f4a5, 0x00fbea9a, 0x00ffdf8e, 0x00fce3a0, 0x00f7e6b1, 0x00fceecc,
|
||||
0x00fffbcb, 0x00fff3c7, 0x00fcf1c3, 0x00fef5d2, 0x00fffcd3, 0x004bb5e7, 0x0021a5ed,
|
||||
0x001ca2ee, 0x003daae2, 0x00eef6ac, 0x00e6f2b1, 0x00e8f2b5, 0x00e9f3b8, 0x00eaf4ba,
|
||||
0x00ebf5bc, 0x00e8f3b6, 0x00e6f2af, 0x00e0f0a8, 0x00dbeea2, 0x00d6ef9a, 0x00d1f092,
|
||||
0x00c9ed82, 0x00c1eb73, 0x00b0e362, 0x00a1dc51, 0x0094d347, 0x0088ca3e, 0x007bbf38,
|
||||
0x006eb433, 0x0066a92e, 0x005da01b, 0x003d9448, 0x000a93f6, 0x000e94ec, 0x001193f0,
|
||||
0x001193f0, 0x004bc5f1, 0x004ac5f1, 0x0048c4f1, 0x0047c3f2, 0x0045c3f2, 0x0040c3f4,
|
||||
0x003bc4f6, 0x003cbff3, 0x003ebbf0, 0x002dcaff, 0x00ff5d25, 0x00fe6d2f, 0x00f37d39,
|
||||
0x00f59348, 0x00f8a958, 0x00f7c083, 0x00f7d7ae, 0x00ffc36d, 0x00ffda84, 0x00fbe48c,
|
||||
0x00f7ee94, 0x00f8ed9e, 0x00faeca7, 0x00f9f1b4, 0x00f8f6c1, 0x00fcf6c8, 0x00fff6d0,
|
||||
0x00fef2d3, 0x00fcf4ba, 0x00fffee8, 0x00f7fdea, 0x00fdfde3, 0x00fffcdc, 0x000b9df1,
|
||||
0x002aaaed, 0x001baaf6, 0x0080c8da, 0x00fdffbb, 0x00e8f2bd, 0x00ebf4c4, 0x00eff7cb,
|
||||
0x00eff7cb, 0x00eff7cb, 0x00edf6c5, 0x00ebf5c0, 0x00eaf4be, 0x00e8f3bd, 0x00e4f4b4,
|
||||
0x00e0f6ab, 0x00d0f191, 0x00c1ec77, 0x00b0e463, 0x009edb4e, 0x0095d448, 0x008bcc42,
|
||||
0x007fc23b, 0x0073b935, 0x006aac31, 0x0060a510, 0x00229687, 0x000b91f1, 0x000e93f3,
|
||||
0x001294f5, 0x001294f5, 0x004cc6f1, 0x004bc5f2, 0x0049c5f2, 0x0047c4f2, 0x0046c4f2,
|
||||
0x0043c4f1, 0x0040c4f0, 0x0042c0f3, 0x0039c1f6, 0x005eacca, 0x00fb591e, 0x00f36e31,
|
||||
0x00f88135, 0x00fb923f, 0x00fbaf5e, 0x00ffc373, 0x00fde2ba, 0x00ffcd75, 0x00ffd372,
|
||||
0x00ffe584, 0x00fff796, 0x00fef4a2, 0x00fdf1ae, 0x00fff8c2, 0x00fcf8cd, 0x00fef8d2,
|
||||
0x00fff9d6, 0x00fef6e1, 0x00fcf5dd, 0x00fffbee, 0x00fbfce8, 0x00fffce0, 0x00b2e0e8,
|
||||
0x0019a4f0, 0x0026abec, 0x0016a8f6, 0x00c2e4d8, 0x00f9fac5, 0x00eff6cb, 0x00f0f7ce,
|
||||
0x00f1f8d2, 0x00f1f8d1, 0x00f2f9d1, 0x00f1f9cd, 0x00f1f9ca, 0x00f2fbca, 0x00f4fdca,
|
||||
0x00e7f8b6, 0x00daf3a2, 0x00cbef8a, 0x00bcec71, 0x00b0e661, 0x00a5e151, 0x009ad949,
|
||||
0x008fd240, 0x0083c73b, 0x0077bc35, 0x006ab31d, 0x005ea905, 0x00138dea, 0x001193ef,
|
||||
0x001093f0, 0x000f93f0, 0x000f93f0, 0x004dc6f2, 0x004cc6f2, 0x004ac5f3, 0x0048c5f3,
|
||||
0x0047c5f3, 0x0046c4ef, 0x0046c4eb, 0x0048c0f3, 0x0034c7fb, 0x00989591, 0x00fc6428,
|
||||
0x00f1773b, 0x00fc8432, 0x00ff9135, 0x00ffb564, 0x00ffbe5a, 0x00f3ddb6, 0x00ccd097,
|
||||
0x00b4cea5, 0x00b0d3b1, 0x00abd7bd, 0x00c3e1bf, 0x00daebc1, 0x00f5fdc7, 0x00ffffbd,
|
||||
0x00fffecd, 0x00fffcdc, 0x00fffce0, 0x00fbfce5, 0x00fdfbe6, 0x00fffae7, 0x00fffbdd,
|
||||
0x0061c4f4, 0x0026aaee, 0x0022abec, 0x0010a7f6, 0x00ffffd7, 0x00f5f5d0, 0x00f6fad9,
|
||||
0x00f4f9d9, 0x00f2f9da, 0x00f3fad8, 0x00f4fbd7, 0x00f5fcd5, 0x00f7fdd4, 0x00f3face,
|
||||
0x00f0f7c8, 0x00e2f4b0, 0x00d4f199, 0x00c5ee82, 0x00b7eb6b, 0x00b1e95f, 0x00abe754,
|
||||
0x009fdf49, 0x0094d83f, 0x0087cc3a, 0x007bc034, 0x006bb425, 0x005ba332, 0x000495f9,
|
||||
0x001795ee, 0x001293ed, 0x000c91eb, 0x000c91eb, 0x004fc8f3, 0x004dc8f3, 0x004cc8f4,
|
||||
0x004bc8f4, 0x0049c8f4, 0x0047c5f2, 0x0045c2ef, 0x0042c2f8, 0x0034c8ff, 0x00df6746,
|
||||
0x00ff632a, 0x00ff701b, 0x00e18b53, 0x00a4a185, 0x0063c1cd, 0x0026c0ff, 0x002ab8ff,
|
||||
0x0025b5f1, 0x0027b7f9, 0x0026b5f6, 0x0023b3f2, 0x0024b5fa, 0x0025b7ff, 0x00189ddf,
|
||||
0x0043bbf4, 0x009edae8, 0x00f9f9dc, 0x00f3fbe6, 0x00ffffea, 0x00fdffe6, 0x00fafce2,
|
||||
0x00ffffff, 0x001ea8ef, 0x001ca8f1, 0x001ba8f2, 0x005bc4f1, 0x00ffffe7, 0x00fbf9e1,
|
||||
0x00fbfce3, 0x00f8fbe0, 0x00f5fadd, 0x00f5fbdb, 0x00f5fbda, 0x00f6fcd7, 0x00f6fdd3,
|
||||
0x00f0f8c9, 0x00ebf4be, 0x00dff2a9, 0x00d4f094, 0x00c7f47b, 0x00baf862, 0x00b0ef58,
|
||||
0x00a6e64e, 0x00a3e248, 0x0098d73a, 0x008acd38, 0x007bc435, 0x0070b821, 0x003b9c84,
|
||||
0x000d93f4, 0x001394ed, 0x001193e9, 0x000f92e6, 0x000f92e6, 0x0050c9f4, 0x004fcaf4,
|
||||
0x004ecaf5, 0x004dcaf5, 0x004ccaf6, 0x0048c5f4, 0x0045c0f3, 0x0047c2ef, 0x004ac4eb,
|
||||
0x00ff521f, 0x00a79a92, 0x0051b7e6, 0x0028c7ff, 0x002cc4f9, 0x0031c1f1, 0x003fbbf0,
|
||||
0x0037c0ef, 0x0039b9f0, 0x003bb3f1, 0x0038b5f4, 0x0036b7f7, 0x0032b9f0, 0x002fbbe8,
|
||||
0x002fb8eb, 0x002fb5ed, 0x0020acf3, 0x0010a3fa, 0x0070c9f3, 0x00f5f9df, 0x00f6fbde,
|
||||
0x00f6fdde, 0x00d8ebe4, 0x0011a5ee, 0x002db2f5, 0x0014a5f8, 0x00a5e2ec, 0x00fffff8,
|
||||
0x00fffef3, 0x00fffded, 0x00fcfde6, 0x00f8fce0, 0x00f7fcde, 0x00f6fcdd, 0x00f6fcd8,
|
||||
0x00f5fdd3, 0x00edf7c4, 0x00e5f1b4, 0x00e5f5b8, 0x00e4f9bb, 0x00ecfed2, 0x00f3ffe9,
|
||||
0x00edfedb, 0x00e8f9cd, 0x00caef89, 0x009cd636, 0x0084c72e, 0x006bb826, 0x006cb315,
|
||||
0x001a95d6, 0x001591ef, 0x001093eb, 0x001193e6, 0x001294e1, 0x001294e1, 0x0052cbf4,
|
||||
0x0050caf4, 0x004ecaf4, 0x004ccaf3, 0x004ac9f3, 0x0048c8f5, 0x0046c7f6, 0x0040bfed,
|
||||
0x0041bfeb, 0x0041d4f9, 0x0033c9fc, 0x002fc9ff, 0x0042c3ec, 0x0040c3f4, 0x003ec3fc,
|
||||
0x0035bbf4, 0x0033bbf3, 0x0049bdf7, 0x0039b7f9, 0x0037b7f6, 0x0035b7f2, 0x002eb5f4,
|
||||
0x0028b3f5, 0x002fbbf8, 0x002fbaf2, 0x0030b5f2, 0x0031b0f1, 0x001facf6, 0x000dabed,
|
||||
0x007fd2ed, 0x00ffffe6, 0x0080d9d2, 0x002faaf8, 0x001dafec, 0x0003aae6, 0x00fff8ff,
|
||||
0x00fffffe, 0x00fffff9, 0x00fffdf4, 0x00fdfeeb, 0x00fbfee3, 0x00f9fde1, 0x00f7fce0,
|
||||
0x00f5fdd8, 0x00f4fdcf, 0x00f5fce2, 0x00f6fde8, 0x00f3fde8, 0x00f1fde9, 0x00ebfdd3,
|
||||
0x00e6fdbe, 0x00e0f8ba, 0x00daf2b7, 0x00eafcd2, 0x00f2fde6, 0x00b7de8d, 0x0084c73d,
|
||||
0x009ab848, 0x0014a1f9, 0x000494f3, 0x001094ef, 0x001095ec, 0x001095e9, 0x001095e9,
|
||||
0x0054ccf5, 0x0051cbf4, 0x004ecaf3, 0x004cc9f2, 0x0049c8f1, 0x0048cbf5, 0x0048cef9,
|
||||
0x0040c4f3, 0x0049cafc, 0x0040c2f1, 0x0047caf5, 0x0046c7f4, 0x0046c4f3, 0x0039b5ee,
|
||||
0x002ca5e8, 0x002eb1e1, 0x0056c1ea, 0x006dc9e9, 0x0037c2e5, 0x0051caeb, 0x006bd2f1,
|
||||
0x0074d1f5, 0x007dcff9, 0x0056c7f8, 0x001fafe8, 0x0025b1ee, 0x002cb3f4, 0x003eb5f9,
|
||||
0x002bb3ee, 0x001baff5, 0x0032b5f0, 0x003fb2f9, 0x0026a9f2, 0x001faeeb, 0x003fb8f4,
|
||||
0x00fcfff3, 0x00ffffff, 0x00ffffff, 0x00fffefb, 0x00fefff1, 0x00feffe6, 0x00fbffe5,
|
||||
0x00f8fde3, 0x00f5fdd7, 0x00f3fecb, 0x00f5fbeb, 0x00f7feee, 0x00f2fdde, 0x00edfccf,
|
||||
0x00e3f9b0, 0x00d9f692, 0x00d2f48b, 0x00ccf184, 0x00ceee97, 0x00d0eaa9, 0x00daebc1,
|
||||
0x00f4fbe9, 0x007fc679, 0x005ac1ff, 0x001aa1eb, 0x001195f2, 0x000f96f2, 0x000e97f2,
|
||||
0x000e97f2, 0x0054cdf5, 0x0052ccf4, 0x004fcbf3, 0x004dc9f3, 0x004ac8f2, 0x0049c6f2,
|
||||
0x0047c4f2, 0x0049d2f3, 0x0046c8f3, 0x004dc5fc, 0x002c9add, 0x001883cd, 0x00046cbe,
|
||||
0x000080c5, 0x000f96d4, 0x002eaddb, 0x0060c6eb, 0x0076cdef, 0x0051caea, 0x0069d2f0,
|
||||
0x0081daf5, 0x009ae4f7, 0x00b3eff9, 0x00cffaff, 0x00e3feff, 0x009ae1ff, 0x0048bcf7,
|
||||
0x0011b5dd, 0x0032aef0, 0x0028acfc, 0x0031b2f3, 0x0034b1f6, 0x0025adf0, 0x0026acf6,
|
||||
0x0098d1fc, 0x00fffdf8, 0x00ffffff, 0x00fffffb, 0x00fefff4, 0x00fdffee, 0x00fcfde7,
|
||||
0x00fbfee4, 0x00faffe0, 0x00f8fde7, 0x00f7fcef, 0x00f3fbeb, 0x00effdd9, 0x00e9fbc2,
|
||||
0x00e3f9ac, 0x00d9f49b, 0x00ceef8b, 0x00c1ea76, 0x00b4e562, 0x00abdd5a, 0x00a2d261,
|
||||
0x00c1e98e, 0x00dbe8b9, 0x0096d4ff, 0x008ed0fa, 0x0042aeee, 0x001095f1, 0x001096f1,
|
||||
0x000f96f1, 0x000f96f1, 0x0055cef5, 0x0053ccf4, 0x0050cbf4, 0x004ecaf4, 0x004cc8f4,
|
||||
0x0051caf7, 0x0057cbfa, 0x0045c0ea, 0x001a75c7, 0x000058ad, 0x00015bb4, 0x00066fc0,
|
||||
0x000b84cd, 0x000093ce, 0x0011a7e0, 0x003eb9e6, 0x006bcbeb, 0x007ed1f6, 0x006cd3f0,
|
||||
0x0082dbf4, 0x0098e3f9, 0x00a5ecf7, 0x00b2f4f5, 0x00c7f7f9, 0x00ddfafd, 0x00f2ffff,
|
||||
0x00f8fff6, 0x00bcebfe, 0x0022b4f2, 0x0029afff, 0x002fb0f7, 0x0029b1f2, 0x0023b1ee,
|
||||
0x001aa7fa, 0x00cae6f4, 0x00f7f8f4, 0x00feffff, 0x00fefff7, 0x00feffed, 0x00fcffeb,
|
||||
0x00fbfae9, 0x00fbfee3, 0x00fbffdc, 0x00fbffe9, 0x00fbfff7, 0x00f1fedd, 0x00e7fbc3,
|
||||
0x00e0f6b4, 0x00d8f0a5, 0x00ceec94, 0x00c4e884, 0x00b8e678, 0x00ace36c, 0x00a0df53,
|
||||
0x0094d455, 0x0080bd41, 0x00d2e599, 0x002ca1f4, 0x0030a2f6, 0x00209cf3, 0x001096f1,
|
||||
0x001096f1, 0x001096f1, 0x001096f1, 0x0055cef4, 0x0053cdf4, 0x0051cbf5, 0x0050cbf5,
|
||||
0x004ecaf6, 0x004dc9f4, 0x0054d0fa, 0x002b86ce, 0x000752b1, 0x00045fb9, 0x000a74c9,
|
||||
0x000882ce, 0x000691d4, 0x0002a0d5, 0x0024b5e7, 0x004cc4ea, 0x0074d3ee, 0x0083d9f5,
|
||||
0x007fddf4, 0x0093e4f6, 0x00a8ecf9, 0x00b6f2f9, 0x00c3f9f9, 0x00d3fafb, 0x00e3fcfc,
|
||||
0x00edfefb, 0x00f0f9f3, 0x00ffffff, 0x00fffdff, 0x007edcef, 0x0026adfd, 0x002aaff7,
|
||||
0x002db2f2, 0x0034b1e0, 0x0009a7f7, 0x008dd3f5, 0x00fdfbf9, 0x00fffff6, 0x00fdffeb,
|
||||
0x00fcffe6, 0x00fcfce0, 0x00f9fcde, 0x00f7fcdd, 0x00fcffef, 0x00f9fdec, 0x00e8f5d0,
|
||||
0x00dff5bd, 0x00d9f1ad, 0x00d2ed9d, 0x00c5e97e, 0x00b8e26d, 0x00abdd5e, 0x009fd74f,
|
||||
0x0098c95f, 0x0092c735, 0x008bc942, 0x0080b34d, 0x00009bf2, 0x001894f8, 0x001595f5,
|
||||
0x001397f2, 0x001296f1, 0x001195f0, 0x001195f0, 0x0056cff4, 0x0054cdf5, 0x0052ccf5,
|
||||
0x0051cbf7, 0x0051cbf9, 0x0049c8f1, 0x0051d5fa, 0x001662c1, 0x00005cbb, 0x000874cd,
|
||||
0x00037cce, 0x00028dd4, 0x00019edb, 0x0009aedc, 0x0037c2ee, 0x005acfef, 0x007edcf0,
|
||||
0x0088e1f4, 0x0092e6f8, 0x00a5eef8, 0x00b9f5f9, 0x00c7f9fb, 0x00d5fdfe, 0x00dffdfc,
|
||||
0x00e9fdfa, 0x00f0fefe, 0x00f8ffff, 0x00fafffe, 0x00fdfffc, 0x00fdfbff, 0x001db0e8,
|
||||
0x002ab1ee, 0x0037b2f5, 0x0025b9f7, 0x0029b4f8, 0x0022aff5, 0x001baaf2, 0x009fd7f6,
|
||||
0x00fdffea, 0x00fcfee0, 0x00fcfdd7, 0x00f8fada, 0x00f4f7dd, 0x00fdfef5, 0x00f6fae1,
|
||||
0x00dfecc3, 0x00d8efb6, 0x00d2eca6, 0x00ccea95, 0x00bce567, 0x00abdb56, 0x009fd344,
|
||||
0x0092cb33, 0x0085c824, 0x0079b46a, 0x003a9eaf, 0x000c97ff, 0x001994f9, 0x000f9bee,
|
||||
0x00139af0, 0x001699f3, 0x001497f1, 0x001295ef, 0x001295ef, 0x0058d0f5, 0x0056cef5,
|
||||
0x0053cdf4, 0x0053ccf6, 0x0052cbf8, 0x0053d6fb, 0x004fc8fc, 0x00004cad, 0x00096fca,
|
||||
0x000b80d4, 0x000588d5, 0x000598db, 0x0005a8e1, 0x0018b6e6, 0x003fc8f2, 0x0063d3f3,
|
||||
0x0086dff5, 0x0091e4f7, 0x009ce9fa, 0x00aef0f9, 0x00c0f7f9, 0x00cbfafb, 0x00d7fdfd,
|
||||
0x00defdfc, 0x00e6fefb, 0x00f0fffe, 0x00faffff, 0x00f2fefb, 0x00fefffd, 0x00c6e9fb,
|
||||
0x001eb0ec, 0x0030b4f6, 0x0030b7f8, 0x0019a8f7, 0x0026b0f0, 0x0022aef3, 0x001eabf5,
|
||||
0x0027aafa, 0x001ca6f6, 0x007dcdea, 0x00dff4dd, 0x00eaffb0, 0x00fdfeed, 0x00ffffef,
|
||||
0x00fcf9d3, 0x00edeeb4, 0x00e6e9ac, 0x00d9e68a, 0x00cbe367, 0x00b9e153, 0x00a6dd4d,
|
||||
0x0075c57f, 0x0043adb0, 0x00229bf3, 0x000a9cff, 0x000998f6, 0x00109cef, 0x00189aee,
|
||||
0x00149ded, 0x00159bf0, 0x001599f2, 0x001397f0, 0x001195ee, 0x001195ee, 0x005ad1f6,
|
||||
0x0057cff5, 0x0054cef4, 0x0054cdf6, 0x0053cbf8, 0x004dd3f4, 0x002c9add, 0x00045ec1,
|
||||
0x000572c9, 0x000683d2, 0x000794dc, 0x0008a2e2, 0x0008b1e8, 0x0028bfef, 0x0048cef6,
|
||||
0x006bd8f8, 0x008fe3fa, 0x009be8fa, 0x00a6edfb, 0x00b7f3fb, 0x00c7f9fa, 0x00d0fbfc,
|
||||
0x00d9fdfd, 0x00defefd, 0x00e2fffc, 0x00effffe, 0x00fcffff, 0x00ebfef7, 0x00fffffe,
|
||||
0x008fd7f8, 0x001eb0f1, 0x002eb0f6, 0x0018abec, 0x00e0f7fd, 0x0024ade9, 0x0023acf1,
|
||||
0x0021acf8, 0x0026aef7, 0x002cb0f6, 0x001aa9f5, 0x0008a3f4, 0x0022a7f9, 0x004cc2f2,
|
||||
0x006dcdef, 0x007ec9db, 0x007fcac2, 0x0081c6c6, 0x0061bccb, 0x0041b3d0, 0x0024a7e9,
|
||||
0x00089bff, 0x00119dff, 0x001a9fff, 0x000f99e9, 0x00149cf9, 0x00159cf7, 0x00159cf5,
|
||||
0x00179df1, 0x00199eed, 0x00179cef, 0x001599f1, 0x001397ef, 0x001195ed, 0x001195ed,
|
||||
0x005cd2f6, 0x0059d0f5, 0x0055cff3, 0x0054cdf5, 0x0053ccf8, 0x0051d5f6, 0x00167bcf,
|
||||
0x000467c6, 0x00067bcf, 0x00068bd7, 0x00059cdf, 0x0008a9e5, 0x000ab6eb, 0x002bc4f1,
|
||||
0x004cd2f7, 0x006ddbf9, 0x008ee5fa, 0x009deafb, 0x00aceffb, 0x00bdf5fb, 0x00cefbfa,
|
||||
0x00d5fbfc, 0x00dcfcfd, 0x00dcfefd, 0x00ddfffd, 0x00e4fffd, 0x00eafffd, 0x00fffffe,
|
||||
0x00ffffff, 0x0027c0de, 0x0026b5f6, 0x001fb0f9, 0x004dc6ff, 0x00fff9ef, 0x00fefffa,
|
||||
0x008bd8f7, 0x0018a7f3, 0x001daaf4, 0x0023acf6, 0x0022acf3, 0x0022abf0, 0x001aa3f2,
|
||||
0x001aa6ee, 0x0018a8f5, 0x000ea2f3, 0x0011a4f2, 0x0014a4ff, 0x0015a3fc, 0x0016a3fa,
|
||||
0x0017a2f3, 0x0019a2ec, 0x000e99fe, 0x00169bed, 0x0000a1ff, 0x002b9de8, 0x0061b5b0,
|
||||
0x00109af7, 0x00149cf2, 0x00189eed, 0x00169cef, 0x00149af0, 0x001298ee, 0x001096ec,
|
||||
0x001096ec, 0x005fd3f7, 0x005bd2f5, 0x0056d0f3, 0x0055cef5, 0x0053cdf7, 0x0056d8f8,
|
||||
0x00005cc0, 0x000370cb, 0x000785d6, 0x000594dc, 0x0004a3e2, 0x0008afe8, 0x000cbcee,
|
||||
0x002ec8f3, 0x0050d5f9, 0x006fdefa, 0x008de7fb, 0x009fecfb, 0x00b1f2fb, 0x00c3f7fb,
|
||||
0x00d4fcfa, 0x00d9fcfc, 0x00defcfd, 0x00dbfdfd, 0x00d9fffd, 0x00d9fdfb, 0x00d9fcfa,
|
||||
0x00e5fafa, 0x00a4eaf7, 0x002badfb, 0x002fb9fa, 0x001aaeed, 0x0099dbf8, 0x00ffffff,
|
||||
0x00fefdfc, 0x00fffefd, 0x00fffffd, 0x008cd4fa, 0x0019a9f6, 0x0018a9f7, 0x0016aaf9,
|
||||
0x001aa7f3, 0x001ea5ee, 0x001fa7f2, 0x0021a9f6, 0x001ea7f7, 0x001ba5f7, 0x0017a4f9,
|
||||
0x0012a2fb, 0x000b9dfd, 0x000399fe, 0x0026a2fa, 0x006fc0b0, 0x00cfca5e, 0x00ffe528,
|
||||
0x0074b4b3, 0x000b98fa, 0x00119af4, 0x00179dee, 0x00159cee, 0x00139aef, 0x001198ed,
|
||||
0x000f96eb, 0x000f96eb, 0x005dd1f6, 0x005bd2f5, 0x0058d2f4, 0x0053cef4, 0x0056d2fb,
|
||||
0x0040b2e6, 0x000164c6, 0x000376cf, 0x000487d7, 0x000296dd, 0x0001a4e4, 0x0004b1ea,
|
||||
0x0007bdf1, 0x001bc8f2, 0x0043d5fc, 0x0064ddfb, 0x0085e6fb, 0x0098ebfc, 0x00acf1fd,
|
||||
0x00bef9ff, 0x00cfffff, 0x00cffdff, 0x00cff9fb, 0x00d2fefe, 0x00d5ffff, 0x00c6f9ff,
|
||||
0x00b8efff, 0x005ad7d9, 0x0040b9e9, 0x002fb9ff, 0x002bb2f0, 0x0028afeb, 0x00def0f2,
|
||||
0x00ffffff, 0x00feffff, 0x00fffefe, 0x00fffefa, 0x00fffffa, 0x00fffff9, 0x00c2e8f0,
|
||||
0x0084cde7, 0x0053bbe9, 0x0022a9eb, 0x0014a1ff, 0x00069ff8, 0x000fa0f8, 0x0019a3eb,
|
||||
0x0043b1e1, 0x006ec2c9, 0x00b0d79a, 0x00f2eb6b, 0x00ebee32, 0x00f8e647, 0x00ffe23a,
|
||||
0x00fde142, 0x000098f4, 0x0019a1fc, 0x00169ef7, 0x00129bf1, 0x00139af1, 0x00149af0,
|
||||
0x001298ee, 0x001096ec, 0x001096ec, 0x005ccff6, 0x005bd2f6, 0x005ad4f6, 0x0052cdf2,
|
||||
0x005ad6fe, 0x00298cd5, 0x00026ccc, 0x00027bd2, 0x000189d8, 0x000097df, 0x0000a6e6,
|
||||
0x0000b2ed, 0x0002bef4, 0x0009c7f1, 0x0035d5ff, 0x0059ddfd, 0x007ce5fb, 0x0091eafd,
|
||||
0x00a6f0ff, 0x00b1f2ff, 0x00bbf5ff, 0x00bef5fc, 0x00c1f6f9, 0x00c1f7f7, 0x00c1f9f4,
|
||||
0x00c7fdfc, 0x00cdffff, 0x00c2f9f8, 0x005acdf4, 0x0039b1f3, 0x0038baf5, 0x002ab4f7,
|
||||
0x00fcfbf8, 0x00fdfeff, 0x00feffff, 0x00fffeff, 0x00fffcf6, 0x00fdfef2, 0x00f7ffee,
|
||||
0x00fcffea, 0x00ffffe5, 0x00ffffd8, 0x00ffffcb, 0x00fffbf1, 0x00ffffdf, 0x00fdfdc2,
|
||||
0x00f7ff88, 0x00fbfe92, 0x00ffff7f, 0x00fdfc6c, 0x00faf759, 0x00f8f059, 0x00f7e958,
|
||||
0x00f7e359, 0x00d0d368, 0x000998ff, 0x00189aef, 0x00129af2, 0x000c99f5, 0x001199f3,
|
||||
0x001599f2, 0x001397f0, 0x001195ee, 0x001195ee, 0x005fd2f9, 0x005cd3f8, 0x0059d4f6,
|
||||
0x0058d3f8, 0x005edaff, 0x001971cd, 0x00026ecd, 0x00037bd3, 0x000488d9, 0x000497e0,
|
||||
0x0005a6e6, 0x0001ade7, 0x0000b5e8, 0x0007beea, 0x0023cbf5, 0x004cd7f8, 0x0074e4fc,
|
||||
0x0089e8fd, 0x009fecfe, 0x00a5edfe, 0x00abeffe, 0x00aeeffc, 0x00b0eff9, 0x00b3f3f9,
|
||||
0x00b6f6f8, 0x00b6f9fc, 0x00b5fcff, 0x00daf3ff, 0x001ab9f1, 0x0028b3f4, 0x002bb3f6,
|
||||
0x0073cef4, 0x00fdfdf5, 0x00fdfefa, 0x00fdfffe, 0x00fffef9, 0x00fffdf3, 0x00fdfeee,
|
||||
0x00faffe9, 0x00fdffe4, 0x00ffffde, 0x00ffffd0, 0x00ffffc2, 0x00fdfad7, 0x00fffcf3,
|
||||
0x00ffffc0, 0x00fcfbc5, 0x00fcff84, 0x00fcfb8b, 0x00fbf67a, 0x00f9f269, 0x00f7ed5e,
|
||||
0x00f4e954, 0x00f7e948, 0x0087bda9, 0x00109afc, 0x00179cf2, 0x00149bf1, 0x00119af1,
|
||||
0x001399f2, 0x001698f3, 0x001496f1, 0x001294ef, 0x001294ef, 0x0062d4fc, 0x005dd4f9,
|
||||
0x0059d4f6, 0x0056d1f6, 0x0053cef5, 0x00014ebe, 0x00026fcd, 0x00057bd4, 0x000787da,
|
||||
0x000996e0, 0x000ca5e7, 0x000bb0e9, 0x0009bbeb, 0x0015c5f3, 0x0021d0fc, 0x0046dafc,
|
||||
0x006ce3fc, 0x0082e6fd, 0x0097e9fe, 0x0099e9fe, 0x009ce8fe, 0x009ee9fb, 0x00a0e9f9,
|
||||
0x00a6eefa, 0x00acf3fc, 0x00b0effc, 0x00b5ecfb, 0x0089ddf9, 0x0028b4f3, 0x003ebef7,
|
||||
0x001eadf7, 0x00bde8f0, 0x00fefff2, 0x00fefff3, 0x00fdfff4, 0x00fefef2, 0x00fefef0,
|
||||
0x00fefeea, 0x00fefee4, 0x00fefede, 0x00fefed8, 0x00fcffc9, 0x00fbffba, 0x00f6fea0,
|
||||
0x00ffffce, 0x00fff9f6, 0x00ffffc9, 0x00fdf7be, 0x00f8f87a, 0x00f9f66b, 0x00f9f35c,
|
||||
0x00f5ee56, 0x00f1e84f, 0x00f8ee37, 0x003fa7ea, 0x00189df5, 0x00179df4, 0x00169cf1,
|
||||
0x00159bee, 0x00169af2, 0x001798f5, 0x001596f3, 0x001394f1, 0x001394f1, 0x0066d7fc,
|
||||
0x005fd1f5, 0x0060d4f6, 0x0059d8f9, 0x00399ddb, 0x000858be, 0x00096ccd, 0x000c7ad2,
|
||||
0x001087d7, 0x001296df, 0x0013a6e8, 0x0013b0eb, 0x001bc3f5, 0x000fc8f3, 0x0017d0f9,
|
||||
0x0027d3f4, 0x004bd7f7, 0x0061dbf8, 0x0077def9, 0x007fe0fa, 0x0088e1fa, 0x008de4fb,
|
||||
0x0091e7fb, 0x0096eafc, 0x009aedfd, 0x009feafb, 0x00a3e7fa, 0x005eccfb, 0x002db7f5,
|
||||
0x0024b8f9, 0x0014b1f5, 0x00fffbff, 0x00feffec, 0x00ffffed, 0x00ffffee, 0x00ffffec,
|
||||
0x00fefdeb, 0x00fefde4, 0x00fefddd, 0x00fefed6, 0x00fefece, 0x00fcfdc1, 0x00fcfcb5,
|
||||
0x00f6fb8d, 0x00f8fc8a, 0x00f8facc, 0x00f8fef2, 0x00f9ffbe, 0x00fbf9c2, 0x00fbf8ac,
|
||||
0x00fcf796, 0x00faf491, 0x00f7f18d, 0x00ffe5a9, 0x000096f7, 0x00089af7, 0x00159ef7,
|
||||
0x00169df4, 0x00169cf0, 0x00169bf2, 0x001699f4, 0x001497f3, 0x001396f1, 0x001396f1,
|
||||
0x006bd9fb, 0x0061cef1, 0x0067d3f7, 0x005cdefd, 0x001f6cc0, 0x000f63bf, 0x000f6acd,
|
||||
0x001478d1, 0x001887d4, 0x001997df, 0x001aa6e9, 0x0014a9e4, 0x001dbbef, 0x000dbeeb,
|
||||
0x0023c5f6, 0x0013c6ed, 0x002acbf3, 0x0040cff4, 0x0056d4f4, 0x0065d7f6, 0x0074daf7,
|
||||
0x007bdffb, 0x0083e5fe, 0x0086e6fe, 0x0089e8fd, 0x008ee5fb, 0x0092e2fa, 0x0033bcfc,
|
||||
0x0032b9f7, 0x0031bafd, 0x0057c5f7, 0x00f4ffde, 0x00fdffe7, 0x00ffffe7, 0x00ffffe7,
|
||||
0x00ffffe6, 0x00fdfce6, 0x00fdfddd, 0x00fdfdd5, 0x00fdfdcd, 0x00fefdc5, 0x00fdfaba,
|
||||
0x00fcf8af, 0x00fef99f, 0x00fffb8e, 0x00fafe77, 0x00f4fb7d, 0x00f9f8d2, 0x00fdffee,
|
||||
0x00fefedf, 0x00fffcd0, 0x00fefacd, 0x00fdf9ca, 0x00a6d3ce, 0x000399eb, 0x001ea1ec,
|
||||
0x00149ffa, 0x00159ef6, 0x00179ef2, 0x00169cf3, 0x00159af3, 0x001499f2, 0x001398f1,
|
||||
0x001398f1, 0x0055d4f4, 0x005bd1f1, 0x0069d6f6, 0x006ee2ff, 0x000c50a8, 0x001161be,
|
||||
0x000f6acd, 0x001f83d6, 0x001f89dc, 0x000f8cdd, 0x001a9be0, 0x0022b1f4, 0x001dabe1,
|
||||
0x0014aedf, 0x0026bdee, 0x0015bae7, 0x001fc1ef, 0x0025c7ef, 0x002bcdef, 0x003dcdf1,
|
||||
0x004ecef3, 0x005bd6f9, 0x0068defe, 0x006eddfc, 0x0073ddfb, 0x0076ddf5, 0x0070d3f7,
|
||||
0x0031bafb, 0x0033b9f6, 0x0024b6ff, 0x00a4dee5, 0x00f9ffdc, 0x00fdfedc, 0x00ffffdc,
|
||||
0x00ffffdc, 0x00fefedb, 0x00fcfdda, 0x00fdfdd2, 0x00fdfdcb, 0x00fdfdc3, 0x00fefdbc,
|
||||
0x00fdfbaf, 0x00fcfaa2, 0x00fdfb93, 0x00fefb83, 0x00fcfd6b, 0x00f9fc60, 0x00fbf85d,
|
||||
0x00fdf74c, 0x00fef576, 0x00fff2a1, 0x00f6ec87, 0x00f8e360, 0x0051bbb4, 0x000d9afe,
|
||||
0x001a9ef7, 0x00159ef6, 0x00159df4, 0x00159df2, 0x00149bf2, 0x001299f2, 0x001299f2,
|
||||
0x001299f2, 0x001299f2, 0x0067d4fd, 0x0069d6f9, 0x006cd9f5, 0x004fb7dc, 0x001953af,
|
||||
0x001c67c6, 0x00005abd, 0x001a7eca, 0x00157bd4, 0x000581dc, 0x002aa1e7, 0x000189d3,
|
||||
0x002dabe3, 0x0023a7dc, 0x0029b4e6, 0x0017ade1, 0x0014b7ec, 0x0015b9ea, 0x0016bbe9,
|
||||
0x001fbfec, 0x0028c2ef, 0x003bcdf7, 0x004ed8ff, 0x0056d5fb, 0x005dd2f8, 0x005ed6f0,
|
||||
0x004ec5f4, 0x002fb9fa, 0x0035b8f4, 0x0017b1ff, 0x00f0f7d2, 0x00feffda, 0x00fdfcd2,
|
||||
0x00fdfdd1, 0x00fdfed1, 0x00fdfecf, 0x00fcfecd, 0x00fcfdc7, 0x00fdfdc0, 0x00fdfdb9,
|
||||
0x00fdfdb2, 0x00fdfca4, 0x00fdfc95, 0x00fdfc87, 0x00fdfc79, 0x00fdfa6c, 0x00fef85f,
|
||||
0x00f9f645, 0x00f6ef47, 0x00f2e938, 0x00efe428, 0x00eee425, 0x00ffdd05, 0x000399ff,
|
||||
0x0017a1f5, 0x00179ef4, 0x00169cf3, 0x00159cf3, 0x00149cf3, 0x00129bf1, 0x001099f0,
|
||||
0x00119af1, 0x00129bf2, 0x00129bf2, 0x0066d5fb, 0x0070d5fc, 0x0078e2ff, 0x003b86c7,
|
||||
0x00235fba, 0x001e6aba, 0x00227ad1, 0x002787d8, 0x00248cd7, 0x001d8dd4, 0x002189d1,
|
||||
0x002ca1ea, 0x002296d5, 0x0031aaef, 0x0020a1db, 0x0017a1dd, 0x000ea1e0, 0x001aace3,
|
||||
0x0013b1eb, 0x0010b8ed, 0x000dc0ef, 0x001cc1ef, 0x002cc3f0, 0x0036c4f2, 0x0040c5f4,
|
||||
0x0047c9f2, 0x0045c3f6, 0x0031bafa, 0x0031b7f7, 0x004cc2f4, 0x00f5fac0, 0x00fdffc6,
|
||||
0x00fdfcc5, 0x00fdfdc4, 0x00fdfdc4, 0x00fcfdc2, 0x00fbfdc1, 0x00f8f9b6, 0x00fdfdb3,
|
||||
0x00fdfdab, 0x00fdfca3, 0x00fcfc95, 0x00fcfb88, 0x00fcfb7b, 0x00fbfb6d, 0x00fcf962,
|
||||
0x00fcf757, 0x00f8f245, 0x00f4eb41, 0x00f0e532, 0x00ebe023, 0x00fbe01c, 0x00c5d244,
|
||||
0x000aa2fe, 0x00169ff9, 0x00179ff6, 0x00189ff3, 0x00179ef2, 0x00159df2, 0x00179ff5,
|
||||
0x0018a1f8, 0x00159ef5, 0x00129bf2, 0x00129bf2, 0x0065d7fa, 0x0064d1f7, 0x005de7ff,
|
||||
0x0004439b, 0x000e4ca5, 0x00317bcd, 0x000455c1, 0x000053c9, 0x000368c6, 0x002687ca,
|
||||
0x002881ca, 0x002789d1, 0x002791d7, 0x000774c9, 0x00178dcf, 0x001f9ce1, 0x00179be4,
|
||||
0x001e9eda, 0x000097de, 0x0003a5e6, 0x0008b1ee, 0x0009b0e8, 0x000aafe2, 0x0017b4e9,
|
||||
0x0024b9ef, 0x0030bdf4, 0x003cc1f9, 0x0034bcf9, 0x002cb6f9, 0x0080d2e8, 0x00fafdaf,
|
||||
0x00fcfdb3, 0x00fdfcb7, 0x00fdfcb7, 0x00fdfdb7, 0x00fcfcb6, 0x00fbfcb5, 0x00f4f4a5,
|
||||
0x00fdfda5, 0x00fcfc9d, 0x00fcfc94, 0x00fbfb87, 0x00fbfb7b, 0x00fafa6e, 0x00fafa61,
|
||||
0x00faf758, 0x00faf54e, 0x00f7ee44, 0x00f3e73a, 0x00ede12c, 0x00e7db1e, 0x00ffd21a,
|
||||
0x0078b090, 0x0009a0fd, 0x00159dfd, 0x0018a0f8, 0x001aa2f2, 0x0018a0f2, 0x00169ef2,
|
||||
0x00139bf2, 0x001099f1, 0x00119af2, 0x00129bf3, 0x00129bf3, 0x0060d4f7, 0x0067dcfd,
|
||||
0x004fc2f0, 0x00002c8a, 0x002e6bc0, 0x000547ad, 0x000044ba, 0x003685c4, 0x00064ebc,
|
||||
0x001462c3, 0x002d70cb, 0x000f5ab4, 0x002274cd, 0x001169c2, 0x001979c2, 0x001d80d0,
|
||||
0x001980d7, 0x001a86d3, 0x001090de, 0x00038dda, 0x000599e6, 0x00059ce1, 0x00049edd,
|
||||
0x0005a6e1, 0x0000a7de, 0x001fb6ee, 0x0039bdf7, 0x0038bcf6, 0x0024b5fc, 0x00bfe8b9,
|
||||
0x00fafea2, 0x00fbfca5, 0x00fcfaa8, 0x00fcfca7, 0x00fdfda6, 0x00fbfca3, 0x00f9fb9f,
|
||||
0x00f6f795, 0x00fafb92, 0x00fbfb8b, 0x00fbfb85, 0x00fafa79, 0x00fafa6d, 0x00f9f961,
|
||||
0x00f8f956, 0x00f9f64c, 0x00f9f442, 0x00f5ec39, 0x00f2e531, 0x00efde28, 0x00ecd620,
|
||||
0x00eed900, 0x0032a6e5, 0x0019a4ff, 0x0029a4f4, 0x0020a2f4, 0x0018a0f5, 0x00179ef4,
|
||||
0x00159df4, 0x00139bf3, 0x001199f2, 0x00129af2, 0x00129af3, 0x00129af3, 0x005bd1f5,
|
||||
0x0063dffa, 0x00318dcc, 0x00062d91, 0x000e499a, 0x0000369f, 0x00003897, 0x00155fb6,
|
||||
0x0053aad9, 0x0031a6e2, 0x0045bcef, 0x006dddff, 0x0076defa, 0x006dd9f9, 0x0064d5f9,
|
||||
0x0054c5f3, 0x0045b5ed, 0x00238ed6, 0x001277ce, 0x00006cc6, 0x000282de, 0x000187db,
|
||||
0x00008dd7, 0x00079be1, 0x000099dc, 0x0022b1f0, 0x0036baf4, 0x003cbcf4, 0x001cb5ff,
|
||||
0x00fffe89, 0x00fbff96, 0x00fbfc98, 0x00fbf99a, 0x00fcfb98, 0x00fdfd96, 0x00fafb90,
|
||||
0x00f6f98a, 0x00f7f984, 0x00f8fa7f, 0x00fafa7a, 0x00fbfb75, 0x00fafa6a, 0x00f9f960,
|
||||
0x00f8f855, 0x00f7f84a, 0x00f7f540, 0x00f8f336, 0x00f4eb2f, 0x00f0e328, 0x00f0da24,
|
||||
0x00f0d121, 0x00e9ca24, 0x00049bff, 0x0020a3f6, 0x0016a1f7, 0x0016a0f7, 0x00169ef7,
|
||||
0x00159df6, 0x00149cf5, 0x00139bf4, 0x00129af3, 0x00129af3, 0x00129af3, 0x00129af3,
|
||||
0x005ae3ff, 0x0064d8ff, 0x000d4798, 0x00002682, 0x001d6bb7, 0x003aa2de, 0x005fe5ff,
|
||||
0x0052d8fd, 0x004dd6f6, 0x0048ccf5, 0x005fd0f6, 0x0068d9ff, 0x0061d3f8, 0x005bd2f8,
|
||||
0x0042cbff, 0x0053cefe, 0x0051cff5, 0x0049caf6, 0x004acdff, 0x0040baff, 0x000e7edb,
|
||||
0x000069c2, 0x000584da, 0x000184d5, 0x00068cd8, 0x0038bef8, 0x003abef7, 0x0035beff,
|
||||
0x0062c7e2, 0x00fbf379, 0x00f8fa83, 0x00f9f983, 0x00faf884, 0x00f9f77f, 0x00f7f77b,
|
||||
0x00f8f979, 0x00f9fa77, 0x00f8f972, 0x00f7f86c, 0x00fcfc6c, 0x00f9f864, 0x00f8f85b,
|
||||
0x00f8f752, 0x00f7f649, 0x00f6f53f, 0x00f5f237, 0x00f4ef2f, 0x00f1e628, 0x00eede20,
|
||||
0x00ead61f, 0x00f2cc11, 0x009db96c, 0x000c9ffe, 0x001ba3f9, 0x0017a2f9, 0x0017a0f9,
|
||||
0x00169ef8, 0x00169df7, 0x00159cf6, 0x00149bf5, 0x00139af5, 0x00139af5, 0x00139af5,
|
||||
0x00139af5, 0x0060d8f9, 0x005bd9f8, 0x004cadd7, 0x0069ddff, 0x0056ddf8, 0x0055d6fc,
|
||||
0x0055d0ff, 0x005cd5ff, 0x0053cbf2, 0x004bcaf6, 0x0043cafa, 0x0047c9f8, 0x004cc8f6,
|
||||
0x005ccff1, 0x0046ccf8, 0x0055caff, 0x003ec4fa, 0x0043c3fb, 0x0048c2fd, 0x003ebff4,
|
||||
0x0044ccfb, 0x0037b3fc, 0x000b7bdd, 0x00006dc9, 0x000d80d4, 0x004eccff, 0x003ec3fa,
|
||||
0x002ec2ff, 0x00a7dea8, 0x00f8ec5b, 0x00f5f570, 0x00f7f66f, 0x00faf76e, 0x00f5f467,
|
||||
0x00f1f060, 0x00f6f663, 0x00fbfc65, 0x00f8f95f, 0x00f6f659, 0x00fefe5d, 0x00f7f652,
|
||||
0x00f7f54c, 0x00f7f545, 0x00f6f33d, 0x00f6f235, 0x00f3ef2f, 0x00f1eb29, 0x00efe221,
|
||||
0x00ecd818, 0x00e5d21a, 0x00f3c700, 0x0052a9b4, 0x0014a4fb, 0x0015a3fb, 0x0017a3fc,
|
||||
0x0017a1fa, 0x00179ff8, 0x00169df8, 0x00159cf7, 0x00159bf7, 0x001499f6, 0x001499f6,
|
||||
0x001499f6, 0x001499f6, 0x0058cff2, 0x0059ddfd, 0x0055d5f9, 0x005ddeff, 0x004dcef3,
|
||||
0x004dcbf3, 0x004cc8f3, 0x0056d2fc, 0x0059d3fd, 0x0050cefb, 0x0047cafa, 0x0048c9f9,
|
||||
0x0049c7f9, 0x0051cbf6, 0x0045c9f9, 0x004bc8fd, 0x003fc5f9, 0x0041c4fa, 0x0043c2fb,
|
||||
0x003bbdf3, 0x003ac0f4, 0x003ec7fc, 0x003ac6fc, 0x0025a1e3, 0x001f8dd9, 0x0037b9f7,
|
||||
0x0026bbfa, 0x002abbf4, 0x00ced857, 0x00f9fa5b, 0x00d9db49, 0x00edec58, 0x00faf560,
|
||||
0x00f2ef4d, 0x00e9ea3b, 0x00eeef46, 0x00f2f451, 0x00f9f34f, 0x00edf145, 0x00fef84b,
|
||||
0x00f4f542, 0x00f5f43d, 0x00f6f337, 0x00f5f131, 0x00f5ef2b, 0x00f2eb27, 0x00f0e622,
|
||||
0x00eedb1d, 0x00ecd117, 0x00f1cc09, 0x00f5c509, 0x000fadff, 0x0017a1f9, 0x0018a1f9,
|
||||
0x0018a1f8, 0x0018a0f9, 0x00179ff9, 0x00169df9, 0x00169cf8, 0x00159bf8, 0x001599f8,
|
||||
0x001599f8, 0x001599f8, 0x001599f8, 0x0060d5fb, 0x005bd3fb, 0x0056d2fb, 0x0055d1fc,
|
||||
0x0055d0fe, 0x0054d0fa, 0x0053d1f6, 0x0051cef7, 0x004ecbf8, 0x004dcbf9, 0x004ccafb,
|
||||
0x0049c8fb, 0x0047c6fc, 0x0045c6fb, 0x0043c6fa, 0x0041c6fa, 0x0040c7f9, 0x003fc5f9,
|
||||
0x003ec3f9, 0x003fc3fb, 0x0041c4fd, 0x0038baf2, 0x0040c1f8, 0x003dc3fb, 0x003bc5fe,
|
||||
0x0037c1f6, 0x0034beef, 0x002ebcf0, 0x00ded722, 0x00bfdc38, 0x00dee142, 0x00ecea4a,
|
||||
0x00eae442, 0x00eee942, 0x00f2ee42, 0x00eeed3f, 0x00eaec3d, 0x00fbee3f, 0x00e5ec31,
|
||||
0x00fff239, 0x00f2f531, 0x00f4f32e, 0x00f5f12a, 0x00f5ee25, 0x00f4ec21, 0x00f2e71e,
|
||||
0x00f0e11c, 0x00eed519, 0x00ecc917, 0x00dec40c, 0x00bbbe39, 0x000798f8, 0x001a9ff8,
|
||||
0x001a9ff7, 0x001a9ff5, 0x00189ff7, 0x00179ff9, 0x00179ef9, 0x00169cf9, 0x00169bf9,
|
||||
0x001699f9, 0x001699f9, 0x001699f9, 0x001699f9, 0x005cd4f9, 0x0058d4f9, 0x0055d3f9,
|
||||
0x0056d2fa, 0x0058d0fb, 0x0056d0f8, 0x0054d0f6, 0x0051cef7, 0x004dccf9, 0x004ccbfa,
|
||||
0x004bcafb, 0x0049c8fb, 0x0047c7fb, 0x0045c7fb, 0x0043c6fa, 0x0041c6fa, 0x0040c6f9,
|
||||
0x003fc4f9, 0x003ec3f9, 0x003ec2fa, 0x003ec2fb, 0x003abef5, 0x003ec2f8, 0x003bc1f9,
|
||||
0x0037c0f9, 0x0036beff, 0x0035bbff, 0x0067bb84, 0x00b0d219, 0x00b4d31a, 0x00d3da39,
|
||||
0x00e2dd3d, 0x00d6d532, 0x00e1df38, 0x00ece93e, 0x00e1e636, 0x00e9e536, 0x00f1e634,
|
||||
0x00e5e42b, 0x00f6e62e, 0x00e9eb29, 0x00f0ee2a, 0x00f0e824, 0x00ece420, 0x00e9e01d,
|
||||
0x00ebdb1c, 0x00edd71c, 0x00e9ce19, 0x00e5c516, 0x00e7c004, 0x006cb292, 0x00109dfc,
|
||||
0x0018a1f7, 0x001aa0f5, 0x001ca0f3, 0x0019a0f6, 0x00179ff9, 0x00169ef9, 0x00169cf9,
|
||||
0x00159bf8, 0x00159af8, 0x001499f8, 0x001499f7, 0x001499f7, 0x0058d4f6, 0x0056d4f6,
|
||||
0x0054d5f7, 0x0057d3f7, 0x005bd1f8, 0x0058d0f6, 0x0054cff5, 0x0050cef8, 0x004dcdfa,
|
||||
0x004bcbfb, 0x004acafb, 0x0048c9fb, 0x0046c7fb, 0x0045c7fa, 0x0043c7fa, 0x0042c6fa,
|
||||
0x0040c6f9, 0x003fc4f9, 0x003ec3f9, 0x003dc1f9, 0x003cc0f9, 0x003cc1f8, 0x003cc2f7,
|
||||
0x0038bff6, 0x0034bbf5, 0x0035bdfd, 0x0037beff, 0x0046bcfc, 0x0082c92c, 0x00a0be02,
|
||||
0x00b8c420, 0x00d8cf31, 0x00d2d632, 0x00d4d52e, 0x00d7d42a, 0x00cdd725, 0x00e9df2f,
|
||||
0x00e6dd2a, 0x00e4dc25, 0x00edd922, 0x00e0e220, 0x00ede927, 0x00eae01e, 0x00e4da1c,
|
||||
0x00ded319, 0x00e5d01a, 0x00ebcd1b, 0x00e5c818, 0x00dec214, 0x00f0bc00, 0x001da5eb,
|
||||
0x0019a1ff, 0x0016a2f7, 0x0019a2f4, 0x001ea2f1, 0x001aa0f5, 0x00169ff9, 0x00169ef8,
|
||||
0x00159df8, 0x00159cf8, 0x00149bf8, 0x00139af7, 0x001299f6, 0x001299f6, 0x005ed5f9,
|
||||
0x0063d6fc, 0x0068d6ff, 0x005fd3fc, 0x0056d0f8, 0x0053cff8, 0x0051cef8, 0x004ecdf9,
|
||||
0x004bccfb, 0x004acbfb, 0x0048cafb, 0x0047c9fa, 0x0046c8fb, 0x0044c7fa, 0x0043c7fa,
|
||||
0x0042c6fa, 0x0040c5f9, 0x003fc4f9, 0x003ec3f9, 0x003dc1f9, 0x003cc0f9, 0x003bc1f9,
|
||||
0x003bc1f8, 0x0038bff7, 0x0036bdf7, 0x0035bdfa, 0x0034bdfe, 0x0022c3f6, 0x0027bbfc,
|
||||
0x0053b0b2, 0x009bc606, 0x00c1d322, 0x00d3dd36, 0x00b4ba12, 0x00c4c71f, 0x00c5cf22,
|
||||
0x00d9d82d, 0x00dfdb30, 0x00dcd52b, 0x00e8d520, 0x00d5d51c, 0x00e8e428, 0x00ece324,
|
||||
0x00d1ce1f, 0x00d3c51d, 0x00dcc302, 0x00cfc312, 0x00e3c209, 0x00e3be00, 0x0084bf6e,
|
||||
0x000ca0f6, 0x00129ffd, 0x0018a2f6, 0x0019a1f5, 0x001ba1f4, 0x0018a0f6, 0x00169ff8,
|
||||
0x00159ef8, 0x00159df8, 0x00149cf7, 0x00139bf7, 0x00129af6, 0x001098f4, 0x001098f4,
|
||||
0x0065d7fb, 0x005dd4fa, 0x0056d2f8, 0x0053d0f9, 0x0050cff9, 0x004fcef9, 0x004dcdfa,
|
||||
0x004bcdfa, 0x004accfb, 0x0048cbfb, 0x0047cafb, 0x0046c9fa, 0x0045c8fa, 0x0044c7fa,
|
||||
0x0043c7fa, 0x0042c6fa, 0x0040c5fa, 0x003fc4f9, 0x003ec3f9, 0x003dc1f9, 0x003bc0f9,
|
||||
0x003ac0f9, 0x0039c0f9, 0x0038bff9, 0x0037bff9, 0x0034bef8, 0x0031bcf7, 0x0033bbf8,
|
||||
0x0035bbfa, 0x002cbcff, 0x0061c2df, 0x0093cb85, 0x00c5d52b, 0x00cbd82f, 0x00b0bb13,
|
||||
0x00b5be17, 0x00b9c21b, 0x00c7c826, 0x00c5bf21, 0x00dbc817, 0x00cac819, 0x00dbd722,
|
||||
0x00ddd61a, 0x00b7bd0d, 0x00c8bd04, 0x00d0c000, 0x00adc951, 0x006cb8b1, 0x0004a3ff,
|
||||
0x0013a4fb, 0x0021a4f5, 0x001ea3f5, 0x001aa1f6, 0x0019a1f6, 0x0018a0f7, 0x0017a0f7,
|
||||
0x00169ff8, 0x00159ef7, 0x00149ef7, 0x00139df7, 0x00139cf6, 0x00119af4, 0x000f98f2,
|
||||
0x000f98f2, 0x005cd5f9, 0x0058d3f8, 0x0053d1f8, 0x0052d0f9, 0x0050cff9, 0x004ecefa,
|
||||
0x004ccdfa, 0x004accfa, 0x0048ccfa, 0x0047cbfa, 0x0046cafa, 0x0045c9fa, 0x0044c8fa,
|
||||
0x0043c7fa, 0x0042c7fa, 0x0041c6fa, 0x0040c5fa, 0x003fc4f9, 0x003ec2f9, 0x003cc1f9,
|
||||
0x003bc0f9, 0x003ac0f9, 0x0038bff9, 0x0037bff9, 0x0036bff9, 0x0035bdf6, 0x0034bbf3,
|
||||
0x0035b9f7, 0x0035b8fb, 0x0022b5ff, 0x002fb5ff, 0x004dbae6, 0x006bbfce, 0x0027b1c5,
|
||||
0x006cbc7c, 0x008abd49, 0x00a7be15, 0x00b9bf09, 0x00ccc000, 0x00dac43d, 0x00bbca20,
|
||||
0x00aec73e, 0x0099bc54, 0x005aad8b, 0x0036abc4, 0x0004b3ff, 0x0015a7ff, 0x0021a4ff,
|
||||
0x0019a0fb, 0x001ba2fa, 0x001da4f9, 0x001ba3f8, 0x001aa1f7, 0x0019a1f7, 0x0018a0f7,
|
||||
0x0017a0f7, 0x00169ff8, 0x00159ef7, 0x00149ef7, 0x00139df7, 0x00129cf6, 0x00119af5,
|
||||
0x000f99f3, 0x000f99f3, 0x0053d2f6, 0x0052d1f7, 0x0051d1f8, 0x0050d0f9, 0x004fcffa,
|
||||
0x004dcefa, 0x004bcdfa, 0x0049ccfa, 0x0047cbfa, 0x0046caf9, 0x0045caf9, 0x0044c9f9,
|
||||
0x0044c8fa, 0x0043c7fa, 0x0042c6f9, 0x0041c6f9, 0x0040c5fa, 0x003fc4f9, 0x003dc2f9,
|
||||
0x003cc1f9, 0x003ac0f9, 0x0039c0f9, 0x0038bff9, 0x0036bff9, 0x0035bef8, 0x0036bcf4,
|
||||
0x0038baf0, 0x0036b8f6, 0x0034b5fc, 0x002cb6f9, 0x0023b7f6, 0x0025b5fa, 0x0028b4ff,
|
||||
0x0028b6ff, 0x0029b7ff, 0x001fb5ff, 0x0015b2ff, 0x0020aef7, 0x003cb9ff, 0x005acbf0,
|
||||
0x0042befa, 0x002ab6fc, 0x0012adff, 0x0018acfc, 0x001eacfa, 0x001ea9fd, 0x001ea7ff,
|
||||
0x001ba8fa, 0x0018a8f4, 0x0018a6f8, 0x0018a4fd, 0x0019a3fa, 0x001aa1f7, 0x0019a1f7,
|
||||
0x0018a0f8, 0x0017a0f8, 0x00169ff8, 0x00159ef7, 0x00149df7, 0x00139cf6, 0x00129bf6,
|
||||
0x00119af5, 0x001099f4, 0x001099f4, 0x0054d1f8, 0x0052d1f8, 0x0051d0f9, 0x004fcff9,
|
||||
0x004ecffa, 0x004ccefa, 0x004acdf9, 0x0048ccf9, 0x0045cbf9, 0x0045caf9, 0x0044c9f9,
|
||||
0x0043c8f9, 0x0043c8f9, 0x0042c7f9, 0x0042c6f9, 0x0041c5f9, 0x0040c5fa, 0x003fc4f9,
|
||||
0x003dc2f9, 0x003bc1f9, 0x003ac0fa, 0x0038bff9, 0x0037bff9, 0x0036bef9, 0x0034bef8,
|
||||
0x0035bcf6, 0x0035baf5, 0x0034b8f8, 0x0033b6fc, 0x002eb6f9, 0x0029b6f7, 0x0029b5f8,
|
||||
0x002ab4fa, 0x002ab5fb, 0x002ab5fc, 0x002ab2f6, 0x002aafef, 0x001ba9f6, 0x009bcfd9,
|
||||
0x006dcfe9, 0x0074c7e4, 0x0080c9dd, 0x0019adfb, 0x001cacf9, 0x001fabf8, 0x001fa9f9,
|
||||
0x001ea7fb, 0x001ca7f9, 0x001aa7f6, 0x001aa5f8, 0x001aa4fb, 0x001aa3fa, 0x001aa2f8,
|
||||
0x0019a1f8, 0x0018a0f8, 0x0017a0f8, 0x00169ff8, 0x00159ef7, 0x00149df7, 0x00139cf6,
|
||||
0x00129bf6, 0x00119bf5, 0x00119af5, 0x00119af5, 0x0055d0f9, 0x0053d0fa, 0x0051d0fa,
|
||||
0x004fcffa, 0x004dcffa, 0x004bcefa, 0x0049cdf9, 0x0046ccf9, 0x0044caf8, 0x0043caf8,
|
||||
0x0043c9f8, 0x0043c8f9, 0x0042c8f9, 0x0042c7f9, 0x0041c6f9, 0x0041c6f9, 0x0040c5fa,
|
||||
0x003ec3f9, 0x003dc2fa, 0x003bc1fa, 0x0039c0fa, 0x0038bff9, 0x0036bff9, 0x0035bef9,
|
||||
0x0034bdf8, 0x0033bcf9, 0x0033bafa, 0x0032b9fb, 0x0032b8fc, 0x0030b7fa, 0x002eb6f8,
|
||||
0x002db5f7, 0x002bb4f5, 0x002bb4f6, 0x002bb3f7, 0x0029b2f9, 0x0028b2fc, 0x0030b2f7,
|
||||
0x0012a8fe, 0x007fd4e1, 0x0058bbe6, 0x0015aafb, 0x001fadf8, 0x0020acf7, 0x0020aaf5,
|
||||
0x001fa9f6, 0x001ea8f7, 0x001da6f7, 0x001ca5f8, 0x001ca4f8, 0x001ba3f9, 0x001ba3f9,
|
||||
0x001ba2f9, 0x0019a1f9, 0x0018a0f8, 0x0017a0f8, 0x00169ff8, 0x00159ef7, 0x00149df7,
|
||||
0x00139cf6, 0x00129bf5, 0x00129bf5, 0x00129bf5, 0x00129bf5, 0x0055d0f9, 0x0053d0fa,
|
||||
0x0051d0fa, 0x004fcffa, 0x004dcffa, 0x004bcefa, 0x0049cdf9, 0x0046ccf9, 0x0044caf8,
|
||||
0x0043caf8, 0x0043c9f8, 0x0043c8f9, 0x0042c8f9, 0x0042c7f9, 0x0041c6f9, 0x0041c6f9,
|
||||
0x0040c5fa, 0x003ec3f9, 0x003dc2fa, 0x003bc1fa, 0x0039c0fa, 0x0038bff9, 0x0036bff9,
|
||||
0x0035bef9, 0x0034bdf8, 0x0033bcf9, 0x0033bafa, 0x0032b9fb, 0x0032b8fc, 0x0030b7fa,
|
||||
0x002eb6f8, 0x002db5f7, 0x002bb4f5, 0x002bb4f6, 0x002bb3f7, 0x002ab2f8, 0x0029b2fa,
|
||||
0x002db6f5, 0x001db5f6, 0x00239bff, 0x0020b6f3, 0x000cacfb, 0x001eacf7, 0x001fabf6,
|
||||
0x0020aaf5, 0x001fa9f6, 0x001ea8f7, 0x001da6f7, 0x001ca5f8, 0x001ca4f8, 0x001ba3f9,
|
||||
0x001ba3f9, 0x001ba2f9, 0x0019a1f9, 0x0018a0f8, 0x0017a0f8, 0x00169ff8, 0x00159ef7,
|
||||
0x00149df7, 0x00139cf6, 0x00129bf5, 0x00129bf5, 0x00129bf5, 0x00129bf5, 0x0055d0f9,
|
||||
0x0053d0fa, 0x0051d0fa, 0x004fcffa, 0x004dcffa, 0x004bcefa, 0x0049cdf9, 0x0046ccf9,
|
||||
0x0044caf8, 0x0043caf8, 0x0043c9f8, 0x0043c8f9, 0x0042c8f9, 0x0042c7f9, 0x0041c6f9,
|
||||
0x0041c6f9, 0x0040c5fa, 0x003ec3f9, 0x003dc2fa, 0x003bc1fa, 0x0039c0fa, 0x0038bff9,
|
||||
0x0036bff9, 0x0035bef9, 0x0034bdf8, 0x0033bcf9, 0x0033bafa, 0x0032b9fb, 0x0032b8fc,
|
||||
0x0030b7fa, 0x002eb6f8, 0x002db5f7, 0x002bb4f5, 0x002bb4f6, 0x002bb3f7, 0x002bb2f8,
|
||||
0x002bb1f8, 0x0022aff9, 0x0019acfa, 0x001eadf7, 0x0024aef3, 0x0020adf5, 0x001dabf6,
|
||||
0x001fabf6, 0x0020aaf5, 0x001fa9f6, 0x001ea8f7, 0x001da6f7, 0x001ca5f8, 0x001ca4f8,
|
||||
0x001ba3f9, 0x001ba3f9, 0x001ba2f9, 0x0019a1f9, 0x0018a0f8, 0x0017a0f8, 0x00169ff8,
|
||||
0x00159ef7, 0x00149df7, 0x00139cf6, 0x00129bf5, 0x00129bf5, 0x00129bf5, 0x00129bf5,
|
||||
0x0055d0f9, 0x0053d0fa, 0x0051d0fa, 0x004fcffa, 0x004dcffa, 0x004bcefa, 0x0049cdf9,
|
||||
0x0046ccf9, 0x0044caf8, 0x0043caf8, 0x0043c9f8, 0x0043c8f9, 0x0042c8f9, 0x0042c7f9,
|
||||
0x0041c6f9, 0x0041c6f9, 0x0040c5fa, 0x003ec3f9, 0x003dc2fa, 0x003bc1fa, 0x0039c0fa,
|
||||
0x0038bff9, 0x0036bff9, 0x0035bef9, 0x0034bdf8, 0x0033bcf9, 0x0033bafa, 0x0032b9fb,
|
||||
0x0032b8fc, 0x0030b7fa, 0x002eb6f8, 0x002db5f7, 0x002bb4f5, 0x002bb4f6, 0x002bb3f7,
|
||||
0x002bb2f8, 0x002bb1f8, 0x0022aff9, 0x0019acfa, 0x001eadf7, 0x0024aef3, 0x0020adf5,
|
||||
0x001dabf6, 0x001fabf6, 0x0020aaf5, 0x001fa9f6, 0x001ea8f7, 0x001da6f7, 0x001ca5f8,
|
||||
0x001ca4f8, 0x001ba3f9, 0x001ba3f9, 0x001ba2f9, 0x0019a1f9, 0x0018a0f8, 0x0017a0f8,
|
||||
0x00169ff8, 0x00159ef7, 0x00149df7, 0x00139cf6, 0x00129bf5, 0x00129bf5, 0x00129bf5,
|
||||
0x00129bf5
|
||||
};
|
||||
|
||||
#define IMG_WIDTH 64ULL
|
||||
#define IMG_HEIGHT 64ULL
|
||||
#define FORMAT_SIZE 4ULL
|
||||
#define FORMAT PIXEL_FORMAT_XRGB32
|
||||
|
||||
static inline size_t fuzzyCompare(BYTE b1, BYTE b2)
|
||||
{
|
||||
if (b1 > b2)
|
||||
return b1 - b2;
|
||||
return b2 - b1;
|
||||
}
|
||||
|
||||
static BOOL fuzzyCompareImage(const UINT32* crefImage, const BYTE* img, size_t npixels)
|
||||
{
|
||||
size_t totalDelta = 0;
|
||||
|
||||
for (size_t i = 0; i < npixels; i++, crefImage++)
|
||||
{
|
||||
BYTE A = *img++;
|
||||
BYTE R = *img++;
|
||||
BYTE G = *img++;
|
||||
BYTE B = *img++;
|
||||
size_t delta = 0;
|
||||
|
||||
if (A != 0x00)
|
||||
return FALSE;
|
||||
|
||||
delta = fuzzyCompare(R, (*crefImage & 0x00ff0000) >> 16);
|
||||
if (delta > 1)
|
||||
return FALSE;
|
||||
totalDelta += delta;
|
||||
|
||||
delta = fuzzyCompare(G, (*crefImage & 0x0000ff00) >> 8);
|
||||
if (delta > 1)
|
||||
return FALSE;
|
||||
totalDelta += delta;
|
||||
|
||||
delta = fuzzyCompare(B, (*crefImage & 0x0000ff));
|
||||
if (delta > 1)
|
||||
return FALSE;
|
||||
totalDelta += delta;
|
||||
}
|
||||
|
||||
WLog_DBG("test", "totalDelta=%d (npixels=%d)", totalDelta, npixels);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecRemoteFX(int argc, char* argv[])
|
||||
{
|
||||
int rc = -1;
|
||||
REGION16 region = WINPR_C_ARRAY_INIT;
|
||||
RFX_CONTEXT* context = nullptr;
|
||||
BYTE* dest = nullptr;
|
||||
size_t stride = FORMAT_SIZE * IMG_WIDTH;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
/* use default threading options here, pass zero as
|
||||
* ThreadingFlags */
|
||||
context = rfx_context_new(FALSE);
|
||||
if (!context)
|
||||
goto fail;
|
||||
|
||||
dest = calloc(IMG_WIDTH * IMG_HEIGHT, FORMAT_SIZE);
|
||||
if (!dest)
|
||||
goto fail;
|
||||
|
||||
region16_init(®ion);
|
||||
if (!rfx_process_message(context, encodeHeaderSample, sizeof(encodeHeaderSample), 0, 0, dest,
|
||||
FORMAT, stride, IMG_HEIGHT, ®ion))
|
||||
goto fail;
|
||||
|
||||
region16_clear(®ion);
|
||||
if (!rfx_process_message(context, encodeDataSample, sizeof(encodeDataSample), 0, 0, dest,
|
||||
FORMAT, stride, IMG_HEIGHT, ®ion))
|
||||
goto fail;
|
||||
region16_print(®ion);
|
||||
|
||||
if (!fuzzyCompareImage(srefImage, dest, IMG_WIDTH * IMG_HEIGHT))
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
region16_uninit(®ion);
|
||||
rfx_context_free(context);
|
||||
free(dest);
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include "../xcrush.h"
|
||||
|
||||
static const BYTE TEST_BELLS_DATA[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!";
|
||||
|
||||
static const BYTE TEST_BELLS_DATA_XCRUSH[] =
|
||||
"\x66\x6f\x72\x2e\x77\x68\x6f\x6d\x2e\x74\x68\x65\x2e\x62"
|
||||
"\x65\x6c\x6c\x2e\x74\x6f\x6c\x6c\x73\x2c\x2e\x74\x68\x65\x2e\x62"
|
||||
"\x65\x6c\x6c\x2e\x74\x6f\x6c\x6c\x73\x2e\x66\x6f\x72\x2e\x74\x68"
|
||||
"\x65\x65\x21";
|
||||
|
||||
static const BYTE TEST_ISLAND_DATA[] = "No man is an island entire of itself; every man "
|
||||
"is a piece of the continent, a part of the main; "
|
||||
"if a clod be washed away by the sea, Europe "
|
||||
"is the less, as well as if a promontory were, as"
|
||||
"well as any manner of thy friends or of thine "
|
||||
"own were; any man's death diminishes me, "
|
||||
"because I am involved in mankind. "
|
||||
"And therefore never send to know for whom "
|
||||
"the bell tolls; it tolls for thee.";
|
||||
|
||||
static const BYTE TEST_ISLAND_DATA_XCRUSH[] =
|
||||
"\x12\x61\x4e\x6f\x20\x6d\x61\x6e\x20\x69\x73\x20\xf8\xd2\xd8\xc2"
|
||||
"\xdc\xc8\x40\xca\xdc\xe8\xd2\xe4\xca\x40\xde\xcc\x40\xd2\xe8\xe6"
|
||||
"\xca\xd8\xcc\x76\x40\xca\xec\xca\xe4\xf3\xfa\x71\x20\x70\x69\x65"
|
||||
"\x63\xfc\x12\xe8\xd0\xca\x40\xc6\xdf\xfb\xcd\xdf\xd0\x58\x40\xc2"
|
||||
"\x40\xe0\xc2\xe4\xe9\xfe\x63\xec\xc3\x6b\x0b\x4b\x71\xd9\x03\x4b"
|
||||
"\x37\xd7\x31\xb6\x37\xb2\x10\x31\x32\x90\x3b\xb0\xb9\xb4\x32\xb2"
|
||||
"\x10\x30\xbb\xb0\xbc\x90\x31\x3c\x90\x7e\x68\x73\x65\x61\x2c\x20"
|
||||
"\x45\x75\x72\x6f\x70\x65\xf2\x34\x7d\x38\x6c\x65\x73\x73\xf0\x69"
|
||||
"\xcc\x81\xdd\x95\xb1\xb0\x81\x85\xcf\xc0\x94\xe0\xe4\xde\xdb\xe2"
|
||||
"\xb3\x7f\x92\x4e\xec\xae\x4c\xbf\x86\x3f\x06\x0c\x2d\xde\x5d\x96"
|
||||
"\xe6\x57\x2f\x1e\x53\xc9\x03\x33\x93\x4b\x2b\x73\x23\x99\x03\x7f"
|
||||
"\xd2\xb6\x96\xef\x38\x1d\xdb\xbc\x24\x72\x65\x3b\xf5\x5b\xf8\x49"
|
||||
"\x3b\x99\x03\x23\x2b\x0b\xa3\x41\x03\x23\x4b\x6b\x4b\x73\x4f\x96"
|
||||
"\xce\x64\x0d\xbe\x19\x31\x32\xb1\xb0\xba\xb9\xb2\x90\x24\x90\x30"
|
||||
"\xb6\x90\x34\xb7\x3b\x37\xb6\x3b\x79\xd4\xd2\xdd\xec\x18\x6b\x69"
|
||||
"\x6e\x64\x2e\x20\x41\xf7\x33\xcd\x47\x26\x56\x66\xff\x74\x9b\xbd"
|
||||
"\xbf\x04\x0e\x7e\x31\x10\x3a\x37\x90\x35\xb7\x37\xbb\x90\x7d\x81"
|
||||
"\x03\xbb\x43\x7b\x6f\xa8\xe5\x8b\xd0\xf0\xe8\xde\xd8\xd8\xe7\xec"
|
||||
"\xf3\xa7\xe4\x7c\xa7\xe2\x9f\x01\x99\x4b\x80";
|
||||
|
||||
static void test_dump(const char* fkt, const void* generated, size_t generated_size,
|
||||
const void* expected, size_t expected_size)
|
||||
{
|
||||
printf("[%s] output size mismatch: Actual: %" PRIuz ", Expected: %" PRIuz "\n", fkt,
|
||||
generated_size, expected_size);
|
||||
printf("[%s] Actual\n", fkt);
|
||||
winpr_HexDump(fkt, WLOG_INFO, generated, generated_size);
|
||||
printf("[%s] Expected\n", fkt);
|
||||
winpr_HexDump(fkt, WLOG_INFO, expected, expected_size);
|
||||
}
|
||||
|
||||
static BOOL test_compare(const char* fkt, const void* generated, size_t generated_size,
|
||||
const void* expected, size_t expected_size)
|
||||
{
|
||||
if (generated_size != expected_size)
|
||||
{
|
||||
test_dump(fkt, generated, generated_size, expected, expected_size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (memcmp(generated, expected, generated_size) != 0)
|
||||
{
|
||||
test_dump(fkt, generated, generated_size, expected, expected_size);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL test_run(const char* fkt, const void* src, UINT32 src_size, const void* expected,
|
||||
size_t expected_size)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
int status = -1;
|
||||
UINT32 Flags = 0;
|
||||
const BYTE* pDstData = nullptr;
|
||||
BYTE OutputBuffer[65536] = WINPR_C_ARRAY_INIT;
|
||||
UINT32 DstSize = sizeof(OutputBuffer);
|
||||
XCRUSH_CONTEXT* xcrush = xcrush_context_new(TRUE);
|
||||
if (!xcrush)
|
||||
return -1;
|
||||
status = xcrush_compress(xcrush, src, src_size, OutputBuffer, &pDstData, &DstSize, &Flags);
|
||||
printf("[%s] status: %d Flags: 0x%08" PRIX32 " DstSize: %" PRIu32 "\n", fkt, status, Flags,
|
||||
DstSize);
|
||||
|
||||
rc = test_compare(fkt, pDstData, DstSize, expected, expected_size);
|
||||
|
||||
xcrush_context_free(xcrush);
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct test_argument
|
||||
{
|
||||
const char* name;
|
||||
const void* src;
|
||||
UINT32 src_size;
|
||||
const void* expected;
|
||||
size_t expected_size;
|
||||
};
|
||||
|
||||
static const struct test_argument tests[] = {
|
||||
{ "XCrushCompressIsland", TEST_ISLAND_DATA, sizeof(TEST_ISLAND_DATA) - 1,
|
||||
TEST_ISLAND_DATA_XCRUSH, sizeof(TEST_ISLAND_DATA_XCRUSH) - 1 },
|
||||
{ "XCrushCompressBells", TEST_BELLS_DATA, sizeof(TEST_BELLS_DATA) - 1, TEST_BELLS_DATA_XCRUSH,
|
||||
sizeof(TEST_BELLS_DATA_XCRUSH) - 1 }
|
||||
};
|
||||
|
||||
int TestFreeRDPCodecXCrush(int argc, char* argv[])
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
for (size_t x = 0; x < ARRAYSIZE(tests); x++)
|
||||
{
|
||||
const struct test_argument* arg = &tests[x];
|
||||
|
||||
if (!test_run(arg->name, arg->src, arg->src_size, arg->expected, arg->expected_size))
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/zgfx.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
/* Sample from [MS-RDPEGFX] */
|
||||
static const BYTE TEST_FOX_DATA[] = "The quick brown "
|
||||
"fox jumps over t"
|
||||
"he lazy dog";
|
||||
|
||||
static const BYTE TEST_FOX_DATA_SINGLE[] =
|
||||
"\xE0\x04\x54\x68\x65\x20\x71\x75\x69\x63\x6B\x20\x62\x72\x6F\x77"
|
||||
"\x6E\x20\x66\x6F\x78\x20\x6A\x75\x6D\x70\x73\x20\x6F\x76\x65\x72"
|
||||
"\x20\x74\x68\x65\x20\x6C\x61\x7A\x79\x20\x64\x6F\x67";
|
||||
|
||||
static const BYTE TEST_FOX_DATA_MULTIPART[] =
|
||||
"\xE1\x03\x00\x2B\x00\x00\x00\x11\x00\x00\x00\x04\x54\x68\x65\x20"
|
||||
"\x71\x75\x69\x63\x6B\x20\x62\x72\x6F\x77\x6E\x20\x0E\x00\x00\x00"
|
||||
"\x04\x66\x6F\x78\x20\x6A\x75\x6D\x70\x73\x20\x6F\x76\x65\x10\x00"
|
||||
"\x00\x00\x24\x39\x08\x0E\x91\xF8\xD8\x61\x3D\x1E\x44\x06\x43\x79"
|
||||
"\x9C\x02";
|
||||
|
||||
static int test_ZGfxCompressFox(void)
|
||||
{
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
UINT32 Flags = 0;
|
||||
const BYTE* pSrcData = nullptr;
|
||||
UINT32 SrcSize = 0;
|
||||
UINT32 DstSize = 0;
|
||||
BYTE* pDstData = nullptr;
|
||||
ZGFX_CONTEXT* zgfx = nullptr;
|
||||
UINT32 expectedSize = 0;
|
||||
zgfx = zgfx_context_new(TRUE);
|
||||
|
||||
if (!zgfx)
|
||||
return -1;
|
||||
|
||||
SrcSize = sizeof(TEST_FOX_DATA) - 1;
|
||||
pSrcData = (const BYTE*)TEST_FOX_DATA;
|
||||
Flags = 0;
|
||||
expectedSize = sizeof(TEST_FOX_DATA_SINGLE) - 1;
|
||||
status = zgfx_compress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, &Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
printf("flags: 0x%08" PRIX32 " size: %" PRIu32 "\n", Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("test_ZGfxCompressFox: output size mismatch: Actual: %" PRIu32 ", Expected: %" PRIu32
|
||||
"\n",
|
||||
DstSize, expectedSize);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_FOX_DATA_SINGLE, DstSize) != 0)
|
||||
{
|
||||
printf("test_ZGfxCompressFox: output mismatch\n");
|
||||
printf("Actual\n");
|
||||
BitDump(__func__, WLOG_INFO, pDstData, DstSize * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__func__, WLOG_INFO, TEST_FOX_DATA_SINGLE, DstSize * 8, 0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
free(pDstData);
|
||||
zgfx_context_free(zgfx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_ZGfxDecompressFoxSingle(void)
|
||||
{
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
UINT32 Flags = 0;
|
||||
const BYTE* pSrcData = nullptr;
|
||||
UINT32 SrcSize = 0;
|
||||
UINT32 DstSize = 0;
|
||||
BYTE* pDstData = nullptr;
|
||||
ZGFX_CONTEXT* zgfx = nullptr;
|
||||
UINT32 expectedSize = 0;
|
||||
zgfx = zgfx_context_new(TRUE);
|
||||
|
||||
if (!zgfx)
|
||||
return -1;
|
||||
|
||||
SrcSize = sizeof(TEST_FOX_DATA_SINGLE) - 1;
|
||||
pSrcData = (const BYTE*)TEST_FOX_DATA_SINGLE;
|
||||
Flags = 0;
|
||||
expectedSize = sizeof(TEST_FOX_DATA) - 1;
|
||||
status = zgfx_decompress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
printf("flags: 0x%08" PRIX32 " size: %" PRIu32 "\n", Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %" PRIu32
|
||||
", Expected: %" PRIu32 "\n",
|
||||
DstSize, expectedSize);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_FOX_DATA, DstSize) != 0)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output mismatch\n");
|
||||
printf("Actual\n");
|
||||
BitDump(__func__, WLOG_INFO, pDstData, DstSize * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__func__, WLOG_INFO, TEST_FOX_DATA, DstSize * 8, 0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
free(pDstData);
|
||||
zgfx_context_free(zgfx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_ZGfxDecompressFoxMultipart(void)
|
||||
{
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
UINT32 Flags = 0;
|
||||
const BYTE* pSrcData = nullptr;
|
||||
UINT32 SrcSize = 0;
|
||||
UINT32 DstSize = 0;
|
||||
BYTE* pDstData = nullptr;
|
||||
ZGFX_CONTEXT* zgfx = nullptr;
|
||||
UINT32 expectedSize = 0;
|
||||
zgfx = zgfx_context_new(TRUE);
|
||||
|
||||
if (!zgfx)
|
||||
return -1;
|
||||
|
||||
SrcSize = sizeof(TEST_FOX_DATA_MULTIPART) - 1;
|
||||
pSrcData = (const BYTE*)TEST_FOX_DATA_MULTIPART;
|
||||
Flags = 0;
|
||||
expectedSize = sizeof(TEST_FOX_DATA) - 1;
|
||||
status = zgfx_decompress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
printf("flags: 0x%08" PRIX32 " size: %" PRIu32 "\n", Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %" PRIu32
|
||||
", Expected: %" PRIu32 "\n",
|
||||
DstSize, expectedSize);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_FOX_DATA, DstSize) != 0)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output mismatch\n");
|
||||
printf("Actual\n");
|
||||
BitDump(__func__, WLOG_INFO, pDstData, DstSize * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__func__, WLOG_INFO, TEST_FOX_DATA, DstSize * 8, 0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
free(pDstData);
|
||||
zgfx_context_free(zgfx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_ZGfxCompressConsistent(void)
|
||||
{
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
|
||||
UINT32 Flags = 0;
|
||||
const BYTE* pSrcData = nullptr;
|
||||
UINT32 SrcSize = 0;
|
||||
UINT32 DstSize = 0;
|
||||
BYTE* pDstData = nullptr;
|
||||
UINT32 DstSize2 = 0;
|
||||
BYTE* pDstData2 = nullptr;
|
||||
ZGFX_CONTEXT* zgfx = nullptr;
|
||||
UINT32 expectedSize = 0;
|
||||
BYTE BigBuffer[65536];
|
||||
memset(BigBuffer, 0xaa, sizeof(BigBuffer));
|
||||
memcpy(BigBuffer, TEST_FOX_DATA, sizeof(TEST_FOX_DATA) - 1);
|
||||
zgfx = zgfx_context_new(TRUE);
|
||||
|
||||
if (!zgfx)
|
||||
return -1;
|
||||
|
||||
/* Compress */
|
||||
expectedSize = SrcSize = sizeof(BigBuffer);
|
||||
pSrcData = (const BYTE*)BigBuffer;
|
||||
Flags = 0;
|
||||
status = zgfx_compress(zgfx, pSrcData, SrcSize, &pDstData2, &DstSize2, &Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
printf("Compress: flags: 0x%08" PRIX32 " size: %" PRIu32 "\n", Flags, DstSize2);
|
||||
/* Decompress */
|
||||
status = zgfx_decompress(zgfx, pDstData2, DstSize2, &pDstData, &DstSize, Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
printf("Decompress: flags: 0x%08" PRIX32 " size: %" PRIu32 "\n", Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %" PRIu32
|
||||
", Expected: %" PRIu32 "\n",
|
||||
DstSize, expectedSize);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, BigBuffer, DstSize) != 0)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output mismatch\n");
|
||||
printf("Actual\n");
|
||||
BitDump(__func__, WLOG_INFO, pDstData, 64 * 8, 0);
|
||||
printf("...\n");
|
||||
BitDump(__func__, WLOG_INFO, pDstData + DstSize - 64, 64 * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__func__, WLOG_INFO, BigBuffer, 64 * 8, 0);
|
||||
printf("...\n");
|
||||
BitDump(__func__, WLOG_INFO, BigBuffer + DstSize - 64, 64 * 8, 0);
|
||||
printf("Middle Result\n");
|
||||
BitDump(__func__, WLOG_INFO, pDstData2, 64 * 8, 0);
|
||||
printf("...\n");
|
||||
BitDump(__func__, WLOG_INFO, pDstData2 + DstSize2 - 64, 64 * 8, 0);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
free(pDstData);
|
||||
free(pDstData2);
|
||||
zgfx_context_free(zgfx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecZGfx(int argc, char* argv[])
|
||||
{
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
if (test_ZGfxCompressFox() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_ZGfxDecompressFoxSingle() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_ZGfxDecompressFoxMultipart() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_ZGfxCompressConsistent() < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2025 Thincast Technologies GmbH
|
||||
* Copyright 2025 Armin Novak <anovak@thincast.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 <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/file.h>
|
||||
#include <winpr/debug.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include "TestFreeRDPHelpers.h"
|
||||
|
||||
static char* get_path(const char* codec, const char* type, const char* name)
|
||||
{
|
||||
char path[500] = WINPR_C_ARRAY_INIT;
|
||||
(void)snprintf(path, sizeof(path), "%s-%s-%s.bin", codec, type, name);
|
||||
char* s1 = GetCombinedPath(CMAKE_CURRENT_SOURCE_DIR, codec);
|
||||
if (!s1)
|
||||
return nullptr;
|
||||
|
||||
char* s2 = GetCombinedPath(s1, path);
|
||||
free(s1);
|
||||
return s2;
|
||||
}
|
||||
|
||||
static FILE* open_path(const char* codec, const char* type, const char* name, const char* mode)
|
||||
{
|
||||
WINPR_ASSERT(type);
|
||||
WINPR_ASSERT(name);
|
||||
WINPR_ASSERT(mode);
|
||||
|
||||
char* path = get_path(codec, type, name);
|
||||
if (!path)
|
||||
{
|
||||
(void)printf("%s: get_path %s %s failed\n", __func__, type, name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FILE* fp = winpr_fopen(path, mode);
|
||||
if (!fp)
|
||||
{
|
||||
char buffer[128] = WINPR_C_ARRAY_INIT;
|
||||
(void)printf("%s: %s %s: fopen(%s, %s) failed: %s\n", __func__, type, name, path, mode,
|
||||
winpr_strerror(errno, buffer, sizeof(buffer)));
|
||||
}
|
||||
free(path);
|
||||
return fp;
|
||||
}
|
||||
|
||||
void* test_codec_helper_read_data(const char* codec, const char* type, const char* name,
|
||||
size_t* plength)
|
||||
{
|
||||
WINPR_ASSERT(type);
|
||||
WINPR_ASSERT(name);
|
||||
WINPR_ASSERT(plength);
|
||||
|
||||
void* rc = nullptr;
|
||||
void* cmp = nullptr;
|
||||
|
||||
*plength = 0;
|
||||
FILE* fp = open_path(codec, type, name, "rb");
|
||||
if (!fp)
|
||||
goto fail;
|
||||
|
||||
if (_fseeki64(fp, 0, SEEK_END) != 0)
|
||||
goto fail;
|
||||
|
||||
const size_t pos = _ftelli64(fp);
|
||||
|
||||
if (_fseeki64(fp, 0, SEEK_SET) != 0)
|
||||
goto fail;
|
||||
|
||||
cmp = calloc(pos, 1);
|
||||
if (!cmp)
|
||||
goto fail;
|
||||
|
||||
if (fread(cmp, 1, pos, fp) != pos)
|
||||
goto fail;
|
||||
|
||||
*plength = pos;
|
||||
rc = cmp;
|
||||
cmp = nullptr;
|
||||
|
||||
fail:
|
||||
(void)printf("%s: [%s] %s %s -> %p\n", __func__, codec, type, name, rc);
|
||||
free(cmp);
|
||||
if (fp)
|
||||
(void)fclose(fp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void test_codec_helper_write_data(const char* codec, const char* type, const char* name,
|
||||
const void* data, size_t length)
|
||||
{
|
||||
FILE* fp = open_path(codec, type, name, "wb");
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
if (fwrite(data, 1, length, fp) != length)
|
||||
goto fail;
|
||||
|
||||
fail:
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
bool test_codec_helper_compare(const char* codec, const char* type, const char* name,
|
||||
const void* data, size_t length)
|
||||
{
|
||||
bool rc = false;
|
||||
size_t cmplen = 0;
|
||||
void* cmp = test_codec_helper_read_data(codec, type, name, &cmplen);
|
||||
if (!cmp)
|
||||
goto fail;
|
||||
if (cmplen != length)
|
||||
{
|
||||
(void)printf("%s: [%s] %s %s: length mismatch: %" PRIuz " vs %" PRIuz "\n", __func__, codec,
|
||||
type, name, cmplen, length);
|
||||
goto fail;
|
||||
}
|
||||
if (memcmp(data, cmp, length) != 0)
|
||||
{
|
||||
(void)printf("%s: [%s] %s %s: data mismatch\n", __func__, codec, type, name);
|
||||
winpr_HexDump(__func__, WLOG_WARN, data, length);
|
||||
winpr_HexDump(__func__, WLOG_WARN, cmp, cmplen);
|
||||
goto fail;
|
||||
}
|
||||
rc = true;
|
||||
fail:
|
||||
(void)printf("%s: [%s] %s %s -> %s\n", __func__, codec, type, name, rc ? "SUCCESS" : "FAILED");
|
||||
free(cmp);
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2025 Thincast Technologies GmbH
|
||||
* Copyright 2025 Armin Novak <anovak@thincast.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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void* test_codec_helper_read_data(const char* codec, const char* type, const char* name,
|
||||
size_t* plength);
|
||||
void test_codec_helper_write_data(const char* codec, const char* type, const char* name,
|
||||
const void* data, size_t length);
|
||||
bool test_codec_helper_compare(const char* codec, const char* type, const char* name,
|
||||
const void* data, size_t length);
|
||||
@@ -0,0 +1,876 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 Thincast Technologies GmbH
|
||||
* Copyright 2014 Hardening <contact@hardening-consulting.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 <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/codec/region.h>
|
||||
|
||||
static BOOL compareRectangles(const RECTANGLE_16* src1, const RECTANGLE_16* src2, int nb)
|
||||
{
|
||||
for (int i = 0; i < nb; i++, src1++, src2++)
|
||||
{
|
||||
if (memcmp(src1, src2, sizeof(RECTANGLE_16)) != 0)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"expecting rect %d (%" PRIu16 ",%" PRIu16 "-%" PRIu16 ",%" PRIu16
|
||||
") and have (%" PRIu16 ",%" PRIu16 "-%" PRIu16 ",%" PRIu16 ")\n",
|
||||
i, src2->left, src2->top, src2->right, src2->bottom, src1->left,
|
||||
src1->top, src1->right, src1->bottom);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int test_basic(void)
|
||||
{
|
||||
REGION16 region = WINPR_C_ARRAY_INIT;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
/* R1 + R2 ==> disjointed rects */
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r2 = { 150, 301, 250, 401 };
|
||||
RECTANGLE_16 r1_r2[] = { { 0, 101, 200, 201 }, { 150, 301, 250, 401 } };
|
||||
/* r1 */
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 1 || memcmp(rects, &r1, sizeof(RECTANGLE_16)) != 0)
|
||||
goto out;
|
||||
|
||||
/* r1 + r2 */
|
||||
if (!region16_union_rect(®ion, ®ion, &r2))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 2 ||
|
||||
!compareRectangles(rects, r1_r2, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
/* clear region */
|
||||
region16_clear(®ion);
|
||||
region16_rects(®ion, &nbRects);
|
||||
|
||||
if (nbRects)
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r3(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r3 = { 150, 151, 250, 251 };
|
||||
RECTANGLE_16 r1_r3[] = { { 0, 101, 200, 151 }, { 0, 151, 250, 201 }, { 150, 201, 250, 251 } };
|
||||
region16_init(®ion);
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+ +-----+
|
||||
* || r1 | | |
|
||||
* || +-+------+ +-----+--------+
|
||||
* || | r3 | | |
|
||||
* |+---+ | ====> +-----+--------+
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
*/
|
||||
|
||||
/* R1 + R3 */
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 ||
|
||||
!compareRectangles(rects, r1_r3, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
/* R3 + R1 */
|
||||
region16_clear(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 ||
|
||||
!compareRectangles(rects, r1_r3, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r9_r10(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* | +---+ +---+
|
||||
* |+--|r10|-+ +--+---+-+
|
||||
* ||r9| | | | |
|
||||
* || | | | | |
|
||||
* || | | | =====> | |
|
||||
* || | | | | |
|
||||
* || | | | | |
|
||||
* |+--| |-+ +--+---+-+
|
||||
* | +---+ +---+
|
||||
*/
|
||||
RECTANGLE_16 r9 = { 0, 100, 400, 200 };
|
||||
RECTANGLE_16 r10 = { 200, 0, 300, 300 };
|
||||
RECTANGLE_16 r9_r10[] = {
|
||||
{ 200, 0, 300, 100 },
|
||||
{ 0, 100, 400, 200 },
|
||||
{ 200, 200, 300, 300 },
|
||||
};
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r9))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r10))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 ||
|
||||
!compareRectangles(rects, r9_r10, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r5(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r5 = { 150, 121, 300, 131 };
|
||||
RECTANGLE_16 r1_r5[] = { { 0, 101, 200, 121 }, { 0, 121, 300, 131 }, { 0, 131, 200, 201 } };
|
||||
region16_init(®ion);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+--------+ +--------+
|
||||
* || r1 | | |
|
||||
* || +--+----+ +--------+----+
|
||||
* || | r5 | =====> | |
|
||||
* || +-------+ +--------+----+
|
||||
* || | | |
|
||||
* |+--------+ +--------+
|
||||
* |
|
||||
*
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r5))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 ||
|
||||
!compareRectangles(rects, r1_r5, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r6(void)
|
||||
{
|
||||
REGION16 region = WINPR_C_ARRAY_INIT;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r6 = { 150, 121, 170, 131 };
|
||||
region16_init(®ion);
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+--------+ +--------+
|
||||
* || r1 | | |
|
||||
* || +--+ | | |
|
||||
* || |r6| | =====> | |
|
||||
* || +--+ | | |
|
||||
* || | | |
|
||||
* |+--------+ +--------+
|
||||
* |
|
||||
*/
|
||||
region16_clear(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r6))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 1 ||
|
||||
!compareRectangles(rects, &r1, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r2_r4(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r2 = { 150, 301, 250, 401 };
|
||||
RECTANGLE_16 r4 = { 150, 251, 250, 301 };
|
||||
RECTANGLE_16 r1_r2_r4[] = { { 0, 101, 200, 201 }, { 150, 251, 250, 401 } };
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+ +-----+
|
||||
* || r1 | | |
|
||||
* || | | |
|
||||
* || | | |
|
||||
* |+-----+ ====> +-----+
|
||||
* |
|
||||
* | +--------+ +--------+
|
||||
* | | r4 | | |
|
||||
* | +--------+ | |
|
||||
* | | r2 | | |
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
*
|
||||
*/
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r2))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r4))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 2 ||
|
||||
!compareRectangles(rects, r1_r2_r4, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r7_r8(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r7 = { 300, 101, 500, 201 };
|
||||
RECTANGLE_16 r8 = { 150, 121, 400, 131 };
|
||||
RECTANGLE_16 r1_r7_r8[] = {
|
||||
{ 0, 101, 200, 121 }, { 300, 101, 500, 121 }, { 0, 121, 500, 131 },
|
||||
{ 0, 131, 200, 201 }, { 300, 131, 500, 201 },
|
||||
};
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+--------+ +--------+ +--------+ +--------+
|
||||
* || r1 | | r7 | | | | |
|
||||
* || +------------+ | +--------+---+--------+
|
||||
* || | r8 | | =====> | |
|
||||
* || +------------+ | +--------+---+--------+
|
||||
* || | | | | | | |
|
||||
* |+--------+ +--------+ +--------+ +--------+
|
||||
* |
|
||||
*/
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r7))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r8))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 5 ||
|
||||
!compareRectangles(rects, r1_r7_r8, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
region16_clear(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r8))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r7))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 5 ||
|
||||
!compareRectangles(rects, r1_r7_r8, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
region16_clear(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r8))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r7))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 5 ||
|
||||
!compareRectangles(rects, r1_r7_r8, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r2_r3_r4(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r2 = { 150, 301, 250, 401 };
|
||||
RECTANGLE_16 r3 = { 150, 151, 250, 251 };
|
||||
RECTANGLE_16 r4 = { 150, 251, 250, 301 };
|
||||
RECTANGLE_16 r1_r2_r3[] = {
|
||||
{ 0, 101, 200, 151 }, { 0, 151, 250, 201 }, { 150, 201, 250, 251 }, { 150, 301, 250, 401 }
|
||||
};
|
||||
RECTANGLE_16 r1_r2_r3_r4[] = { { 0, 101, 200, 151 },
|
||||
{ 0, 151, 250, 201 },
|
||||
{ 150, 201, 250, 401 } };
|
||||
region16_init(®ion);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+ +-----+
|
||||
* || r1 | | |
|
||||
* || +-+------+ +-----+--------+
|
||||
* || | r3 | | |
|
||||
* |+---+ | ====> +-----+--------+
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
* | +--------+ +--------+
|
||||
* | | r2 | | |
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r2))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 4 || !compareRectangles(rects, r1_r2_r3, 4))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+ +-----+
|
||||
* || | | |
|
||||
* |+-----+--------+ +-----+--------+
|
||||
* || | ==> | |
|
||||
* |+-----+--------+ +-----+--------+
|
||||
* | | | | |
|
||||
* | +--------+ | |
|
||||
* | | + r4 | | |
|
||||
* | +--------+ | |
|
||||
* | | | | |
|
||||
* | | | | |
|
||||
* | +--------+ +--------+
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r4))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r2_r3_r4, 3))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_from_weston(void)
|
||||
{
|
||||
/*
|
||||
* 0: 0,0 -> 640,32 (w=640 h=32)
|
||||
* 1: 236,169 -> 268,201 (w=32 h=32)
|
||||
* 2: 246,258 -> 278,290 (w=32 h=32)
|
||||
*/
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 0, 640, 32 };
|
||||
RECTANGLE_16 r2 = { 236, 169, 268, 201 };
|
||||
RECTANGLE_16 r3 = { 246, 258, 278, 290 };
|
||||
RECTANGLE_16 r1_r2_r3[] = { { 0, 0, 640, 32 }, { 236, 169, 268, 201 }, { 246, 258, 278, 290 } };
|
||||
region16_init(®ion);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |+-------------------------------------------------------------+
|
||||
* || r1 |
|
||||
* |+-------------------------------------------------------------+
|
||||
* |
|
||||
* | +---------------+
|
||||
* | | r2 |
|
||||
* | +---------------+
|
||||
* |
|
||||
* | +---------------+
|
||||
* | | r3 |
|
||||
* | +---------------+
|
||||
* |
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r2))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(®ion, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 3 || !compareRectangles(rects, r1_r2_r3, 3))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_inter_r3(void)
|
||||
{
|
||||
REGION16 region;
|
||||
REGION16 intersection;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r3 = { 150, 151, 250, 251 };
|
||||
RECTANGLE_16 r1_inter_r3[] = {
|
||||
{ 150, 151, 200, 201 },
|
||||
};
|
||||
region16_init(®ion);
|
||||
region16_init(&intersection);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+
|
||||
* || r1 |
|
||||
* || +-+------+ +-+
|
||||
* || | r3 | r1&r3 | |
|
||||
* |+---+ | ====> +-+
|
||||
* | | |
|
||||
* | +--------+
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersects_rect(®ion, &r3))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersect_rect(&intersection, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(&intersection, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 1 ||
|
||||
!compareRectangles(rects, r1_inter_r3, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
region16_uninit(&intersection);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_r1_r3_inter_r11(void)
|
||||
{
|
||||
REGION16 region;
|
||||
REGION16 intersection;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 r1 = { 0, 101, 200, 201 };
|
||||
RECTANGLE_16 r3 = { 150, 151, 250, 251 };
|
||||
RECTANGLE_16 r11 = { 170, 151, 600, 301 };
|
||||
RECTANGLE_16 r1_r3_inter_r11[] = {
|
||||
{ 170, 151, 250, 251 },
|
||||
};
|
||||
region16_init(®ion);
|
||||
region16_init(&intersection);
|
||||
|
||||
/*
|
||||
* +===============================================================
|
||||
* |
|
||||
* |+-----+
|
||||
* || |
|
||||
* || +------+
|
||||
* || r1+r3 | (r1+r3) & r11
|
||||
* || +----------------+ +--------+
|
||||
* |+---+ | | | ====> | |
|
||||
* | | | | | | |
|
||||
* | | | | | | |
|
||||
* | +-|------+ | +--------+
|
||||
* | | r11 |
|
||||
* | +----------------+
|
||||
*
|
||||
*
|
||||
* R1+R3 is made of 3 bands, R11 overlap the second and the third band. The
|
||||
* intersection is made of two band that must be reassembled to give only
|
||||
* one
|
||||
*/
|
||||
if (!region16_union_rect(®ion, ®ion, &r1))
|
||||
goto out;
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &r3))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersects_rect(®ion, &r11))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersect_rect(&intersection, ®ion, &r11))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(&intersection, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 1 ||
|
||||
!compareRectangles(rects, r1_r3_inter_r11, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(&intersection);
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_norbert_case(void)
|
||||
{
|
||||
REGION16 region;
|
||||
REGION16 intersection;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 inRectangles[5] = { { 1680, 0, 1920, 242 },
|
||||
{ 294, 242, 971, 776 },
|
||||
{ 1680, 242, 1920, 776 },
|
||||
{ 1680, 776, 1920, 1036 },
|
||||
{ 2, 1040, 53, 1078 } };
|
||||
RECTANGLE_16 screenRect = { 0, 0, 1920, 1080 };
|
||||
RECTANGLE_16 expected_inter_extents = { 2, 0, 1920, 1078 };
|
||||
region16_init(®ion);
|
||||
region16_init(&intersection);
|
||||
|
||||
/*
|
||||
* Consider following as a screen with resolution 1920*1080
|
||||
* | | | | | | |
|
||||
* | |2 |53 |294 |971 |1680 |
|
||||
* | | | | | | |
|
||||
* 0 +=+======================================+======+
|
||||
* | | | |
|
||||
* | | R[0]|
|
||||
* 242 | +-----------+ +------+
|
||||
* | | | | | |
|
||||
* | | | | |
|
||||
* | | R[1]| | R[2]|
|
||||
* 776 | | +-----------+ +------+
|
||||
* | | |
|
||||
* | | R[3]|
|
||||
* 1036 | | +------+
|
||||
* 1040 | +----+
|
||||
* | |R[4]| Union of R[0-4]|
|
||||
* 1078 | +----+ - - - - - - - -+
|
||||
* 1080 |
|
||||
*
|
||||
*
|
||||
* The result is union of R[0] - R[4].
|
||||
* After intersected with the full screen rect, the
|
||||
* result should keep the same.
|
||||
*/
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (!region16_union_rect(®ion, ®ion, &inRectangles[i]))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!compareRectangles(region16_extents(®ion), &expected_inter_extents, 1))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersect_rect(&intersection, ®ion, &screenRect))
|
||||
goto out;
|
||||
|
||||
rects = region16_rects(&intersection, &nbRects);
|
||||
|
||||
if (!rects || nbRects != 5 ||
|
||||
!compareRectangles(rects, inRectangles, WINPR_ASSERTING_INT_CAST(int, nbRects)))
|
||||
goto out;
|
||||
|
||||
if (!compareRectangles(region16_extents(&intersection), &expected_inter_extents, 1))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(&intersection);
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_norbert2_case(void)
|
||||
{
|
||||
REGION16 region;
|
||||
int retCode = -1;
|
||||
const RECTANGLE_16* rects = nullptr;
|
||||
UINT32 nbRects = 0;
|
||||
RECTANGLE_16 rect1 = { 464, 696, 476, 709 };
|
||||
RECTANGLE_16 rect2 = { 0, 0, 1024, 32 };
|
||||
region16_init(®ion);
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &rect1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 1 - region16_union_rect failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(rects = region16_rects(®ion, &nbRects)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 2 - region16_rects failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nbRects != 1)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 3 - expected nbRects == 1 but got %" PRIu32 "\n", __func__,
|
||||
nbRects);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!compareRectangles(&rects[0], &rect1, 1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 4 - compare failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!region16_union_rect(®ion, ®ion, &rect2))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 5 - region16_union_rect failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(rects = region16_rects(®ion, &nbRects)))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 6 - region16_rects failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nbRects != 2)
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 7 - expected nbRects == 2 but got %" PRIu32 "\n", __func__,
|
||||
nbRects);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!compareRectangles(&rects[0], &rect2, 1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 8 - compare failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!compareRectangles(&rects[1], &rect1, 1))
|
||||
{
|
||||
(void)fprintf(stderr, "%s: Error 9 - compare failed\n", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int test_empty_rectangle(void)
|
||||
{
|
||||
REGION16 region;
|
||||
REGION16 intersection;
|
||||
int retCode = -1;
|
||||
RECTANGLE_16 emptyRectangles[3] = { { 0, 0, 0, 0 }, { 10, 10, 10, 11 }, { 10, 10, 11, 10 } };
|
||||
RECTANGLE_16 firstRect = { 0, 0, 100, 100 };
|
||||
RECTANGLE_16 anotherRect = { 100, 100, 200, 200 };
|
||||
RECTANGLE_16 expected_inter_extents = { 0, 0, 0, 0 };
|
||||
region16_init(®ion);
|
||||
region16_init(&intersection);
|
||||
|
||||
/* Check for empty rectangles */
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (!rectangle_is_empty(&emptyRectangles[i]))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check for non-empty rectangles */
|
||||
if (rectangle_is_empty(&firstRect))
|
||||
goto out;
|
||||
|
||||
/* Intersect 2 non-intersect rectangle, result should be empty */
|
||||
if (!region16_union_rect(®ion, ®ion, &firstRect))
|
||||
goto out;
|
||||
|
||||
if (!region16_intersect_rect(®ion, ®ion, &anotherRect))
|
||||
goto out;
|
||||
|
||||
if (!compareRectangles(region16_extents(®ion), &expected_inter_extents, 1))
|
||||
goto out;
|
||||
|
||||
if (!region16_is_empty(®ion))
|
||||
goto out;
|
||||
|
||||
if (!rectangle_is_empty(region16_extents(&intersection)))
|
||||
goto out;
|
||||
|
||||
retCode = 0;
|
||||
out:
|
||||
region16_uninit(&intersection);
|
||||
region16_uninit(®ion);
|
||||
return retCode;
|
||||
}
|
||||
|
||||
typedef int (*TestFunction)(void);
|
||||
struct UnitaryTest
|
||||
{
|
||||
const char* name;
|
||||
WINPR_ATTR_NODISCARD TestFunction func;
|
||||
};
|
||||
|
||||
static struct UnitaryTest tests[] = { { "Basic trivial tests", test_basic },
|
||||
{ "R1+R3 and R3+R1", test_r1_r3 },
|
||||
{ "R1+R5", test_r1_r5 },
|
||||
{ "R1+R6", test_r1_r6 },
|
||||
{ "R9+R10", test_r9_r10 },
|
||||
{ "R1+R2+R4", test_r1_r2_r4 },
|
||||
{ "R1+R7+R8 in many orders", test_r1_r7_r8 },
|
||||
{ "R1+R2+R3+R4", test_r1_r2_r3_r4 },
|
||||
{ "data from weston", test_from_weston },
|
||||
{ "R1 & R3", test_r1_inter_r3 },
|
||||
{ "(R1+R3)&R11 (band merge)", test_r1_r3_inter_r11 },
|
||||
{ "norbert's case", test_norbert_case },
|
||||
{ "norbert's case 2", test_norbert2_case },
|
||||
{ "empty rectangle case", test_empty_rectangle },
|
||||
|
||||
{ nullptr, nullptr } };
|
||||
|
||||
int TestFreeRDPRegion(int argc, char* argv[])
|
||||
{
|
||||
int testNb = 0;
|
||||
int retCode = -1;
|
||||
WINPR_UNUSED(argc);
|
||||
WINPR_UNUSED(argv);
|
||||
|
||||
for (int i = 0; tests[i].func; i++)
|
||||
{
|
||||
testNb++;
|
||||
(void)fprintf(stderr, "%d: %s\n", testNb, tests[i].name);
|
||||
retCode = tests[i].func();
|
||||
|
||||
if (retCode < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (retCode < 0)
|
||||
(void)fprintf(stderr, "failed for test %d\n", testNb);
|
||||
|
||||
return retCode;
|
||||
}
|
||||
@@ -0,0 +1,467 @@
|
||||
/* https://github.com/ergnoorr/fuzzrdp
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2024 ergnoorr
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#include <freerdp/assistance.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/platform.h>
|
||||
#include <freerdp/codec/interleaved.h>
|
||||
#include <freerdp/codec/planar.h>
|
||||
#include <freerdp/codec/bulk.h>
|
||||
#include <freerdp/codec/clear.h>
|
||||
#include <freerdp/codec/zgfx.h>
|
||||
#include <freerdp/log.h>
|
||||
#include <winpr/bitstream.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/codec/progressive.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/gdi/gdi.h>
|
||||
|
||||
#include "../progressive.h"
|
||||
#include "../mppc.h"
|
||||
#include "../xcrush.h"
|
||||
#include "../ncrush.h"
|
||||
|
||||
static BOOL test_ClearDecompressExample(UINT32 nr, UINT32 width, UINT32 height,
|
||||
const BYTE* pSrcData, const UINT32 SrcSize)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
int status = 0;
|
||||
BYTE* pDstData = calloc(1ull * width * height, 4);
|
||||
CLEAR_CONTEXT* clear = clear_context_new(FALSE);
|
||||
|
||||
WINPR_UNUSED(nr);
|
||||
if (!clear || !pDstData)
|
||||
goto fail;
|
||||
|
||||
status = clear_decompress(clear, pSrcData, SrcSize, width, height, pDstData,
|
||||
PIXEL_FORMAT_XRGB32, 0, 0, 0, width, height, nullptr);
|
||||
// printf("clear_decompress example %" PRIu32 " status: %d\n", nr, status);
|
||||
// fflush(stdout);
|
||||
rc = (status == 0);
|
||||
fail:
|
||||
clear_context_free(clear);
|
||||
free(pDstData);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int TestFreeRDPCodecClear(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
if (Size > UINT32_MAX)
|
||||
return -1;
|
||||
test_ClearDecompressExample(2, 78, 17, Data, (UINT32)Size);
|
||||
test_ClearDecompressExample(3, 64, 24, Data, (UINT32)Size);
|
||||
test_ClearDecompressExample(4, 7, 15, Data, (UINT32)Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int TestFreeRDPCodecXCrush(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
if (Size > UINT32_MAX)
|
||||
return -1;
|
||||
|
||||
const BYTE* OutputBuffer = nullptr;
|
||||
UINT32 DstSize = 0;
|
||||
XCRUSH_CONTEXT* xcrush = xcrush_context_new(TRUE);
|
||||
if (!xcrush)
|
||||
return 0;
|
||||
xcrush_decompress(xcrush, Data, (UINT32)Size, &OutputBuffer, &DstSize, 0);
|
||||
xcrush_context_free(xcrush);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_ZGfxDecompressFoxSingle(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
if (Size > UINT32_MAX)
|
||||
return -1;
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
UINT32 Flags = 0;
|
||||
const BYTE* pSrcData = (const BYTE*)Data;
|
||||
UINT32 SrcSize = (UINT32)Size;
|
||||
UINT32 DstSize = 0;
|
||||
BYTE* pDstData = nullptr;
|
||||
ZGFX_CONTEXT* zgfx = zgfx_context_new(TRUE);
|
||||
|
||||
if (!zgfx)
|
||||
return -1;
|
||||
|
||||
status = zgfx_decompress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
free(pDstData);
|
||||
zgfx_context_free(zgfx);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int TestFreeRDPCodecZGfx(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
test_ZGfxDecompressFoxSingle(Data, Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL test_NCrushDecompressBells(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
if (Size > UINT32_MAX)
|
||||
return FALSE;
|
||||
|
||||
BOOL rc = FALSE;
|
||||
int status = 0;
|
||||
UINT32 Flags = PACKET_COMPRESSED | 2;
|
||||
const BYTE* pSrcData = (const BYTE*)Data;
|
||||
UINT32 SrcSize = (UINT32)Size;
|
||||
UINT32 DstSize = 0;
|
||||
const BYTE* pDstData = nullptr;
|
||||
NCRUSH_CONTEXT* ncrush = ncrush_context_new(FALSE);
|
||||
|
||||
if (!ncrush)
|
||||
return rc;
|
||||
|
||||
status = ncrush_decompress(ncrush, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
ncrush_context_free(ncrush);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int TestFreeRDPCodecNCrush(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
test_NCrushDecompressBells(Data, Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const size_t IMG_WIDTH = 64;
|
||||
static const size_t IMG_HEIGHT = 64;
|
||||
static const size_t FORMAT_SIZE = 4;
|
||||
static const UINT32 FORMAT = PIXEL_FORMAT_XRGB32;
|
||||
|
||||
static int TestFreeRDPCodecRemoteFX(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
int rc = -1;
|
||||
REGION16 region = WINPR_C_ARRAY_INIT;
|
||||
RFX_CONTEXT* context = rfx_context_new(FALSE);
|
||||
BYTE* dest = calloc(IMG_WIDTH * IMG_HEIGHT, FORMAT_SIZE);
|
||||
size_t stride = FORMAT_SIZE * IMG_WIDTH;
|
||||
if (!context)
|
||||
goto fail;
|
||||
if (Size > UINT32_MAX)
|
||||
goto fail;
|
||||
if (stride > UINT32_MAX)
|
||||
goto fail;
|
||||
if (!dest)
|
||||
goto fail;
|
||||
|
||||
region16_init(®ion);
|
||||
if (!rfx_process_message(context, Data, (UINT32)Size, 0, 0, dest, FORMAT, (UINT32)stride,
|
||||
IMG_HEIGHT, ®ion))
|
||||
goto fail;
|
||||
|
||||
region16_clear(®ion);
|
||||
if (!rfx_process_message(context, Data, (UINT32)Size, 0, 0, dest, FORMAT, (UINT32)stride,
|
||||
IMG_HEIGHT, ®ion))
|
||||
goto fail;
|
||||
region16_print(®ion);
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
region16_uninit(®ion);
|
||||
rfx_context_free(context);
|
||||
free(dest);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_MppcDecompressBellsRdp5(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
UINT32 Flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
|
||||
const BYTE* pSrcData = Data;
|
||||
UINT32 SrcSize = (UINT32)Size;
|
||||
UINT32 DstSize = 0;
|
||||
const BYTE* pDstData = nullptr;
|
||||
MPPC_CONTEXT* mppc = mppc_context_new(1, FALSE);
|
||||
|
||||
if (!mppc)
|
||||
return -1;
|
||||
|
||||
status = mppc_decompress(mppc, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
|
||||
fail:
|
||||
mppc_context_free(mppc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_MppcDecompressBellsRdp4(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
if (Size > UINT32_MAX)
|
||||
return -1;
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
UINT32 Flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 0;
|
||||
const BYTE* pSrcData = (const BYTE*)Data;
|
||||
UINT32 SrcSize = (UINT32)Size;
|
||||
UINT32 DstSize = 0;
|
||||
const BYTE* pDstData = nullptr;
|
||||
MPPC_CONTEXT* mppc = mppc_context_new(0, FALSE);
|
||||
|
||||
if (!mppc)
|
||||
return -1;
|
||||
|
||||
status = mppc_decompress(mppc, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
mppc_context_free(mppc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int test_MppcDecompressBufferRdp5(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
if (Size > UINT32_MAX)
|
||||
return -1;
|
||||
int rc = -1;
|
||||
int status = 0;
|
||||
UINT32 Flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
|
||||
const BYTE* pSrcData = (const BYTE*)Data;
|
||||
UINT32 SrcSize = (UINT32)Size;
|
||||
UINT32 DstSize = 0;
|
||||
const BYTE* pDstData = nullptr;
|
||||
MPPC_CONTEXT* mppc = mppc_context_new(1, FALSE);
|
||||
|
||||
if (!mppc)
|
||||
return -1;
|
||||
|
||||
status = mppc_decompress(mppc, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
|
||||
if (status < 0)
|
||||
goto fail;
|
||||
|
||||
rc = 0;
|
||||
fail:
|
||||
mppc_context_free(mppc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int TestFreeRDPCodecMppc(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
test_MppcDecompressBellsRdp5(Data, Size);
|
||||
test_MppcDecompressBellsRdp4(Data, Size);
|
||||
test_MppcDecompressBufferRdp5(Data, Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL progressive_decode(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
BOOL res = FALSE;
|
||||
int rc = 0;
|
||||
BYTE* resultData = nullptr;
|
||||
UINT32 ColorFormat = PIXEL_FORMAT_BGRX32;
|
||||
REGION16 invalidRegion = WINPR_C_ARRAY_INIT;
|
||||
UINT32 scanline = 4240;
|
||||
UINT32 width = 1060;
|
||||
UINT32 height = 827;
|
||||
if (Size > UINT32_MAX)
|
||||
return FALSE;
|
||||
|
||||
PROGRESSIVE_CONTEXT* progressiveDec = progressive_context_new(FALSE);
|
||||
|
||||
region16_init(&invalidRegion);
|
||||
if (!progressiveDec)
|
||||
goto fail;
|
||||
|
||||
resultData = calloc(scanline, height);
|
||||
if (!resultData)
|
||||
goto fail;
|
||||
|
||||
rc = progressive_create_surface_context(progressiveDec, 0, width, height);
|
||||
if (rc <= 0)
|
||||
goto fail;
|
||||
|
||||
rc = progressive_decompress(progressiveDec, Data, (UINT32)Size, resultData, ColorFormat,
|
||||
scanline, 0, 0, &invalidRegion, 0, 0);
|
||||
if (rc < 0)
|
||||
goto fail;
|
||||
|
||||
res = TRUE;
|
||||
fail:
|
||||
region16_uninit(&invalidRegion);
|
||||
progressive_context_free(progressiveDec);
|
||||
free(resultData);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int TestFreeRDPCodecProgressive(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
progressive_decode(Data, Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL i_run_encode_decode(UINT16 bpp, BITMAP_INTERLEAVED_CONTEXT* encoder,
|
||||
BITMAP_INTERLEAVED_CONTEXT* decoder, const uint8_t* Data,
|
||||
size_t Size)
|
||||
{
|
||||
BOOL rc2 = FALSE;
|
||||
BOOL rc = 0;
|
||||
const UINT32 w = 64;
|
||||
const UINT32 h = 64;
|
||||
const UINT32 x = 0;
|
||||
const UINT32 y = 0;
|
||||
const UINT32 format = PIXEL_FORMAT_RGBX32;
|
||||
const size_t step = (w + 13ull) * 4ull;
|
||||
const size_t SrcSize = step * h;
|
||||
BYTE* pSrcData = calloc(1, SrcSize);
|
||||
BYTE* pDstData = calloc(1, SrcSize);
|
||||
BYTE* tmp = calloc(1, SrcSize);
|
||||
|
||||
WINPR_UNUSED(encoder);
|
||||
if (!pSrcData || !pDstData || !tmp)
|
||||
goto fail;
|
||||
|
||||
if (Size > UINT32_MAX)
|
||||
goto fail;
|
||||
|
||||
winpr_RAND(pSrcData, SrcSize);
|
||||
|
||||
if (!bitmap_interleaved_context_reset(decoder))
|
||||
goto fail;
|
||||
|
||||
rc = interleaved_decompress(decoder, Data, (UINT32)Size, w, h, bpp, pDstData, format, step, x,
|
||||
y, w, h, nullptr);
|
||||
|
||||
if (!rc)
|
||||
goto fail;
|
||||
|
||||
rc2 = TRUE;
|
||||
fail:
|
||||
free(pSrcData);
|
||||
free(pDstData);
|
||||
free(tmp);
|
||||
return rc2;
|
||||
}
|
||||
|
||||
static int TestFreeRDPCodecInterleaved(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
int rc = -1;
|
||||
BITMAP_INTERLEAVED_CONTEXT* decoder = bitmap_interleaved_context_new(FALSE);
|
||||
|
||||
if (!decoder)
|
||||
goto fail;
|
||||
|
||||
i_run_encode_decode(24, nullptr, decoder, Data, Size);
|
||||
i_run_encode_decode(16, nullptr, decoder, Data, Size);
|
||||
i_run_encode_decode(15, nullptr, decoder, Data, Size);
|
||||
rc = 0;
|
||||
fail:
|
||||
bitmap_interleaved_context_free(decoder);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL RunTestPlanar(BITMAP_PLANAR_CONTEXT* planar, const BYTE* srcBitmap,
|
||||
const UINT32 srcFormat, const UINT32 dstFormat, const UINT32 width,
|
||||
const UINT32 height, const uint8_t* Data, size_t Size)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
WINPR_UNUSED(srcBitmap);
|
||||
WINPR_UNUSED(srcFormat);
|
||||
if (Size > UINT32_MAX)
|
||||
return FALSE;
|
||||
UINT32 dstSize = (UINT32)Size;
|
||||
const BYTE* compressedBitmap = Data;
|
||||
BYTE* decompressedBitmap =
|
||||
(BYTE*)calloc(height, 1ull * width * FreeRDPGetBytesPerPixel(dstFormat));
|
||||
rc = TRUE;
|
||||
|
||||
if (!decompressedBitmap)
|
||||
goto fail;
|
||||
|
||||
if (!planar_decompress(planar, compressedBitmap, dstSize, width, height, decompressedBitmap,
|
||||
dstFormat, 0, 0, 0, width, height, FALSE))
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
free(decompressedBitmap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static BOOL TestPlanar(const UINT32 format, const uint8_t* Data, size_t Size)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
const DWORD planarFlags = PLANAR_FORMAT_HEADER_NA | PLANAR_FORMAT_HEADER_RLE;
|
||||
BITMAP_PLANAR_CONTEXT* planar = freerdp_bitmap_planar_context_new(planarFlags, 64, 64);
|
||||
|
||||
if (!planar)
|
||||
goto fail;
|
||||
|
||||
RunTestPlanar(planar, nullptr, PIXEL_FORMAT_RGBX32, format, 64, 64, Data, Size);
|
||||
|
||||
RunTestPlanar(planar, nullptr, PIXEL_FORMAT_RGB16, format, 32, 32, Data, Size);
|
||||
|
||||
rc = TRUE;
|
||||
fail:
|
||||
freerdp_bitmap_planar_context_free(planar);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int TestFreeRDPCodecPlanar(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
TestPlanar(0, Data, Size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size)
|
||||
{
|
||||
if (Size < 4)
|
||||
return 0;
|
||||
|
||||
TestFreeRDPCodecClear(Data, Size);
|
||||
TestFreeRDPCodecXCrush(Data, Size);
|
||||
TestFreeRDPCodecZGfx(Data, Size);
|
||||
TestFreeRDPCodecNCrush(Data, Size);
|
||||
TestFreeRDPCodecRemoteFX(Data, Size);
|
||||
TestFreeRDPCodecMppc(Data, Size);
|
||||
TestFreeRDPCodecProgressive(Data, Size);
|
||||
TestFreeRDPCodecInterleaved(Data, Size);
|
||||
TestFreeRDPCodecPlanar(Data, Size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
cursor dumps created from a connection to FreeRDP shadow server.
|
||||
|
||||
target machine was a debian 12 with openbox.
|
||||
|
||||
So licensing of image, ... according to the license of the default cursor theme
|
||||
@@ -0,0 +1,140 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_c_file
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#include "cursor_dump_00000000.h"
|
||||
|
||||
static uint8_t andmask[] = { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0x80, 0xe3, 0x80, 0xe3,
|
||||
0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80, 0xe3, 0x80,
|
||||
0xe3, 0x80, 0xc1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 };
|
||||
|
||||
static uint8_t xormask[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00
|
||||
};
|
||||
|
||||
const gdiPalette cursor_dump_00000000_palette = {
|
||||
.format = 0,
|
||||
.palette = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000 }
|
||||
};
|
||||
|
||||
const rdpPointer cursor_dump_00000000_pointer = { .size = 0,
|
||||
.New = nullptr,
|
||||
.Free = nullptr,
|
||||
.Set = nullptr,
|
||||
.SetNull = nullptr,
|
||||
.SetDefault = nullptr,
|
||||
.SetPosition = nullptr,
|
||||
.paddingA = { 0 },
|
||||
.xPos = 0,
|
||||
.yPos = 0,
|
||||
.width = 9,
|
||||
.height = 16,
|
||||
.xorBpp = 24,
|
||||
.lengthAndMask = ARRAYSIZE(andmask),
|
||||
.lengthXorMask = ARRAYSIZE(xormask),
|
||||
.xorMaskData = xormask,
|
||||
.andMaskData = andmask,
|
||||
.paddingB = { 0 } };
|
||||
|
||||
const uint8_t cursor_dump_00000000_image_bgra32[] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_header
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/graphics.h>
|
||||
|
||||
extern const gdiPalette cursor_dump_00000000_palette;
|
||||
extern const rdpPointer cursor_dump_00000000_pointer;
|
||||
extern const uint8_t cursor_dump_00000000_image_bgra32[];
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 136 B |
@@ -0,0 +1,333 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_c_file
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#include "cursor_dump_00000001.h"
|
||||
|
||||
static uint8_t andmask[] = {
|
||||
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00, 0xff, 0xc0, 0xff, 0x00,
|
||||
0xff, 0xc0, 0xff, 0x00, 0xff, 0xc0, 0xff, 0x00, 0xff, 0xc0, 0xff, 0x00, 0xff, 0xc0, 0xff, 0x00,
|
||||
0xff, 0xc0, 0xff, 0x00, 0xff, 0xc0, 0xff, 0x00, 0xfc, 0x00, 0x07, 0x00, 0xf8, 0x00, 0x07, 0x00,
|
||||
0xfc, 0x00, 0x0f, 0x00, 0xfe, 0x00, 0x1f, 0x00, 0xff, 0x00, 0x3f, 0x00, 0xff, 0x00, 0x7f, 0x00,
|
||||
0xf8, 0x00, 0x07, 0x00, 0xf0, 0x00, 0x03, 0x00, 0xf0, 0x00, 0x03, 0x00, 0xf0, 0x00, 0x07, 0x00,
|
||||
0xf0, 0x00, 0x07, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00
|
||||
};
|
||||
|
||||
static uint8_t xormask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0xc9, 0xc9, 0xf1, 0xf1, 0xf1, 0xff, 0xff, 0xff, 0xf6,
|
||||
0xf6, 0xf6, 0xa0, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9,
|
||||
0xf9, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x15, 0x15, 0x15, 0xf6, 0xf6, 0xf6, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03,
|
||||
0x03, 0x03, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc,
|
||||
0xfc, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03,
|
||||
0x03, 0x03, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc,
|
||||
0xfc, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03,
|
||||
0x03, 0x03, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x2a, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0xfc, 0xfc,
|
||||
0xfc, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0xfc, 0xfc, 0xfc, 0x1d, 0x1d, 0x1d,
|
||||
0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, 0x22, 0x24, 0x24, 0x24, 0x29, 0x29, 0x29, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xf1, 0xf1, 0xf1,
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xef, 0xef, 0xef, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03,
|
||||
0x03, 0x03, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf9, 0xf9,
|
||||
0xf9, 0xf9, 0xf9, 0xf9, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xf3, 0xf3, 0xf3, 0x4d, 0x4d, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x3b, 0x3b, 0x3b, 0xee, 0xee, 0xee, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0xf2, 0xf2,
|
||||
0x4d, 0x4d, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x3b, 0x3b, 0xee, 0xee, 0xee, 0xab, 0xab,
|
||||
0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0xf2, 0xf2, 0x4e, 0x4e, 0x4e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x3b, 0x3b,
|
||||
0xee, 0xee, 0xee, 0xa6, 0xa6, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x99, 0x99, 0x99, 0xf0, 0xf0, 0xf0, 0x4f, 0x4f, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x3b, 0x3b, 0x3b, 0xed, 0xed, 0xed, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
|
||||
0x1c, 0x1c, 0x22, 0x22, 0x22, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x6e, 0x6e, 0x6e, 0xf2, 0xf2,
|
||||
0xf2, 0x4e, 0x4e, 0x4e, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0xf0, 0xf0, 0xf0, 0x76, 0x76, 0x76,
|
||||
0x1f, 0x1f, 0x1f, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd5, 0xd5, 0xd5, 0xf5, 0xf5, 0xf5, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe8, 0xe8, 0xe8, 0x6d, 0x6d, 0x6d, 0xe3,
|
||||
0xe3, 0xe3, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||
0xf0, 0xf5, 0xf5, 0xf5, 0xb4, 0xb4, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0xf1, 0xf1, 0x19,
|
||||
0x19, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0xf9, 0xf9, 0xf9, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xf1, 0xf1, 0xf1, 0x1f, 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x08, 0x08, 0x08, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xf9,
|
||||
0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xdf, 0xdf, 0xdf, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const gdiPalette cursor_dump_00000001_palette = {
|
||||
.format = 0,
|
||||
.palette = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000 }
|
||||
};
|
||||
|
||||
const rdpPointer cursor_dump_00000001_pointer = { .size = 0,
|
||||
.New = nullptr,
|
||||
.Free = nullptr,
|
||||
.Set = nullptr,
|
||||
.SetNull = nullptr,
|
||||
.SetDefault = nullptr,
|
||||
.SetPosition = nullptr,
|
||||
.paddingA = { 0 },
|
||||
.xPos = 0,
|
||||
.yPos = 0,
|
||||
.width = 24,
|
||||
.height = 24,
|
||||
.xorBpp = 24,
|
||||
.lengthAndMask = ARRAYSIZE(andmask),
|
||||
.lengthXorMask = ARRAYSIZE(xormask),
|
||||
.xorMaskData = xormask,
|
||||
.andMaskData = andmask,
|
||||
.paddingB = { 0 } };
|
||||
|
||||
const uint8_t cursor_dump_00000001_image_bgra32[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xe7, 0xe7, 0xe7, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xfa, 0xfa, 0xff,
|
||||
0xdf, 0xdf, 0xdf, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xf1, 0xf1, 0xf1, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0xfc, 0xfc, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xf1, 0xf1, 0xf1, 0xff, 0x19, 0x19, 0x19, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x06, 0x06, 0x06, 0xff,
|
||||
0xf9, 0xf9, 0xf9, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xd5, 0xd5, 0xd5, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff,
|
||||
0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xe8, 0xe8, 0xe8, 0xff,
|
||||
0x6d, 0x6d, 0x6d, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff,
|
||||
0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf5, 0xf5, 0xf5, 0xff,
|
||||
0xb4, 0xb4, 0xb4, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0xff, 0x22, 0x22, 0x22, 0xff, 0x21, 0x21, 0x21, 0xff,
|
||||
0x21, 0x21, 0x21, 0xff, 0x6e, 0x6e, 0x6e, 0xff, 0xf2, 0xf2, 0xf2, 0xff, 0x4e, 0x4e, 0x4e, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x3e, 0x3e, 0x3e, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0x76, 0x76, 0x76, 0xff,
|
||||
0x1f, 0x1f, 0x1f, 0xff, 0x21, 0x21, 0x21, 0xff, 0x21, 0x21, 0x21, 0xff, 0x16, 0x16, 0x16, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x99, 0x99, 0x99, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0x4f, 0x4f, 0x4f, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xed, 0xed, 0xed, 0xff,
|
||||
0x88, 0x88, 0x88, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xf2, 0xf2, 0xf2, 0xff, 0x4e, 0x4e, 0x4e, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff,
|
||||
0xee, 0xee, 0xee, 0xff, 0xa6, 0xa6, 0xa6, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf2, 0xf2, 0xf2, 0xff,
|
||||
0x4d, 0x4d, 0x4d, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x3b, 0x3b, 0x3b, 0xff, 0xee, 0xee, 0xee, 0xff, 0xab, 0xab, 0xab, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf3, 0xf3, 0xf3, 0xff, 0x4d, 0x4d, 0x4d, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xee, 0xee, 0xee, 0xff, 0xab, 0xab, 0xab, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xfb, 0xfb, 0xfb, 0xff, 0xfb, 0xfb, 0xfb, 0xff, 0xf1, 0xf1, 0xf1, 0xff,
|
||||
0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xef, 0xef, 0xef, 0xff, 0x03, 0x03, 0x03, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0xef, 0xef, 0xef, 0xff, 0xf0, 0xf0, 0xf0, 0xff,
|
||||
0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf9, 0xf9, 0xf9, 0xff, 0xf9, 0xf9, 0xf9, 0xff,
|
||||
0xab, 0xab, 0xab, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x2a, 0x2a, 0xff, 0x22, 0x22, 0x22, 0xff,
|
||||
0x21, 0x21, 0x21, 0xff, 0x21, 0x21, 0x21, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x03, 0x03, 0x03, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x1d, 0x1d, 0x1d, 0xff,
|
||||
0x20, 0x20, 0x20, 0xff, 0x21, 0x21, 0x21, 0xff, 0x22, 0x22, 0x22, 0xff, 0x24, 0x24, 0x24, 0xff,
|
||||
0x29, 0x29, 0x29, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xff, 0x03, 0x03, 0x03, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xff, 0x03, 0x03, 0x03, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xff, 0x03, 0x03, 0x03, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xff, 0x03, 0x03, 0x03, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xff, 0x03, 0x03, 0x03, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x03, 0x03, 0x03, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xff, 0x16, 0x16, 0x16, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x15, 0x15, 0x15, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc9, 0xc9, 0xc9, 0xff, 0xf1, 0xf1, 0xf1, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0xa0, 0xa0, 0xa0, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_header
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/graphics.h>
|
||||
|
||||
extern const gdiPalette cursor_dump_00000001_palette;
|
||||
extern const rdpPointer cursor_dump_00000001_pointer;
|
||||
extern const uint8_t cursor_dump_00000001_image_bgra32[];
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 456 B |
@@ -0,0 +1,333 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_c_file
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#include "cursor_dump_00000002.h"
|
||||
|
||||
static uint8_t andmask[] = {
|
||||
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x8f, 0xff, 0x00, 0xef, 0x87, 0xff, 0x00,
|
||||
0xe3, 0x07, 0xff, 0x00, 0xe0, 0x07, 0xff, 0x00, 0xe0, 0x0f, 0xff, 0x00, 0xe0, 0x0f, 0xff, 0x00,
|
||||
0xe0, 0x01, 0xff, 0x00, 0xe0, 0x00, 0xff, 0x00, 0xe0, 0x01, 0xff, 0x00, 0xe0, 0x03, 0xff, 0x00,
|
||||
0xe0, 0x07, 0xff, 0x00, 0xe0, 0x0f, 0xff, 0x00, 0xe0, 0x1f, 0xff, 0x00, 0xe0, 0x3f, 0xff, 0x00,
|
||||
0xe0, 0x7f, 0xff, 0x00, 0xe0, 0xff, 0xff, 0x00, 0xe1, 0xff, 0xff, 0x00, 0xe3, 0xff, 0xff, 0x00,
|
||||
0xe7, 0xff, 0xff, 0x00, 0xef, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00
|
||||
};
|
||||
|
||||
static uint8_t xormask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x76, 0x76,
|
||||
0x76, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xb6, 0xb6, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xee, 0xee, 0xee, 0xc0, 0xc0, 0xc0, 0xeb, 0xeb, 0xeb, 0x3b, 0x3b, 0x3b, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfd, 0xfd, 0x8d, 0x8d, 0x8d, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xd5, 0xd5, 0x80, 0x80, 0x80, 0x14, 0x14,
|
||||
0x14, 0xb6, 0xb6, 0xb6, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0xe7, 0xe7, 0xe7, 0x8c, 0x8c, 0x8c, 0x00, 0x00, 0x00, 0x75, 0x75, 0x75,
|
||||
0xee, 0xee, 0xee, 0x1a, 0x1a, 0x1a, 0x27, 0x27, 0x27, 0xf0, 0xf0, 0xf0, 0x55, 0x55, 0x55, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x26, 0x26, 0x26, 0xe5,
|
||||
0xe5, 0xe5, 0x94, 0x94, 0x94, 0xc3, 0xc3, 0xc3, 0x83, 0x83, 0x83, 0x12, 0x12, 0x12, 0x87, 0x87,
|
||||
0x87, 0xc8, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0xe2, 0xe2, 0xe2, 0xef, 0xef, 0xef,
|
||||
0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0xea, 0xea, 0xea, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x77, 0x77, 0x77, 0xcc, 0xcc,
|
||||
0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09,
|
||||
0x19, 0x19, 0x19, 0xde, 0xde, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xf5, 0xf5, 0xf5, 0x8d, 0x8d, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0x02, 0x02, 0x0e, 0x0e, 0x0e, 0x1b, 0x1b, 0x1b, 0x27, 0x27, 0x27, 0x34, 0x34,
|
||||
0x34, 0x40, 0x40, 0x40, 0x7c, 0x7c, 0x7c, 0xf1, 0xf1, 0xf1, 0x87, 0x87, 0x87, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x14, 0x14, 0x14,
|
||||
0x20, 0x20, 0x20, 0x2d, 0x2d, 0x2d, 0x39, 0x39, 0x39, 0x77, 0x77, 0x77, 0xf1, 0xf1, 0xf1, 0x8b,
|
||||
0x8b, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x19, 0x19, 0x19, 0x26, 0x26, 0x26, 0x32, 0x32, 0x32, 0x6b, 0x6b,
|
||||
0x6b, 0xf1, 0xf1, 0xf1, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x12, 0x12, 0x12, 0x1e, 0x1e, 0x1e,
|
||||
0x2b, 0x2b, 0x2b, 0x62, 0x62, 0x62, 0xf0, 0xf0, 0xf0, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x0b,
|
||||
0x0b, 0x0b, 0x17, 0x17, 0x17, 0x24, 0x24, 0x24, 0x56, 0x56, 0x56, 0xee, 0xee, 0xee, 0xa2, 0xa2,
|
||||
0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x10, 0x10, 0x10, 0x1c, 0x1c, 0x1c, 0x4a, 0x4a, 0x4a,
|
||||
0xec, 0xec, 0xec, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x09, 0x09, 0x09, 0x15,
|
||||
0x15, 0x15, 0x41, 0x41, 0x41, 0xea, 0xea, 0xea, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x0e, 0x0e, 0x0e, 0x34, 0x34, 0x34, 0xe5, 0xe5, 0xe5, 0xb5, 0xb5, 0xb5,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x2c, 0x2c, 0x2c, 0xe3,
|
||||
0xe3, 0xe3, 0xb3, 0xb3, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0xdf, 0xdf, 0xdf, 0xb9, 0xb9, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc7, 0xc7, 0xc7, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xee, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const gdiPalette cursor_dump_00000002_palette = {
|
||||
.format = 0,
|
||||
.palette = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000 }
|
||||
};
|
||||
|
||||
const rdpPointer cursor_dump_00000002_pointer = { .size = 0,
|
||||
.New = nullptr,
|
||||
.Free = nullptr,
|
||||
.Set = nullptr,
|
||||
.SetNull = nullptr,
|
||||
.SetDefault = nullptr,
|
||||
.SetPosition = nullptr,
|
||||
.paddingA = { 0 },
|
||||
.xPos = 0,
|
||||
.yPos = 0,
|
||||
.width = 24,
|
||||
.height = 24,
|
||||
.xorBpp = 24,
|
||||
.lengthAndMask = ARRAYSIZE(andmask),
|
||||
.lengthXorMask = ARRAYSIZE(xormask),
|
||||
.xorMaskData = xormask,
|
||||
.andMaskData = andmask,
|
||||
.paddingB = { 0 } };
|
||||
|
||||
const uint8_t cursor_dump_00000002_image_bgra32[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0xee, 0xee, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xc7, 0xc7, 0xc7, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xdf, 0xdf, 0xdf, 0xff, 0xb9, 0xb9, 0xb9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x2c, 0x2c, 0x2c, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xb3, 0xb3, 0xb3, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x0e, 0x0e, 0x0e, 0xff, 0x34, 0x34, 0x34, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xb5, 0xb5, 0xb5, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x09, 0x09, 0x09, 0xff, 0x15, 0x15, 0x15, 0xff, 0x41, 0x41, 0x41, 0xff, 0xea, 0xea, 0xea, 0xff,
|
||||
0xaa, 0xaa, 0xaa, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x03, 0x03, 0x03, 0xff, 0x10, 0x10, 0x10, 0xff, 0x1c, 0x1c, 0x1c, 0xff, 0x4a, 0x4a, 0x4a, 0xff,
|
||||
0xec, 0xec, 0xec, 0xff, 0xaa, 0xaa, 0xaa, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x0b, 0x0b, 0x0b, 0xff, 0x17, 0x17, 0x17, 0xff, 0x24, 0x24, 0x24, 0xff,
|
||||
0x56, 0x56, 0x56, 0xff, 0xee, 0xee, 0xee, 0xff, 0xa2, 0xa2, 0xa2, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x12, 0x12, 0x12, 0xff, 0x1e, 0x1e, 0x1e, 0xff,
|
||||
0x2b, 0x2b, 0x2b, 0xff, 0x62, 0x62, 0x62, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0x98, 0x98, 0x98, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0c, 0x0c, 0x0c, 0xff, 0x19, 0x19, 0x19, 0xff,
|
||||
0x26, 0x26, 0x26, 0xff, 0x32, 0x32, 0x32, 0xff, 0x6b, 0x6b, 0x6b, 0xff, 0xf1, 0xf1, 0xf1, 0xff,
|
||||
0x98, 0x98, 0x98, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x14, 0x14, 0x14, 0xff,
|
||||
0x20, 0x20, 0x20, 0xff, 0x2d, 0x2d, 0x2d, 0xff, 0x39, 0x39, 0x39, 0xff, 0x77, 0x77, 0x77, 0xff,
|
||||
0xf1, 0xf1, 0xf1, 0xff, 0x8b, 0x8b, 0x8b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x0e, 0x0e, 0x0e, 0xff,
|
||||
0x1b, 0x1b, 0x1b, 0xff, 0x27, 0x27, 0x27, 0xff, 0x34, 0x34, 0x34, 0xff, 0x40, 0x40, 0x40, 0xff,
|
||||
0x7c, 0x7c, 0x7c, 0xff, 0xf1, 0xf1, 0xf1, 0xff, 0x87, 0x87, 0x87, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff,
|
||||
0x19, 0x19, 0x19, 0xff, 0xde, 0xde, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x8d, 0x8d, 0x8d, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0x6a, 0x6a, 0x6a, 0xff,
|
||||
0x10, 0x10, 0x10, 0xff, 0x77, 0x77, 0x77, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x22, 0x22, 0x22, 0xff, 0xe2, 0xe2, 0xe2, 0xff, 0xef, 0xef, 0xef, 0xff,
|
||||
0x1b, 0x1b, 0x1b, 0xff, 0x1e, 0x1e, 0x1e, 0xff, 0xea, 0xea, 0xea, 0xff, 0x63, 0x63, 0x63, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x26, 0x26, 0x26, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0x94, 0x94, 0x94, 0xff, 0xc3, 0xc3, 0xc3, 0xff,
|
||||
0x83, 0x83, 0x83, 0xff, 0x12, 0x12, 0x12, 0xff, 0x87, 0x87, 0x87, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xe7, 0xe7, 0xe7, 0xff, 0x8c, 0x8c, 0x8c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x75, 0x75, 0x75, 0xff,
|
||||
0xee, 0xee, 0xee, 0xff, 0x1a, 0x1a, 0x1a, 0xff, 0x27, 0x27, 0x27, 0xff, 0xf0, 0xf0, 0xf0, 0xff,
|
||||
0x55, 0x55, 0x55, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfd, 0xfd, 0xff,
|
||||
0x8d, 0x8d, 0x8d, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xd5, 0xd5, 0xd5, 0xff, 0x80, 0x80, 0x80, 0xff, 0x14, 0x14, 0x14, 0xff, 0xb6, 0xb6, 0xb6, 0xff,
|
||||
0x92, 0x92, 0x92, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0xb6, 0xb6, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xee, 0xee, 0xee, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xeb, 0xeb, 0xeb, 0xff,
|
||||
0x3b, 0x3b, 0x3b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0xff, 0x76, 0x76, 0x76, 0xff, 0x23, 0x23, 0x23, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_header
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/graphics.h>
|
||||
|
||||
extern const gdiPalette cursor_dump_00000002_palette;
|
||||
extern const rdpPointer cursor_dump_00000002_pointer;
|
||||
extern const uint8_t cursor_dump_00000002_image_bgra32[];
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 537 B |
@@ -0,0 +1,333 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_c_file
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#include "cursor_dump_00000003.h"
|
||||
|
||||
static uint8_t andmask[] = {
|
||||
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xc7, 0xff, 0x00,
|
||||
0xff, 0x83, 0xff, 0x00, 0xff, 0x01, 0xff, 0x00, 0xfe, 0x00, 0xff, 0x00, 0xfc, 0x00, 0x7f, 0x00,
|
||||
0xf8, 0x00, 0x3f, 0x00, 0xf0, 0xc2, 0x1f, 0x00, 0xe0, 0x82, 0x0f, 0x00, 0xc0, 0x00, 0x07, 0x00,
|
||||
0x80, 0x00, 0x07, 0x00, 0x80, 0x02, 0x07, 0x00, 0xc0, 0x02, 0x0f, 0x00, 0xe0, 0x86, 0x1f, 0x00,
|
||||
0xf0, 0x00, 0x3f, 0x00, 0xf8, 0x00, 0x7f, 0x00, 0xfc, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xff, 0x00,
|
||||
0xff, 0x03, 0xff, 0x00, 0xff, 0x87, 0xff, 0x00, 0xff, 0xcf, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00
|
||||
};
|
||||
|
||||
static uint8_t xormask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xb5, 0xb5, 0xac, 0xac, 0xac, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb4, 0xb4, 0xdd, 0xdd,
|
||||
0xdd, 0xd6, 0xd6, 0xd6, 0xa4, 0xa4, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xb1, 0xb1, 0xb1, 0xde, 0xde, 0xde, 0x1b, 0x1b, 0x1b, 0x15, 0x15, 0x15, 0xd6, 0xd6, 0xd6, 0xa3,
|
||||
0xa3, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0xb1, 0xb1, 0xdf, 0xdf, 0xdf, 0x1b, 0x1b, 0x1b, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0xd6, 0xd6, 0xd6, 0xa3, 0xa3, 0xa3, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb0, 0xb0, 0xe3, 0xe3, 0xe3,
|
||||
0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
|
||||
0x16, 0x16, 0xd7, 0xd7, 0xd7, 0xa6, 0xa6, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf,
|
||||
0xaf, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xa6, 0xa6, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xaf, 0xaf, 0xaf, 0xe1, 0xe1, 0xe1, 0xfd, 0xfd, 0xfd, 0x08, 0x08, 0x08,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xda, 0xda, 0xda, 0xa1, 0xa1, 0xa1, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0xad, 0xad, 0xe2, 0xe2, 0xe2, 0x1f,
|
||||
0x1f, 0x1f, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0xba, 0xba, 0xba, 0xee, 0xee,
|
||||
0xee, 0xed, 0xed, 0xed, 0xac, 0xac, 0xac, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe,
|
||||
0x19, 0x19, 0x19, 0xda, 0xda, 0xda, 0xa1, 0xa1, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xaf,
|
||||
0xaf, 0xe3, 0xe3, 0xe3, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08,
|
||||
0xc9, 0xc9, 0xc9, 0xb4, 0xb4, 0xb4, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0xb5, 0xb5, 0xb5, 0xb0,
|
||||
0xb0, 0xb0, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x01, 0x01, 0x01, 0x18, 0x18, 0x18, 0xda, 0xda,
|
||||
0xda, 0xa0, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xd5, 0xd5, 0xd5, 0xe5, 0xe5, 0xe5, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x07, 0x07, 0x07, 0xf1, 0xf1, 0xf1, 0x17, 0x17, 0x17, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0xee, 0xee, 0xee, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe,
|
||||
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xdb, 0xdb, 0xdb, 0xa9, 0xa9, 0xa9, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0xe9, 0xe9, 0xe5, 0xe5,
|
||||
0xe5, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08,
|
||||
0xf2, 0xf2, 0xf2, 0x17, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0xef,
|
||||
0xef, 0xef, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x13, 0x13,
|
||||
0x13, 0xd2, 0xd2, 0xd2, 0xcb, 0xcb, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0x20, 0x20, 0x20, 0x00,
|
||||
0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08, 0xdd, 0xdd, 0xdd, 0xb4, 0xb4, 0xb4, 0x17, 0x17,
|
||||
0x17, 0x18, 0x18, 0x18, 0xb4, 0xb4, 0xb4, 0xc8, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe,
|
||||
0x01, 0x01, 0x01, 0x15, 0x15, 0x15, 0xd5, 0xd5, 0xd5, 0xca, 0xca, 0xca, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0x1f, 0x1f, 0x1f, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08,
|
||||
0x00, 0x00, 0x00, 0xd9, 0xd9, 0xd9, 0xf3, 0xf3, 0xf3, 0xf2, 0xf2, 0xf2, 0xce, 0xce, 0xce, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x17, 0x17, 0x17, 0xd8, 0xd8, 0xd8, 0xc8, 0xc8,
|
||||
0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xe5,
|
||||
0xe5, 0xe5, 0xfd, 0xfd, 0xfd, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe,
|
||||
0xd9, 0xd9, 0xd9, 0xc5, 0xc5, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xe5, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc4, 0xc4, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xe4, 0xe4, 0xe4, 0xe6, 0xe6, 0xe6, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xda, 0xda, 0xda, 0xc5, 0xc5, 0xc5,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0xe4,
|
||||
0xe6, 0xe6, 0xe6, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0xdf,
|
||||
0xdf, 0xdf, 0xc5, 0xc5, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0xe4, 0xe6, 0xe6, 0xe6, 0x21, 0x21,
|
||||
0x21, 0x1d, 0x1d, 0x1d, 0xe0, 0xe0, 0xe0, 0xc5, 0xc5, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xbf, 0xbf, 0xbf, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0xeb,
|
||||
0xeb, 0xdd, 0xdd, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const gdiPalette cursor_dump_00000003_palette = {
|
||||
.format = 0,
|
||||
.palette = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000 }
|
||||
};
|
||||
|
||||
const rdpPointer cursor_dump_00000003_pointer = { .size = 0,
|
||||
.New = nullptr,
|
||||
.Free = nullptr,
|
||||
.Set = nullptr,
|
||||
.SetNull = nullptr,
|
||||
.SetDefault = nullptr,
|
||||
.SetPosition = nullptr,
|
||||
.paddingA = { 0 },
|
||||
.xPos = 0,
|
||||
.yPos = 0,
|
||||
.width = 24,
|
||||
.height = 24,
|
||||
.xorBpp = 24,
|
||||
.lengthAndMask = ARRAYSIZE(andmask),
|
||||
.lengthXorMask = ARRAYSIZE(xormask),
|
||||
.xorMaskData = xormask,
|
||||
.andMaskData = andmask,
|
||||
.paddingB = { 0 } };
|
||||
|
||||
const uint8_t cursor_dump_00000003_image_bgra32[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0xeb, 0xeb, 0xff, 0xdd, 0xdd, 0xdd, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xe3, 0xe3, 0xe3, 0xff,
|
||||
0xbf, 0xbf, 0xbf, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xe4, 0xe4, 0xe4, 0xff, 0xe6, 0xe6, 0xe6, 0xff, 0x21, 0x21, 0x21, 0xff, 0x1d, 0x1d, 0x1d, 0xff,
|
||||
0xe0, 0xe0, 0xe0, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0xe4, 0xff,
|
||||
0xe6, 0xe6, 0xe6, 0xff, 0x21, 0x21, 0x21, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x1c, 0x1c, 0x1c, 0xff, 0xdf, 0xdf, 0xdf, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0xe4, 0xff, 0xe6, 0xe6, 0xe6, 0xff,
|
||||
0x21, 0x21, 0x21, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0xff, 0xda, 0xda, 0xda, 0xff, 0xc5, 0xc5, 0xc5, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xe5, 0xe5, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xc4, 0xc4, 0xc4, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xe7, 0xe7, 0xe7, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x06, 0x06, 0x06, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0xd9, 0xd9, 0xd9, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xe5, 0xe5, 0xff,
|
||||
0xe5, 0xe5, 0xe5, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd9, 0xd9, 0xd9, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xf2, 0xf2, 0xf2, 0xff,
|
||||
0xce, 0xce, 0xce, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x17, 0x17, 0x17, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xff, 0xe6, 0xe6, 0xe6, 0xff,
|
||||
0x20, 0x20, 0x20, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0xdd, 0xdd, 0xdd, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0x17, 0x17, 0x17, 0xff, 0x18, 0x18, 0x18, 0xff,
|
||||
0xb4, 0xb4, 0xb4, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x01, 0x01, 0x01, 0xff, 0x15, 0x15, 0x15, 0xff, 0xd5, 0xd5, 0xd5, 0xff, 0xca, 0xca, 0xca, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xe9, 0xe9, 0xe9, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0x20, 0x20, 0x20, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0xf2, 0xf2, 0xf2, 0xff, 0x17, 0x17, 0x17, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x19, 0x19, 0x19, 0xff, 0xef, 0xef, 0xef, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x13, 0x13, 0x13, 0xff, 0xd2, 0xd2, 0xd2, 0xff,
|
||||
0xcb, 0xcb, 0xcb, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd5, 0xd5, 0xd5, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0x21, 0x21, 0x21, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x07, 0x07, 0x07, 0xff,
|
||||
0xf1, 0xf1, 0xf1, 0xff, 0x17, 0x17, 0x17, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x19, 0x19, 0x19, 0xff, 0xee, 0xee, 0xee, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0xff, 0xdb, 0xdb, 0xdb, 0xff,
|
||||
0xa9, 0xa9, 0xa9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xaf, 0xaf, 0xff, 0xe3, 0xe3, 0xe3, 0xff,
|
||||
0x20, 0x20, 0x20, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0xc9, 0xc9, 0xc9, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0x18, 0x18, 0x18, 0xff, 0x19, 0x19, 0x19, 0xff,
|
||||
0xb5, 0xb5, 0xb5, 0xff, 0xb0, 0xb0, 0xb0, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x01, 0x01, 0x01, 0xff, 0x18, 0x18, 0x18, 0xff, 0xda, 0xda, 0xda, 0xff, 0xa0, 0xa0, 0xa0, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0xad, 0xad, 0xff,
|
||||
0xe2, 0xe2, 0xe2, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0xba, 0xba, 0xba, 0xff, 0xee, 0xee, 0xee, 0xff, 0xed, 0xed, 0xed, 0xff,
|
||||
0xac, 0xac, 0xac, 0xff, 0x0f, 0x0f, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x19, 0x19, 0x19, 0xff, 0xda, 0xda, 0xda, 0xff, 0xa1, 0xa1, 0xa1, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xaf, 0xaf, 0xaf, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0xda, 0xda, 0xda, 0xff, 0xa1, 0xa1, 0xa1, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xaf, 0xaf, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xa6, 0xa6, 0xa6, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb0, 0xb0, 0xff, 0xe3, 0xe3, 0xe3, 0xff,
|
||||
0x20, 0x20, 0x20, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x16, 0x16, 0x16, 0xff, 0xd7, 0xd7, 0xd7, 0xff, 0xa6, 0xa6, 0xa6, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0xb1, 0xb1, 0xff,
|
||||
0xdf, 0xdf, 0xdf, 0xff, 0x1b, 0x1b, 0x1b, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x16, 0x16, 0x16, 0xff, 0xd6, 0xd6, 0xd6, 0xff, 0xa3, 0xa3, 0xa3, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xb1, 0xb1, 0xb1, 0xff, 0xde, 0xde, 0xde, 0xff, 0x1b, 0x1b, 0x1b, 0xff, 0x15, 0x15, 0x15, 0xff,
|
||||
0xd6, 0xd6, 0xd6, 0xff, 0xa3, 0xa3, 0xa3, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xb4, 0xb4, 0xb4, 0xff, 0xdd, 0xdd, 0xdd, 0xff, 0xd6, 0xd6, 0xd6, 0xff,
|
||||
0xa4, 0xa4, 0xa4, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xb5, 0xb5, 0xff, 0xac, 0xac, 0xac, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_header
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/graphics.h>
|
||||
|
||||
extern const gdiPalette cursor_dump_00000003_palette;
|
||||
extern const rdpPointer cursor_dump_00000003_pointer;
|
||||
extern const uint8_t cursor_dump_00000003_image_bgra32[];
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 573 B |
@@ -0,0 +1,333 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_c_file
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#include "cursor_dump_00000004.h"
|
||||
|
||||
static uint8_t andmask[] = {
|
||||
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xc7, 0xff, 0x00,
|
||||
0xff, 0x83, 0xff, 0x00, 0xff, 0x01, 0xff, 0x00, 0xfe, 0x00, 0xff, 0x00, 0xfc, 0x00, 0x7f, 0x00,
|
||||
0xf8, 0x00, 0x3f, 0x00, 0xf0, 0xc2, 0x1f, 0x00, 0xe0, 0x82, 0x0f, 0x00, 0xc0, 0x00, 0x07, 0x00,
|
||||
0x80, 0x00, 0x07, 0x00, 0x80, 0x02, 0x07, 0x00, 0xc0, 0x02, 0x0f, 0x00, 0xe0, 0x86, 0x1f, 0x00,
|
||||
0xf0, 0x00, 0x3f, 0x00, 0xf8, 0x00, 0x7f, 0x00, 0xfc, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xff, 0x00,
|
||||
0xff, 0x03, 0xff, 0x00, 0xff, 0x87, 0xff, 0x00, 0xff, 0xcf, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00
|
||||
};
|
||||
|
||||
static uint8_t xormask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xb5, 0xb5, 0xac, 0xac, 0xac, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb4, 0xb4, 0xdd, 0xdd,
|
||||
0xdd, 0xd6, 0xd6, 0xd6, 0xa4, 0xa4, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xb1, 0xb1, 0xb1, 0xde, 0xde, 0xde, 0x1b, 0x1b, 0x1b, 0x15, 0x15, 0x15, 0xd6, 0xd6, 0xd6, 0xa3,
|
||||
0xa3, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0xb1, 0xb1, 0xdf, 0xdf, 0xdf, 0x1b, 0x1b, 0x1b, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x16, 0x16, 0x16, 0xd6, 0xd6, 0xd6, 0xa3, 0xa3, 0xa3, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb0, 0xb0, 0xe3, 0xe3, 0xe3,
|
||||
0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
|
||||
0x16, 0x16, 0xd7, 0xd7, 0xd7, 0xa6, 0xa6, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf,
|
||||
0xaf, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xa6, 0xa6, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xaf, 0xaf, 0xaf, 0xe1, 0xe1, 0xe1, 0xfd, 0xfd, 0xfd, 0x08, 0x08, 0x08,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xda, 0xda, 0xda, 0xa1, 0xa1, 0xa1, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0xad, 0xad, 0xe2, 0xe2, 0xe2, 0x1f,
|
||||
0x1f, 0x1f, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0xba, 0xba, 0xba, 0xee, 0xee,
|
||||
0xee, 0xed, 0xed, 0xed, 0xac, 0xac, 0xac, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe,
|
||||
0x19, 0x19, 0x19, 0xda, 0xda, 0xda, 0xa1, 0xa1, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xaf,
|
||||
0xaf, 0xe3, 0xe3, 0xe3, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08,
|
||||
0xc9, 0xc9, 0xc9, 0xb4, 0xb4, 0xb4, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0xb5, 0xb5, 0xb5, 0xb0,
|
||||
0xb0, 0xb0, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x01, 0x01, 0x01, 0x18, 0x18, 0x18, 0xda, 0xda,
|
||||
0xda, 0xa0, 0xa0, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xd5, 0xd5, 0xd5, 0xe5, 0xe5, 0xe5, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x07, 0x07, 0x07, 0xf1, 0xf1, 0xf1, 0x17, 0x17, 0x17, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0xee, 0xee, 0xee, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe,
|
||||
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xdb, 0xdb, 0xdb, 0xa9, 0xa9, 0xa9, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9, 0xe9, 0xe9, 0xe5, 0xe5,
|
||||
0xe5, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08,
|
||||
0xf2, 0xf2, 0xf2, 0x17, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x19, 0x19, 0xef,
|
||||
0xef, 0xef, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x13, 0x13,
|
||||
0x13, 0xd2, 0xd2, 0xd2, 0xcb, 0xcb, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0x20, 0x20, 0x20, 0x00,
|
||||
0x00, 0x00, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08, 0xdd, 0xdd, 0xdd, 0xb4, 0xb4, 0xb4, 0x17, 0x17,
|
||||
0x17, 0x18, 0x18, 0x18, 0xb4, 0xb4, 0xb4, 0xc8, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe,
|
||||
0x01, 0x01, 0x01, 0x15, 0x15, 0x15, 0xd5, 0xd5, 0xd5, 0xca, 0xca, 0xca, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0x1f, 0x1f, 0x1f, 0xfc, 0xfc, 0xfc, 0x08, 0x08, 0x08,
|
||||
0x00, 0x00, 0x00, 0xd9, 0xd9, 0xd9, 0xf3, 0xf3, 0xf3, 0xf2, 0xf2, 0xf2, 0xce, 0xce, 0xce, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x17, 0x17, 0x17, 0xd8, 0xd8, 0xd8, 0xc8, 0xc8,
|
||||
0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xe5,
|
||||
0xe5, 0xe5, 0xfd, 0xfd, 0xfd, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe,
|
||||
0xd9, 0xd9, 0xd9, 0xc5, 0xc5, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xe5, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc4, 0xc4, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xe4, 0xe4, 0xe4, 0xe6, 0xe6, 0xe6, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xda, 0xda, 0xda, 0xc5, 0xc5, 0xc5,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0xe4,
|
||||
0xe6, 0xe6, 0xe6, 0x21, 0x21, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0xdf,
|
||||
0xdf, 0xdf, 0xc5, 0xc5, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0xe4, 0xe6, 0xe6, 0xe6, 0x21, 0x21,
|
||||
0x21, 0x1d, 0x1d, 0x1d, 0xe0, 0xe0, 0xe0, 0xc5, 0xc5, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xe3, 0xbf, 0xbf, 0xbf, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0xeb,
|
||||
0xeb, 0xdd, 0xdd, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const gdiPalette cursor_dump_00000004_palette = {
|
||||
.format = 0,
|
||||
.palette = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000 }
|
||||
};
|
||||
|
||||
const rdpPointer cursor_dump_00000004_pointer = { .size = 0,
|
||||
.New = nullptr,
|
||||
.Free = nullptr,
|
||||
.Set = nullptr,
|
||||
.SetNull = nullptr,
|
||||
.SetDefault = nullptr,
|
||||
.SetPosition = nullptr,
|
||||
.paddingA = { 0 },
|
||||
.xPos = 0,
|
||||
.yPos = 0,
|
||||
.width = 24,
|
||||
.height = 24,
|
||||
.xorBpp = 24,
|
||||
.lengthAndMask = ARRAYSIZE(andmask),
|
||||
.lengthXorMask = ARRAYSIZE(xormask),
|
||||
.xorMaskData = xormask,
|
||||
.andMaskData = andmask,
|
||||
.paddingB = { 0 } };
|
||||
|
||||
const uint8_t cursor_dump_00000004_image_bgra32[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0xeb, 0xeb, 0xff, 0xdd, 0xdd, 0xdd, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xe3, 0xe3, 0xe3, 0xff,
|
||||
0xbf, 0xbf, 0xbf, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xe4, 0xe4, 0xe4, 0xff, 0xe6, 0xe6, 0xe6, 0xff, 0x21, 0x21, 0x21, 0xff, 0x1d, 0x1d, 0x1d, 0xff,
|
||||
0xe0, 0xe0, 0xe0, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0xe4, 0xff,
|
||||
0xe6, 0xe6, 0xe6, 0xff, 0x21, 0x21, 0x21, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x1c, 0x1c, 0x1c, 0xff, 0xdf, 0xdf, 0xdf, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xe4, 0xe4, 0xff, 0xe6, 0xe6, 0xe6, 0xff,
|
||||
0x21, 0x21, 0x21, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0xff, 0xda, 0xda, 0xda, 0xff, 0xc5, 0xc5, 0xc5, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xe5, 0xe5, 0xe5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xc4, 0xc4, 0xc4, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xe7, 0xe7, 0xe7, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x06, 0x06, 0x06, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0xd9, 0xd9, 0xd9, 0xff, 0xc5, 0xc5, 0xc5, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0xe5, 0xe5, 0xff,
|
||||
0xe5, 0xe5, 0xe5, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd9, 0xd9, 0xd9, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0xf2, 0xf2, 0xf2, 0xff,
|
||||
0xce, 0xce, 0xce, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x17, 0x17, 0x17, 0xff, 0xd8, 0xd8, 0xd8, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0xe7, 0xe7, 0xff, 0xe6, 0xe6, 0xe6, 0xff,
|
||||
0x20, 0x20, 0x20, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0xdd, 0xdd, 0xdd, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0x17, 0x17, 0x17, 0xff, 0x18, 0x18, 0x18, 0xff,
|
||||
0xb4, 0xb4, 0xb4, 0xff, 0xc8, 0xc8, 0xc8, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x01, 0x01, 0x01, 0xff, 0x15, 0x15, 0x15, 0xff, 0xd5, 0xd5, 0xd5, 0xff, 0xca, 0xca, 0xca, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xe9, 0xe9, 0xe9, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0x20, 0x20, 0x20, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0xf2, 0xf2, 0xf2, 0xff, 0x17, 0x17, 0x17, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x19, 0x19, 0x19, 0xff, 0xef, 0xef, 0xef, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x13, 0x13, 0x13, 0xff, 0xd2, 0xd2, 0xd2, 0xff,
|
||||
0xcb, 0xcb, 0xcb, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xd5, 0xd5, 0xd5, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0x21, 0x21, 0x21, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x07, 0x07, 0x07, 0xff,
|
||||
0xf1, 0xf1, 0xf1, 0xff, 0x17, 0x17, 0x17, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x19, 0x19, 0x19, 0xff, 0xee, 0xee, 0xee, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x01, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0xff, 0xdb, 0xdb, 0xdb, 0xff,
|
||||
0xa9, 0xa9, 0xa9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaf, 0xaf, 0xaf, 0xff, 0xe3, 0xe3, 0xe3, 0xff,
|
||||
0x20, 0x20, 0x20, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0xc9, 0xc9, 0xc9, 0xff, 0xb4, 0xb4, 0xb4, 0xff, 0x18, 0x18, 0x18, 0xff, 0x19, 0x19, 0x19, 0xff,
|
||||
0xb5, 0xb5, 0xb5, 0xff, 0xb0, 0xb0, 0xb0, 0xff, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x01, 0x01, 0x01, 0xff, 0x18, 0x18, 0x18, 0xff, 0xda, 0xda, 0xda, 0xff, 0xa0, 0xa0, 0xa0, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0xad, 0xad, 0xff,
|
||||
0xe2, 0xe2, 0xe2, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0xfc, 0xfc, 0xfc, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0xba, 0xba, 0xba, 0xff, 0xee, 0xee, 0xee, 0xff, 0xed, 0xed, 0xed, 0xff,
|
||||
0xac, 0xac, 0xac, 0xff, 0x0f, 0x0f, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0x19, 0x19, 0x19, 0xff, 0xda, 0xda, 0xda, 0xff, 0xa1, 0xa1, 0xa1, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xaf, 0xaf, 0xaf, 0xff, 0xe1, 0xe1, 0xe1, 0xff, 0xfd, 0xfd, 0xfd, 0xff, 0x08, 0x08, 0x08, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xff,
|
||||
0xda, 0xda, 0xda, 0xff, 0xa1, 0xa1, 0xa1, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xaf, 0xaf, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xa6, 0xa6, 0xa6, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xb0, 0xb0, 0xff, 0xe3, 0xe3, 0xe3, 0xff,
|
||||
0x20, 0x20, 0x20, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x16, 0x16, 0x16, 0xff, 0xd7, 0xd7, 0xd7, 0xff, 0xa6, 0xa6, 0xa6, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0xb1, 0xb1, 0xff,
|
||||
0xdf, 0xdf, 0xdf, 0xff, 0x1b, 0x1b, 0x1b, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x16, 0x16, 0x16, 0xff, 0xd6, 0xd6, 0xd6, 0xff, 0xa3, 0xa3, 0xa3, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xb1, 0xb1, 0xb1, 0xff, 0xde, 0xde, 0xde, 0xff, 0x1b, 0x1b, 0x1b, 0xff, 0x15, 0x15, 0x15, 0xff,
|
||||
0xd6, 0xd6, 0xd6, 0xff, 0xa3, 0xa3, 0xa3, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xb4, 0xb4, 0xb4, 0xff, 0xdd, 0xdd, 0xdd, 0xff, 0xd6, 0xd6, 0xd6, 0xff,
|
||||
0xa4, 0xa4, 0xa4, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xb5, 0xb5, 0xff, 0xac, 0xac, 0xac, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_header
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/graphics.h>
|
||||
|
||||
extern const gdiPalette cursor_dump_00000004_palette;
|
||||
extern const rdpPointer cursor_dump_00000004_pointer;
|
||||
extern const uint8_t cursor_dump_00000004_image_bgra32[];
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 573 B |
@@ -0,0 +1,333 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_c_file
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#include "cursor_dump_00000005.h"
|
||||
|
||||
static uint8_t andmask[] = {
|
||||
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x8f, 0xff, 0x00, 0xef, 0x87, 0xff, 0x00,
|
||||
0xe3, 0x07, 0xff, 0x00, 0xe0, 0x07, 0xff, 0x00, 0xe0, 0x0f, 0xff, 0x00, 0xe0, 0x0f, 0xff, 0x00,
|
||||
0xe0, 0x01, 0xff, 0x00, 0xe0, 0x00, 0xff, 0x00, 0xe0, 0x01, 0xff, 0x00, 0xe0, 0x03, 0xff, 0x00,
|
||||
0xe0, 0x07, 0xff, 0x00, 0xe0, 0x0f, 0xff, 0x00, 0xe0, 0x1f, 0xff, 0x00, 0xe0, 0x3f, 0xff, 0x00,
|
||||
0xe0, 0x7f, 0xff, 0x00, 0xe0, 0xff, 0xff, 0x00, 0xe1, 0xff, 0xff, 0x00, 0xe3, 0xff, 0xff, 0x00,
|
||||
0xe7, 0xff, 0xff, 0x00, 0xef, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00
|
||||
};
|
||||
|
||||
static uint8_t xormask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x76, 0x76,
|
||||
0x76, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xb6, 0xb6, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xee, 0xee, 0xee, 0xc0, 0xc0, 0xc0, 0xeb, 0xeb, 0xeb, 0x3b, 0x3b, 0x3b, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfd, 0xfd, 0x8d, 0x8d, 0x8d, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xd5, 0xd5, 0x80, 0x80, 0x80, 0x14, 0x14,
|
||||
0x14, 0xb6, 0xb6, 0xb6, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0xe7, 0xe7, 0xe7, 0x8c, 0x8c, 0x8c, 0x00, 0x00, 0x00, 0x75, 0x75, 0x75,
|
||||
0xee, 0xee, 0xee, 0x1a, 0x1a, 0x1a, 0x27, 0x27, 0x27, 0xf0, 0xf0, 0xf0, 0x55, 0x55, 0x55, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x26, 0x26, 0x26, 0xe5,
|
||||
0xe5, 0xe5, 0x94, 0x94, 0x94, 0xc3, 0xc3, 0xc3, 0x83, 0x83, 0x83, 0x12, 0x12, 0x12, 0x87, 0x87,
|
||||
0x87, 0xc8, 0xc8, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0xe2, 0xe2, 0xe2, 0xef, 0xef, 0xef,
|
||||
0x1b, 0x1b, 0x1b, 0x1e, 0x1e, 0x1e, 0xea, 0xea, 0xea, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x6a, 0x6a, 0x6a, 0x10, 0x10, 0x10, 0x77, 0x77, 0x77, 0xcc, 0xcc,
|
||||
0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09,
|
||||
0x19, 0x19, 0x19, 0xde, 0xde, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xf5, 0xf5, 0xf5, 0x8d, 0x8d, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0x02, 0x02, 0x0e, 0x0e, 0x0e, 0x1b, 0x1b, 0x1b, 0x27, 0x27, 0x27, 0x34, 0x34,
|
||||
0x34, 0x40, 0x40, 0x40, 0x7c, 0x7c, 0x7c, 0xf1, 0xf1, 0xf1, 0x87, 0x87, 0x87, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x14, 0x14, 0x14,
|
||||
0x20, 0x20, 0x20, 0x2d, 0x2d, 0x2d, 0x39, 0x39, 0x39, 0x77, 0x77, 0x77, 0xf1, 0xf1, 0xf1, 0x8b,
|
||||
0x8b, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x19, 0x19, 0x19, 0x26, 0x26, 0x26, 0x32, 0x32, 0x32, 0x6b, 0x6b,
|
||||
0x6b, 0xf1, 0xf1, 0xf1, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x12, 0x12, 0x12, 0x1e, 0x1e, 0x1e,
|
||||
0x2b, 0x2b, 0x2b, 0x62, 0x62, 0x62, 0xf0, 0xf0, 0xf0, 0x98, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x0b,
|
||||
0x0b, 0x0b, 0x17, 0x17, 0x17, 0x24, 0x24, 0x24, 0x56, 0x56, 0x56, 0xee, 0xee, 0xee, 0xa2, 0xa2,
|
||||
0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x10, 0x10, 0x10, 0x1c, 0x1c, 0x1c, 0x4a, 0x4a, 0x4a,
|
||||
0xec, 0xec, 0xec, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x09, 0x09, 0x09, 0x15,
|
||||
0x15, 0x15, 0x41, 0x41, 0x41, 0xea, 0xea, 0xea, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0x0e, 0x0e, 0x0e, 0x34, 0x34, 0x34, 0xe5, 0xe5, 0xe5, 0xb5, 0xb5, 0xb5,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x2c, 0x2c, 0x2c, 0xe3,
|
||||
0xe3, 0xe3, 0xb3, 0xb3, 0xb3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0xff, 0xdf, 0xdf, 0xdf, 0xb9, 0xb9, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xc7, 0xc7, 0xc7, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xee, 0xee, 0xee, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const gdiPalette cursor_dump_00000005_palette = {
|
||||
.format = 0,
|
||||
.palette = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000 }
|
||||
};
|
||||
|
||||
const rdpPointer cursor_dump_00000005_pointer = { .size = 0,
|
||||
.New = nullptr,
|
||||
.Free = nullptr,
|
||||
.Set = nullptr,
|
||||
.SetNull = nullptr,
|
||||
.SetDefault = nullptr,
|
||||
.SetPosition = nullptr,
|
||||
.paddingA = { 0 },
|
||||
.xPos = 0,
|
||||
.yPos = 0,
|
||||
.width = 24,
|
||||
.height = 24,
|
||||
.xorBpp = 24,
|
||||
.lengthAndMask = ARRAYSIZE(andmask),
|
||||
.lengthXorMask = ARRAYSIZE(xormask),
|
||||
.xorMaskData = xormask,
|
||||
.andMaskData = andmask,
|
||||
.paddingB = { 0 } };
|
||||
|
||||
const uint8_t cursor_dump_00000005_image_bgra32[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0xee, 0xee, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xc7, 0xc7, 0xc7, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xdf, 0xdf, 0xdf, 0xff, 0xb9, 0xb9, 0xb9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x2c, 0x2c, 0x2c, 0xff, 0xe3, 0xe3, 0xe3, 0xff, 0xb3, 0xb3, 0xb3, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x0e, 0x0e, 0x0e, 0xff, 0x34, 0x34, 0x34, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0xb5, 0xb5, 0xb5, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x09, 0x09, 0x09, 0xff, 0x15, 0x15, 0x15, 0xff, 0x41, 0x41, 0x41, 0xff, 0xea, 0xea, 0xea, 0xff,
|
||||
0xaa, 0xaa, 0xaa, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x03, 0x03, 0x03, 0xff, 0x10, 0x10, 0x10, 0xff, 0x1c, 0x1c, 0x1c, 0xff, 0x4a, 0x4a, 0x4a, 0xff,
|
||||
0xec, 0xec, 0xec, 0xff, 0xaa, 0xaa, 0xaa, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x0b, 0x0b, 0x0b, 0xff, 0x17, 0x17, 0x17, 0xff, 0x24, 0x24, 0x24, 0xff,
|
||||
0x56, 0x56, 0x56, 0xff, 0xee, 0xee, 0xee, 0xff, 0xa2, 0xa2, 0xa2, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x05, 0x05, 0x05, 0xff, 0x12, 0x12, 0x12, 0xff, 0x1e, 0x1e, 0x1e, 0xff,
|
||||
0x2b, 0x2b, 0x2b, 0xff, 0x62, 0x62, 0x62, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0x98, 0x98, 0x98, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x0c, 0x0c, 0x0c, 0xff, 0x19, 0x19, 0x19, 0xff,
|
||||
0x26, 0x26, 0x26, 0xff, 0x32, 0x32, 0x32, 0xff, 0x6b, 0x6b, 0x6b, 0xff, 0xf1, 0xf1, 0xf1, 0xff,
|
||||
0x98, 0x98, 0x98, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x07, 0x07, 0x07, 0xff, 0x14, 0x14, 0x14, 0xff,
|
||||
0x20, 0x20, 0x20, 0xff, 0x2d, 0x2d, 0x2d, 0xff, 0x39, 0x39, 0x39, 0xff, 0x77, 0x77, 0x77, 0xff,
|
||||
0xf1, 0xf1, 0xf1, 0xff, 0x8b, 0x8b, 0x8b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x02, 0x02, 0x02, 0xff, 0x0e, 0x0e, 0x0e, 0xff,
|
||||
0x1b, 0x1b, 0x1b, 0xff, 0x27, 0x27, 0x27, 0xff, 0x34, 0x34, 0x34, 0xff, 0x40, 0x40, 0x40, 0xff,
|
||||
0x7c, 0x7c, 0x7c, 0xff, 0xf1, 0xf1, 0xf1, 0xff, 0x87, 0x87, 0x87, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x09, 0x09, 0x09, 0xff,
|
||||
0x19, 0x19, 0x19, 0xff, 0xde, 0xde, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x8d, 0x8d, 0x8d, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x1f, 0x1f, 0x1f, 0xff, 0x6a, 0x6a, 0x6a, 0xff,
|
||||
0x10, 0x10, 0x10, 0xff, 0x77, 0x77, 0x77, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x22, 0x22, 0x22, 0xff, 0xe2, 0xe2, 0xe2, 0xff, 0xef, 0xef, 0xef, 0xff,
|
||||
0x1b, 0x1b, 0x1b, 0xff, 0x1e, 0x1e, 0x1e, 0xff, 0xea, 0xea, 0xea, 0xff, 0x63, 0x63, 0x63, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0x26, 0x26, 0x26, 0xff, 0xe5, 0xe5, 0xe5, 0xff, 0x94, 0x94, 0x94, 0xff, 0xc3, 0xc3, 0xc3, 0xff,
|
||||
0x83, 0x83, 0x83, 0xff, 0x12, 0x12, 0x12, 0xff, 0x87, 0x87, 0x87, 0xff, 0xc8, 0xc8, 0xc8, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
|
||||
0xe7, 0xe7, 0xe7, 0xff, 0x8c, 0x8c, 0x8c, 0xff, 0x00, 0x00, 0x00, 0xff, 0x75, 0x75, 0x75, 0xff,
|
||||
0xee, 0xee, 0xee, 0xff, 0x1a, 0x1a, 0x1a, 0xff, 0x27, 0x27, 0x27, 0xff, 0xf0, 0xf0, 0xf0, 0xff,
|
||||
0x55, 0x55, 0x55, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xfd, 0xfd, 0xff,
|
||||
0x8d, 0x8d, 0x8d, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xd5, 0xd5, 0xd5, 0xff, 0x80, 0x80, 0x80, 0xff, 0x14, 0x14, 0x14, 0xff, 0xb6, 0xb6, 0xb6, 0xff,
|
||||
0x92, 0x92, 0x92, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0xb6, 0xb6, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xee, 0xee, 0xee, 0xff, 0xc0, 0xc0, 0xc0, 0xff, 0xeb, 0xeb, 0xeb, 0xff,
|
||||
0x3b, 0x3b, 0x3b, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0xff, 0x76, 0x76, 0x76, 0xff, 0x23, 0x23, 0x23, 0xff,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
/* FreeRDP cursor dump to use for unit tests
|
||||
* this file was auto generated by dump_write_header
|
||||
* do not modify manually
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/graphics.h>
|
||||
|
||||
extern const gdiPalette cursor_dump_00000005_palette;
|
||||
extern const rdpPointer cursor_dump_00000005_pointer;
|
||||
extern const uint8_t cursor_dump_00000005_image_bgra32[];
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 537 B |
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* helper utility, convert image to RAW RGBA32 header ready to be included
|
||||
*
|
||||
* Copyright 2025 Armin Novak <armin.novak@thincast.com>
|
||||
* Copyright 2025 Thincast Technologies GmbH
|
||||
*
|
||||
* 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 <winpr/image.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void usage(const char* name)
|
||||
{
|
||||
(void)printf("%s <source file> <destination file>\n\n", name);
|
||||
(void)printf("\tRead any image format supported by WinPR::wImage\n");
|
||||
(void)printf("\tand convert it to raw BGRA data.\n\n");
|
||||
(void)printf("\toutput format is a C header with an array ready to be included\n");
|
||||
}
|
||||
|
||||
static int dump_data_hex(FILE* fp, const uint8_t* data, size_t size)
|
||||
{
|
||||
if (size > 0)
|
||||
{
|
||||
const int rc = fprintf(fp, "0x%02" PRIx8, data[0]);
|
||||
if (rc != 4)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size_t x = 1; x < size; x++)
|
||||
{
|
||||
if (x % 16 == 0)
|
||||
{
|
||||
const int rc = fprintf(fp, ",\n");
|
||||
if (rc != 2)
|
||||
return -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int rc = fprintf(fp, ",");
|
||||
if (rc != 1)
|
||||
return -2;
|
||||
}
|
||||
|
||||
const int rc = fprintf(fp, "0x%02" PRIx8, data[x]);
|
||||
if (rc != 4)
|
||||
return -2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_data(const wImage* img, const char* file)
|
||||
{
|
||||
FILE* fp = fopen(file, "w");
|
||||
if (!fp)
|
||||
{
|
||||
(void)fprintf(stderr, "Failed to open file '%s'\n", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rc = -2;
|
||||
int count = fprintf(fp, "#pragma once\n");
|
||||
if (count < 0)
|
||||
goto fail;
|
||||
count = fprintf(fp, "\n");
|
||||
if (count < 0)
|
||||
goto fail;
|
||||
count = fprintf(fp, "#include <stdint.h>\n");
|
||||
if (count < 0)
|
||||
goto fail;
|
||||
count = fprintf(fp, "\n");
|
||||
if (count < 0)
|
||||
goto fail;
|
||||
count = fprintf(fp, "static const uint8_t img_data[] ={\n");
|
||||
if (count < 0)
|
||||
goto fail;
|
||||
count = dump_data_hex(fp, img->data, 1ULL * img->height * img->scanline);
|
||||
if (count < 0)
|
||||
goto fail;
|
||||
count = fprintf(fp, "};\n");
|
||||
if (count < 0)
|
||||
goto fail;
|
||||
rc = 0;
|
||||
fail:
|
||||
fclose(fp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rc = -1;
|
||||
const char* src = argv[1];
|
||||
const char* dst = argv[2];
|
||||
wImage* img = winpr_image_new();
|
||||
if (!img)
|
||||
goto fail;
|
||||
|
||||
const int res = winpr_image_read(img, src);
|
||||
if (res <= 0)
|
||||
{
|
||||
(void)fprintf(stderr, "Failed to read image file '%s'\n", src);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = dump_data(img, dst);
|
||||
|
||||
if (rc >= 0)
|
||||
(void)printf("Converted '%s' to header '%s'\n", src, dst);
|
||||
fail:
|
||||
if (rc != 0)
|
||||
usage(argv[0]);
|
||||
winpr_image_free(img, TRUE);
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
[
|
||||
{
|
||||
"name": "encoder_test_01",
|
||||
"format": "PIXEL_FORMAT_BGRA32",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "encoder_test_02",
|
||||
"format": "PIXEL_FORMAT_BGRX32",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "encoder_test_03",
|
||||
"format": "PIXEL_FORMAT_RGBA32",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "encoder_test_04",
|
||||
"format": "PIXEL_FORMAT_RGBX32",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "encoder_test_05",
|
||||
"format": "PIXEL_FORMAT_ABGR32",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "encoder_test_06",
|
||||
"format": "PIXEL_FORMAT_XBGR32",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "encoder_test_07",
|
||||
"format": "PIXEL_FORMAT_ARGB32",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "encoder_test_08",
|
||||
"format": "PIXEL_FORMAT_XRGB32",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "encoder_test_09",
|
||||
"format": "PIXEL_FORMAT_RGB24",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "encoder_test_10",
|
||||
"format": "PIXEL_FORMAT_BGR24",
|
||||
"width": 64,
|
||||
"height": 64,
|
||||
"step": 256,
|
||||
"bpp": [
|
||||
24,
|
||||
16,
|
||||
15
|
||||
]
|
||||
}
|
||||
]
|
||||
BIN
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user