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