2 * FreeRDP: A Remote Desktop Protocol client.
3 * RemoteFX Codec Library - Decode
5 * Copyright 2011 Vic Lee
6 * Copyright 2011 Norbert Federa <nfedera@thinstuff.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
24 #include <freerdp/utils/stream.h>
25 #include "rfx_types.h"
27 #include "rfx_differential.h"
28 #include "rfx_quantization.h"
31 #include "rfx_decode.h"
33 static void rfx_decode_format_rgb(sint16* r_buf, sint16* g_buf, sint16* b_buf,
34 RFX_PIXEL_FORMAT pixel_format, uint8* dst_buf)
44 case RFX_PIXEL_FORMAT_BGRA:
45 for (i = 0; i < 4096; i++)
47 *dst++ = (uint8) (*b++);
48 *dst++ = (uint8) (*g++);
49 *dst++ = (uint8) (*r++);
53 case RFX_PIXEL_FORMAT_RGBA:
54 for (i = 0; i < 4096; i++)
56 *dst++ = (uint8) (*r++);
57 *dst++ = (uint8) (*g++);
58 *dst++ = (uint8) (*b++);
62 case RFX_PIXEL_FORMAT_BGR:
63 for (i = 0; i < 4096; i++)
65 *dst++ = (uint8) (*b++);
66 *dst++ = (uint8) (*g++);
67 *dst++ = (uint8) (*r++);
70 case RFX_PIXEL_FORMAT_RGB:
71 for (i = 0; i < 4096; i++)
73 *dst++ = (uint8) (*r++);
74 *dst++ = (uint8) (*g++);
75 *dst++ = (uint8) (*b++);
83 #define MINMAX(_v,_l,_h) ((_v) < (_l) ? (_l) : ((_v) > (_h) ? (_h) : (_v)))
85 void rfx_decode_ycbcr_to_rgb(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf)
87 /* sint32 is used intentionally because we calculate with shifted factors! */
93 * The decoded YCbCr coeffectients are represented as 11.5 fixed-point numbers:
95 * 1 sign bit + 10 integer bits + 5 fractional bits
97 * However only 7 integer bits will be actually used since the value range is [-128.0, 127.0].
98 * In other words, the decoded coeffectients is scaled by << 5 when intepreted as sint16.
99 * It was scaled in the quantization phase, so we must scale it back here.
101 for (i = 0; i < 4096; i++)
109 * This is the slow floating point version kept here for reference
112 y = y + 4096; /* 128<<5=4096 so that we can scale the sum by >> 5 */
115 g = y - cb*0.344f - cr*0.714f;
118 y_r_buf[i] = MINMAX(r>>5, 0, 255);
119 cb_g_buf[i] = MINMAX(g>>5, 0, 255);
120 cr_b_buf[i] = MINMAX(b>>5, 0, 255);
123 * We scale the factors by << 16 into 32-bit integers in order to avoid slower
124 * floating point multiplications. Since the final result needs to be scaled
125 * by >> 5 we will extract only the upper 11 bits (>> 21) from the final sum.
126 * Hence we also have to scale the other terms of the sum by << 16.
128 * R: 1.403 << 16 = 91947
129 * G: 0.344 << 16 = 22544, 0.714 << 16 = 46792
130 * B: 1.770 << 16 = 115998
136 g = y - cb*22544 - cr*46792;
139 y_r_buf[i] = MINMAX(r>>21, 0, 255);
140 cb_g_buf[i] = MINMAX(g>>21, 0, 255);
141 cr_b_buf[i] = MINMAX(b>>21, 0, 255);
146 static void rfx_decode_component(RFX_CONTEXT* context, const uint32* quantization_values,
147 const uint8* data, int size, sint16* buffer)
149 PROFILER_ENTER(context->priv->prof_rfx_decode_component);
151 PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode);
152 rfx_rlgr_decode(context->mode, data, size, buffer, 4096);
153 PROFILER_EXIT(context->priv->prof_rfx_rlgr_decode);
155 PROFILER_ENTER(context->priv->prof_rfx_differential_decode);
156 rfx_differential_decode(buffer + 4032, 64);
157 PROFILER_EXIT(context->priv->prof_rfx_differential_decode);
159 PROFILER_ENTER(context->priv->prof_rfx_quantization_decode);
160 context->quantization_decode(buffer, quantization_values);
161 PROFILER_EXIT(context->priv->prof_rfx_quantization_decode);
163 PROFILER_ENTER(context->priv->prof_rfx_dwt_2d_decode);
164 context->dwt_2d_decode(buffer, context->priv->dwt_buffer);
165 PROFILER_EXIT(context->priv->prof_rfx_dwt_2d_decode);
167 PROFILER_EXIT(context->priv->prof_rfx_decode_component);
170 void rfx_decode_rgb(RFX_CONTEXT* context, STREAM* data_in,
171 int y_size, const uint32 * y_quants,
172 int cb_size, const uint32 * cb_quants,
173 int cr_size, const uint32 * cr_quants, uint8* rgb_buffer)
175 PROFILER_ENTER(context->priv->prof_rfx_decode_rgb);
177 rfx_decode_component(context, y_quants, stream_get_tail(data_in), y_size, context->priv->y_r_buffer); /* YData */
178 stream_seek(data_in, y_size);
179 rfx_decode_component(context, cb_quants, stream_get_tail(data_in), cb_size, context->priv->cb_g_buffer); /* CbData */
180 stream_seek(data_in, cb_size);
181 rfx_decode_component(context, cr_quants, stream_get_tail(data_in), cr_size, context->priv->cr_b_buffer); /* CrData */
182 stream_seek(data_in, cr_size);
184 PROFILER_ENTER(context->priv->prof_rfx_decode_ycbcr_to_rgb);
185 context->decode_ycbcr_to_rgb(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer);
186 PROFILER_EXIT(context->priv->prof_rfx_decode_ycbcr_to_rgb);
188 PROFILER_ENTER(context->priv->prof_rfx_decode_format_rgb);
189 rfx_decode_format_rgb(context->priv->y_r_buffer, context->priv->cb_g_buffer, context->priv->cr_b_buffer,
190 context->pixel_format, rgb_buffer);
191 PROFILER_EXIT(context->priv->prof_rfx_decode_format_rgb);
193 PROFILER_EXIT(context->priv->prof_rfx_decode_rgb);