Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-codec / rfx_decode.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol client.
3  * RemoteFX Codec Library - Decode
4  *
5  * Copyright 2011 Vic Lee
6  * Copyright 2011 Norbert Federa <nfedera@thinstuff.com>
7  *
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
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <freerdp/utils/stream.h>
25 #include "rfx_types.h"
26 #include "rfx_rlgr.h"
27 #include "rfx_differential.h"
28 #include "rfx_quantization.h"
29 #include "rfx_dwt.h"
30
31 #include "rfx_decode.h"
32
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)
35 {
36         sint16* r = r_buf;
37         sint16* g = g_buf;
38         sint16* b = b_buf;
39         uint8* dst = dst_buf;
40         int i;
41         
42         switch (pixel_format)
43         {
44                 case RFX_PIXEL_FORMAT_BGRA:
45                         for (i = 0; i < 4096; i++)
46                         {
47                                 *dst++ = (uint8) (*b++);
48                                 *dst++ = (uint8) (*g++);
49                                 *dst++ = (uint8) (*r++);
50                                 *dst++ = 0xFF;
51                         }
52                         break;
53                 case RFX_PIXEL_FORMAT_RGBA:
54                         for (i = 0; i < 4096; i++)
55                         {
56                                 *dst++ = (uint8) (*r++);
57                                 *dst++ = (uint8) (*g++);
58                                 *dst++ = (uint8) (*b++);
59                                 *dst++ = 0xFF;
60                         }
61                         break;
62                 case RFX_PIXEL_FORMAT_BGR:
63                         for (i = 0; i < 4096; i++)
64                         {
65                                 *dst++ = (uint8) (*b++);
66                                 *dst++ = (uint8) (*g++);
67                                 *dst++ = (uint8) (*r++);
68                         }
69                         break;
70                 case RFX_PIXEL_FORMAT_RGB:
71                         for (i = 0; i < 4096; i++)
72                         {
73                                 *dst++ = (uint8) (*r++);
74                                 *dst++ = (uint8) (*g++);
75                                 *dst++ = (uint8) (*b++);
76                         }
77                         break;
78                 default:
79                         break;
80         }
81 }
82
83 #define MINMAX(_v,_l,_h) ((_v) < (_l) ? (_l) : ((_v) > (_h) ? (_h) : (_v)))
84
85 void rfx_decode_ycbcr_to_rgb(sint16* y_r_buf, sint16* cb_g_buf, sint16* cr_b_buf)
86 {
87         /* sint32 is used intentionally because we calculate with shifted factors! */
88         sint32 y, cb, cr;
89         sint32 r, g, b;
90         int i;
91
92         /**
93          * The decoded YCbCr coeffectients are represented as 11.5 fixed-point numbers:
94          *
95          * 1 sign bit + 10 integer bits + 5 fractional bits
96          *
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.
100          */
101         for (i = 0; i < 4096; i++)
102         {
103                 y = y_r_buf[i];
104                 cb = cb_g_buf[i];
105                 cr = cr_b_buf[i];
106
107 #if 0
108                 /**
109                  * This is the slow floating point version kept here for reference
110                  */
111
112                 y = y + 4096; /* 128<<5=4096 so that we can scale the sum by >> 5 */
113
114                 r = y + cr*1.403f;
115                 g = y - cb*0.344f - cr*0.714f;
116                 b = y + cb*1.770f;
117
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);
121 #else
122                 /**
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.
127                  *
128                  * R: 1.403 << 16 = 91947
129                  * G: 0.344 << 16 = 22544, 0.714 << 16 = 46792
130                  * B: 1.770 << 16 = 115998
131                  */
132
133                 y = (y+4096)<<16;
134
135                 r = y + cr*91947;
136                 g = y - cb*22544 - cr*46792;
137                 b = y + cb*115998;
138
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);
142 #endif
143         }
144 }
145
146 static void rfx_decode_component(RFX_CONTEXT* context, const uint32* quantization_values,
147         const uint8* data, int size, sint16* buffer)
148 {
149         PROFILER_ENTER(context->priv->prof_rfx_decode_component);
150
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);
154
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);
158
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);
162
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);
166
167         PROFILER_EXIT(context->priv->prof_rfx_decode_component);
168 }
169
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)
174 {
175         PROFILER_ENTER(context->priv->prof_rfx_decode_rgb);
176
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);
183
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);
187
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);
192         
193         PROFILER_EXIT(context->priv->prof_rfx_decode_rgb);
194 }