1 /**
2  * RFX codec encoder
3  *
4  * Copyright 2014-2017 Jay Sorg <jay.sorg@gmail.com>
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #if defined(HAVE_CONFIG_H)
20 #include <config_ac.h>
21 #endif
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include <rfxcodec_encode.h>
28 
29 #include "rfxcommon.h"
30 #include "rfxencode.h"
31 #include "rfxencode_compose.h"
32 #include "rfxconstants.h"
33 #include "rfxencode_tile.h"
34 #include "rfxencode_rlgr1.h"
35 #include "rfxencode_rlgr3.h"
36 #include "rfxencode_differential.h"
37 #include "rfxencode_quantization.h"
38 #include "rfxencode_dwt.h"
39 #include "rfxencode_diff_rlgr1.h"
40 #include "rfxencode_diff_rlgr3.h"
41 #include "rfxencode_rgb_to_yuv.h"
42 
43 #ifdef RFX_USE_ACCEL_X86
44 #include "x86/funcs_x86.h"
45 #endif
46 
47 #ifdef RFX_USE_ACCEL_AMD64
48 #include "amd64/funcs_amd64.h"
49 #endif
50 
51 /******************************************************************************/
52 int
rfxcodec_encode_create_ex(int width,int height,int format,int flags,void ** handle)53 rfxcodec_encode_create_ex(int width, int height, int format, int flags,
54                           void **handle)
55 {
56     struct rfxencode *enc;
57     int ax;
58     int bx;
59     int cx;
60     int dx;
61 
62     enc = (struct rfxencode *) calloc(1, sizeof(struct rfxencode));
63     if (enc == NULL)
64     {
65         return 1;
66     }
67 
68     enc->dwt_buffer = (sint16 *) (((size_t) (enc->dwt_buffer_a)) & ~15);
69     enc->dwt_buffer1 = (sint16 *) (((size_t) (enc->dwt_buffer1_a)) & ~15);
70     enc->dwt_buffer2 = (sint16 *) (((size_t) (enc->dwt_buffer2_a)) & ~15);
71 
72 #if defined(RFX_USE_ACCEL_X86)
73     cpuid_x86(1, 0, &ax, &bx, &cx, &dx);
74 #elif defined(RFX_USE_ACCEL_AMD64)
75     cpuid_amd64(1, 0, &ax, &bx, &cx, &dx);
76 #else
77     ax = 0;
78     bx = 0;
79     cx = 0;
80     dx = 0;
81 #endif
82     if (dx & (1 << 26)) /* SSE 2 */
83     {
84         printf("rfxcodec_encode_create: got sse2\n");
85         enc->got_sse2 = 1;
86     }
87     if (cx & (1 << 0)) /* SSE 3 */
88     {
89         printf("rfxcodec_encode_create: got sse3\n");
90         enc->got_sse3 = 1;
91     }
92     if (cx & (1 << 19)) /* SSE 4.1 */
93     {
94         printf("rfxcodec_encode_create: got sse4.1\n");
95         enc->got_sse41 = 1;
96     }
97     if (cx & (1 << 20)) /* SSE 4.2 */
98     {
99         printf("rfxcodec_encode_create: got sse4.2\n");
100         enc->got_sse42 = 1;
101     }
102     if (cx & (1 << 23)) /* popcnt */
103     {
104         printf("rfxcodec_encode_create: got popcnt\n");
105         enc->got_popcnt = 1;
106     }
107 #if defined(RFX_USE_ACCEL_X86)
108     cpuid_x86(0x80000001, 0, &ax, &bx, &cx, &dx);
109 #elif defined(RFX_USE_ACCEL_AMD64)
110     cpuid_amd64(0x80000001, 0, &ax, &bx, &cx, &dx);
111 #else
112     ax = 0;
113     bx = 0;
114     cx = 0;
115     dx = 0;
116 #endif
117     if (cx & (1 << 5)) /* lzcnt */
118     {
119         printf("rfxcodec_encode_create: got lzcnt\n");
120         enc->got_lzcnt = 1;
121     }
122     if (cx & (1 << 6)) /* SSE 4.a */
123     {
124         printf("rfxcodec_encode_create: got sse4.a\n");
125         enc->got_sse4a = 1;
126     }
127 
128     enc->width = width;
129     enc->height = height;
130     enc->mode = RLGR3;
131     if (flags & RFX_FLAGS_RLGR1)
132     {
133         enc->mode = RLGR1;
134     }
135     switch (format)
136     {
137         case RFX_FORMAT_BGRA:
138             enc->bits_per_pixel = 32;
139             break;
140         case RFX_FORMAT_RGBA:
141             enc->bits_per_pixel = 32;
142             break;
143         case RFX_FORMAT_BGR:
144             enc->bits_per_pixel = 24;
145             break;
146         case RFX_FORMAT_RGB:
147             enc->bits_per_pixel = 24;
148             break;
149         case RFX_FORMAT_YUV:
150             enc->bits_per_pixel = 32;
151             break;
152         default:
153             free(enc);
154             return 2;
155     }
156     enc->format = format;
157     enc->rfx_encode_rgb_to_yuv = rfx_encode_rgb_to_yuv;
158     enc->rfx_encode_argb_to_yuva = rfx_encode_argb_to_yuva;
159     /* assign encoding functions */
160     if (flags & RFX_FLAGS_NOACCEL)
161     {
162         if (enc->mode == RLGR3)
163         {
164             printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr3\n");
165             enc->rfx_encode = rfx_encode_component_rlgr3; /* rfxencode_tile.c */
166         }
167         else
168         {
169             printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr1\n");
170             enc->rfx_encode = rfx_encode_component_rlgr1; /* rfxencode_tile.c */
171         }
172     }
173     else
174     {
175 #if defined(RFX_USE_ACCEL_X86)
176         if (enc->got_sse41)
177         {
178             if (enc->mode == RLGR3)
179             {
180                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr3_x86_sse41\n");
181                 enc->rfx_encode = rfx_encode_component_rlgr3_x86_sse41; /* rfxencode_tile.c */
182             }
183             else
184             {
185                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr1_x86_sse41\n");
186                 enc->rfx_encode = rfx_encode_component_rlgr1_x86_sse41; /* rfxencode_tile.c */
187             }
188         }
189         else if (enc->got_sse2)
190         {
191             if (enc->mode == RLGR3)
192             {
193                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr3_x86_sse2\n");
194                 enc->rfx_encode = rfx_encode_component_rlgr3_x86_sse2; /* rfxencode_tile.c */
195             }
196             else
197             {
198                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr1_x86_sse2\n");
199                 enc->rfx_encode = rfx_encode_component_rlgr1_x86_sse2; /* rfxencode_tile.c */
200             }
201         }
202         else
203         {
204             if (enc->mode == RLGR3)
205             {
206                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr3\n");
207                 enc->rfx_encode = rfx_encode_component_rlgr3; /* rfxencode_tile.c */
208             }
209             else
210             {
211                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr1\n");
212                 enc->rfx_encode = rfx_encode_component_rlgr1; /* rfxencode_tile.c */
213             }
214         }
215 #elif defined(RFX_USE_ACCEL_AMD64)
216         if (enc->got_sse41)
217         {
218             if (enc->mode == RLGR3)
219             {
220                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr3_amd64_sse41\n");
221                 enc->rfx_encode = rfx_encode_component_rlgr3_amd64_sse41; /* rfxencode_tile.c */
222             }
223             else
224             {
225                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr1_amd64_sse41\n");
226                 enc->rfx_encode = rfx_encode_component_rlgr1_amd64_sse41; /* rfxencode_tile.c */
227             }
228         }
229         else if (enc->got_sse2)
230         {
231             if (enc->mode == RLGR3)
232             {
233                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr3_amd64_sse2\n");
234                 enc->rfx_encode = rfx_encode_component_rlgr3_amd64_sse2; /* rfxencode_tile.c */
235             }
236             else
237             {
238                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr1_amd64_sse2\n");
239                 enc->rfx_encode = rfx_encode_component_rlgr1_amd64_sse2; /* rfxencode_tile.c */
240             }
241         }
242         else
243         {
244             if (enc->mode == RLGR3)
245             {
246                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr3\n");
247                 enc->rfx_encode = rfx_encode_component_rlgr3; /* rfxencode_tile.c */
248             }
249             else
250             {
251                 printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr1\n");
252                 enc->rfx_encode = rfx_encode_component_rlgr1; /* rfxencode_tile.c */
253             }
254         }
255 #else
256         if (enc->mode == RLGR3)
257         {
258             printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr3\n");
259             enc->rfx_encode = rfx_encode_component_rlgr3; /* rfxencode_tile.c */
260         }
261         else
262         {
263             printf("rfxcodec_encode_create: rfx_encode set to rfx_encode_component_rlgr1\n");
264             enc->rfx_encode = rfx_encode_component_rlgr1; /* rfxencode_tile.c */
265         }
266 #endif
267     }
268     if (ax == 0)
269     {
270     }
271     if (bx == 0)
272     {
273     }
274     *handle = enc;
275     return 0;
276 }
277 
278 /******************************************************************************/
279 void *
rfxcodec_encode_create(int width,int height,int format,int flags)280 rfxcodec_encode_create(int width, int height, int format, int flags)
281 {
282     int error;
283     void *handle;
284 
285     error = rfxcodec_encode_create_ex(width, height, format, flags, &handle);
286     if (error == 0)
287     {
288         return handle;
289     }
290     return 0;
291 }
292 
293 /******************************************************************************/
294 int
rfxcodec_encode_destroy(void * handle)295 rfxcodec_encode_destroy(void *handle)
296 {
297     struct rfxencode *enc;
298 
299     enc = (struct rfxencode *) handle;
300     if (enc == NULL)
301     {
302         return 0;
303     }
304     free(enc);
305     return 0;
306 }
307 
308 /******************************************************************************/
309 int
rfxcodec_encode_ex(void * handle,char * cdata,int * cdata_bytes,const char * buf,int width,int height,int stride_bytes,const struct rfx_rect * regions,int num_regions,const struct rfx_tile * tiles,int num_tiles,const char * quants,int num_quants,int flags)310 rfxcodec_encode_ex(void *handle, char *cdata, int *cdata_bytes,
311                    const char *buf, int width, int height, int stride_bytes,
312                    const struct rfx_rect *regions, int num_regions,
313                    const struct rfx_tile *tiles, int num_tiles,
314                    const char *quants, int num_quants, int flags)
315 {
316     struct rfxencode *enc;
317     STREAM s;
318 
319     enc = (struct rfxencode *) handle;
320 
321     s.data = (uint8 *) cdata;
322     s.p = s.data;
323     s.size = *cdata_bytes;
324 
325     /* Only the first frame should send the RemoteFX header */
326     if ((enc->frame_idx == 0) && (enc->header_processed == 0))
327     {
328         if (rfx_compose_message_header(enc, &s) != 0)
329         {
330             return 1;
331         }
332     }
333     if (rfx_compose_message_data(enc, &s, regions, num_regions,
334                                  buf, width, height, stride_bytes,
335                                  tiles, num_tiles, quants, num_quants,
336                                  flags) != 0)
337     {
338         return 1;
339     }
340     *cdata_bytes = (int) (s.p - s.data);
341     return 0;
342 }
343 
344 /******************************************************************************/
345 int
rfxcodec_encode(void * handle,char * cdata,int * cdata_bytes,const char * buf,int width,int height,int stride_bytes,const struct rfx_rect * regions,int num_regions,const struct rfx_tile * tiles,int num_tiles,const char * quants,int num_quants)346 rfxcodec_encode(void *handle, char *cdata, int *cdata_bytes,
347                 const char *buf, int width, int height, int stride_bytes,
348                 const struct rfx_rect *regions, int num_regions,
349                 const struct rfx_tile *tiles, int num_tiles,
350                 const char *quants, int num_quants)
351 {
352     return rfxcodec_encode_ex(handle, cdata, cdata_bytes, buf, width, height,
353                               stride_bytes, regions, num_regions, tiles,
354                               num_tiles, quants, num_quants, 0);
355 }
356 
357 /******************************************************************************/
358 int
rfxcodec_encode_get_internals(struct rfxcodec_encode_internals * internals)359 rfxcodec_encode_get_internals(struct rfxcodec_encode_internals *internals)
360 {
361     memset(internals, 0, sizeof(struct rfxcodec_encode_internals));
362     internals->rfxencode_rlgr1 = rfx_rlgr1_encode;
363     internals->rfxencode_rlgr3 = rfx_rlgr3_encode;
364     internals->rfxencode_differential = rfx_differential_encode;
365     internals->rfxencode_quantization = rfx_quantization_encode;
366     internals->rfxencode_dwt_2d = rfx_dwt_2d_encode;
367     internals->rfxencode_diff_rlgr1 = rfx_encode_diff_rlgr1;
368     internals->rfxencode_diff_rlgr3 = rfx_encode_diff_rlgr3;
369 #if defined(RFX_USE_ACCEL_X86)
370     internals->rfxencode_dwt_shift_x86_sse2 = rfxcodec_encode_dwt_shift_x86_sse2;
371     internals->rfxencode_dwt_shift_x86_sse41 = rfxcodec_encode_dwt_shift_x86_sse41;
372 #endif
373 #if defined(RFX_USE_ACCEL_AMD64)
374     internals->rfxencode_dwt_shift_amd64_sse2 = rfxcodec_encode_dwt_shift_amd64_sse2;
375     internals->rfxencode_dwt_shift_amd64_sse41 = rfxcodec_encode_dwt_shift_amd64_sse41;
376 #endif
377     return 0;
378 }
379