1 /**
2  * RFX codec encoder test
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 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 
32 #include <rfxcodec_encode.h>
33 
34 #define MAX_OUT_DATA_BYTES (1024 * 1024)
35 #define MAX_BMP_DATA_BYTES (10 * 1024 * 1024)
36 
37 static char g_in_filename[256] = "";
38 static char g_out_filename[256] = "";
39 static int g_count = 1;
40 static int g_no_accel = 0;
41 static int g_use_rlgr1 = 0;
42 
43 struct bmp_magic
44 {
45     char magic[2];
46 };
47 
48 struct bmp_hdr
49 {
50     unsigned int   size;
51     unsigned short reserved1;
52     unsigned short reserved2;
53     unsigned int offset;
54 };
55 
56 struct dib_hdr
57 {
58     unsigned int   hdr_size;
59     int            width;
60     int            height;
61     unsigned short nplanes;
62     unsigned short bpp;
63     unsigned int   compress_type;
64     unsigned int   image_size;
65     int            hres;
66     int            vres;
67     unsigned int   ncolors;
68     unsigned int   nimpcolors;
69 };
70 
71 static int
read_bitmap(char * file_name,int * width,int * height,int * bpp,char * bmp_data)72 read_bitmap(char *file_name, int *width, int *height, int *bpp, char *bmp_data)
73 {
74     int i;
75     int j;
76     int e;
77     int fd;
78     int file_stride_bytes;
79     int pixel;
80     struct bmp_magic bm;
81     struct bmp_hdr bh;
82     struct dib_hdr dh;
83     unsigned char *src8;
84     int *src32;
85     int *dst32;
86 
87     fd = open(file_name, O_RDONLY);
88     if (fd == -1)
89     {
90         return 1;
91     }
92     if (read(fd, &bm, sizeof(bm)) != sizeof(bm))
93     {
94         close(fd);
95         return 1;
96     }
97     if (read(fd, &bh, sizeof(bh)) != sizeof(bh))
98     {
99         close(fd);
100         return 1;
101     }
102     if (read(fd, &dh, sizeof(dh)) != sizeof(dh))
103     {
104         close(fd);
105         return 1;
106     }
107 
108     if (dh.bpp != 24 && dh.bpp != 32)
109     {
110         printf("error, only support 24 and 32 bpp\n");
111         close(fd);
112         return 1;
113     }
114 
115     *width = dh.width;
116     *height = dh.height;
117     *bpp = dh.bpp;
118 
119     file_stride_bytes = dh.width * ((dh.bpp + 7) / 8);
120     e = (4 - file_stride_bytes) & 3;
121     src8 = (unsigned char *) malloc(file_stride_bytes * 4);
122     for (j = 0; j < dh.height; j++)
123     {
124         dst32 = (int *) (bmp_data + (dh.width * dh.height * 4) - ((j + 1) * dh.width * 4));
125         if (read(fd, src8, file_stride_bytes + e) != file_stride_bytes + e)
126         {
127             free(src8);
128             close(fd);
129             return 1;
130         }
131         if (dh.bpp == 32)
132         {
133             src32 = (int *) src8;
134             for (i = 0; i < dh.width; i++)
135             {
136                 pixel = src32[i];
137                 dst32[i] = pixel;
138             }
139         }
140         else if (dh.bpp == 24)
141         {
142             for (i = 0; i < dh.width; i++)
143             {
144                 pixel =  src8[i * 3 + 0] << 0;
145                 pixel |= src8[i * 3 + 1] << 8;
146                 pixel |= src8[i * 3 + 2] << 16;
147                 dst32[i] = pixel;
148             }
149         }
150     }
151 
152     free(src8);
153     close(fd);
154     return 0;
155 }
156 
out_params(void)157 int out_params(void)
158 {
159     printf("rfxencode: a RemoteFX encoder testing program.\n");
160     printf("  -i <in file name> bmp file\n");
161     printf("  -o <out file name> rfx file\n");
162     printf("  -c <number> times to loop\n");
163     printf("  -n no accel\n");
164     printf("  -1 use rlgr1\n");
165     return 0;
166 }
167 
process(void)168 int process(void)
169 {
170     char *out_data;
171     char *bmp_data;
172     int out_fd;
173     int out_bytes;
174     int error;
175     int index;
176     int index_x;
177     int index_y;
178     void *han;
179     int num_tiles;
180     int num_tiles_x;
181     int num_tiles_y;
182     int flags;
183     int width;
184     int height;
185     int bpp;
186     struct rfx_rect region;
187     struct rfx_tile *tiles;
188     struct rfx_tile *tile;
189 
190     out_data = (char *) malloc(MAX_OUT_DATA_BYTES);
191     bmp_data = (char *) malloc(MAX_BMP_DATA_BYTES);
192     memset(bmp_data, 0xff, MAX_BMP_DATA_BYTES);
193 
194     if (read_bitmap(g_in_filename, &width, &height, &bpp, bmp_data) != 0)
195     {
196         printf("read bitmap failed\n");
197         free(bmp_data);
198         free(out_data);
199         return 1;
200     }
201 
202     printf("process: got bitmap width %d height %d bpp %d\n", width, height, bpp);
203 
204     flags = 0;
205     if (g_no_accel)
206     {
207         flags |= RFX_FLAGS_NOACCEL;
208     }
209     if (g_use_rlgr1)
210     {
211         flags |= RFX_FLAGS_RLGR1;
212     }
213     han = rfxcodec_encode_create(1920, 1080, RFX_FORMAT_BGRA, flags);
214 
215     region.x = 0;
216     region.y = 0;
217     region.cx = width;
218     region.cy = height;
219 
220     num_tiles_x = (width + 63) / 64;
221     num_tiles_y = (height + 63) / 64;
222 
223     num_tiles = num_tiles_x * num_tiles_y;
224     tiles = (struct rfx_tile *) calloc(num_tiles, sizeof(struct rfx_tile));
225     if (tiles == NULL)
226     {
227         free(bmp_data);
228         free(out_data);
229         return 1;
230     }
231     for (index_y = 0; index_y < num_tiles_y; index_y++)
232     {
233         for (index_x = 0; index_x < num_tiles_x; index_x++)
234         {
235             tile = tiles + (index_y * num_tiles_x + index_x);
236             tile->x = index_x * 64;
237             tile->y = index_y * 64;
238             tile->cx = 64;
239             tile->cy = 64;
240         }
241     }
242     if (han != NULL)
243     {
244         error = 0;
245         for (index = 0; index < g_count; index++)
246         {
247             out_bytes = 1024 * 1024;
248             error = rfxcodec_encode(han, out_data, &out_bytes, bmp_data,
249                                     width, height, width * 4,
250                                     &region, 1, tiles, num_tiles, NULL, 0);
251             if (error != 0)
252             {
253                 break;
254             }
255         }
256         printf("error %d out_bytes %d num_tiles %d\n", error,
257                out_bytes, num_tiles);
258         if (g_out_filename[0] != 0)
259         {
260             out_fd = open(g_out_filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
261             if (out_fd == -1)
262             {
263                 printf("failed to open %s\n", g_out_filename);
264                 free(bmp_data);
265                 free(out_data);
266                 free(tiles);
267                 return 1;
268             }
269             if (write(out_fd, out_data, out_bytes) != out_bytes)
270             {
271                 printf("write failed\n");
272                 free(bmp_data);
273                 free(out_data);
274                 free(tiles);
275                 close(out_fd);
276                 return 1;
277             }
278             close(out_fd);
279         }
280     }
281     rfxcodec_encode_destroy(han);
282 
283     free(bmp_data);
284     free(out_data);
285     free(tiles);
286     return 0;
287 }
288 
main(int argc,char ** argv)289 int main(int argc, char **argv)
290 {
291     int index;
292 
293     if (argc < 2)
294     {
295         out_params();
296         return 0;
297     }
298     for (index = 1; index < argc; index++)
299     {
300         if (strcmp(argv[index], "-i") == 0)
301         {
302             index++;
303             strcpy(g_in_filename, argv[index]);
304         }
305         else if (strcmp(argv[index], "-o") == 0)
306         {
307             index++;
308             strcpy(g_out_filename, argv[index]);
309         }
310         else if (strcmp(argv[index], "-c") == 0)
311         {
312             index++;
313             g_count = atoi(argv[index]);
314         }
315         else if (strcmp(argv[index], "-n") == 0)
316         {
317             g_no_accel = 1;
318         }
319         else if (strcmp(argv[index], "-1") == 0)
320         {
321             g_use_rlgr1 = 1;
322         }
323         else
324         {
325             out_params();
326             return 0;
327         }
328     }
329     process();
330     return 0;
331 }
332 
333