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 static const unsigned char g_rfx_default_quantization_values[] =
35 {
36     /* LL3 LH3 HL3 HH3 LH2 HL2 HH2 LH1 HL1 HH1 */
37     0x66,  0x66,  0x77,  0x88,  0x98,
38     0x99,  0x99,  0xaa,  0xcc,  0xdc
39 };
40 
41 /*****************************************************************************/
42 static int
get_mstime(void)43 get_mstime(void)
44 {
45     struct timeval tp;
46 
47     gettimeofday(&tp, 0);
48     return (tp.tv_sec * 1000) + (tp.tv_usec / 1000);
49 }
50 
51 /******************************************************************************/
52 static int
speed_random(int count,const char * quants)53 speed_random(int count, const char *quants)
54 {
55     void *han;
56     int error;
57     int index;
58     int cdata_bytes;
59     int fd;
60     char *cdata;
61     char *buf;
62     struct rfx_rect regions[1];
63     struct rfx_tile tiles[2];
64     int stime;
65     int etime;
66     int tiles_per_second;
67     int num_regions;
68     int num_tiles;
69     int num_quants;
70     int flags;
71 
72     printf("speed_random:\n");
73     //flags = RFX_FLAGS_RLGR1 | RFX_FLAGS_NOACCEL;
74     flags = RFX_FLAGS_RLGR1;
75     //flags = RFX_FLAGS_RLGR3;
76     //flags = RFX_FLAGS_RLGR1 | RFX_FLAGS_ALPHAV1;
77     error = rfxcodec_encode_create_ex(1920, 1024, RFX_FORMAT_BGRA, flags, &han);
78     if (error != 0)
79     {
80         printf("speed_random: rfxcodec_encode_create_ex failed\n");
81         return 1;
82     }
83     printf("speed_random: rfxcodec_encode_create_ex ok\n");
84     cdata = (char *) malloc(128 * 64 * 4);
85     cdata_bytes = 128 * 64 * 4;
86     buf = (char *) malloc(128 * 64 * 4);
87 #if 1
88     fd = open("/dev/urandom", O_RDONLY);
89     //fd = open("/dev/zero", O_RDONLY);
90     if (read(fd, buf, 128 * 64 * 4) != 128 * 64 * 4)
91     {
92         printf("speed_random: read error\n");
93     }
94     close(fd);
95 #else
96     memset(buf, 0x7f, 128 * 64 * 4);
97 #endif
98     regions[0].x = 0;
99     regions[0].y = 0;
100     regions[0].cx = 128;
101     regions[0].cy = 64;
102     num_regions = 1;
103     tiles[0].x = 0;
104     tiles[0].y = 0;
105     tiles[0].cx = 64;
106     tiles[0].cy = 64;
107     tiles[0].quant_y = 0;
108     tiles[0].quant_cb = 0;
109     tiles[0].quant_cr = 0;
110     tiles[1].x = 64;
111     tiles[1].y = 0;
112     tiles[1].cx = 64;
113     tiles[1].cy = 64;
114     tiles[1].quant_y = 0;
115     tiles[1].quant_cb = 0;
116     tiles[1].quant_cr = 0;
117     num_tiles = 1;
118     num_quants = 1;
119     error = 0;
120     stime = get_mstime();
121     flags = 0;
122     //flags = RFX_FLAGS_ALPHAV1;
123     for (index = 0; index < count; index++)
124     {
125         error = rfxcodec_encode_ex(han, cdata, &cdata_bytes, buf, 64, 64, 64 * 4,
126                                    regions, num_regions, tiles, num_tiles,
127                                    quants, num_quants, flags);
128         if (error != 0)
129         {
130             break;
131         }
132     }
133     etime = get_mstime();
134     tiles_per_second = count * num_tiles * 1000 / (etime - stime + 1);
135     printf("speed_random: cdata_bytes %d count %d ms time %d "
136            "tiles_per_second %d\n",
137            cdata_bytes, count, etime - stime, tiles_per_second);
138     rfxcodec_encode_destroy(han);
139     free(buf);
140     free(cdata);
141     return 0;
142 }
143 
144 struct bmp_magic
145 {
146     char magic[2];
147 };
148 
149 struct bmp_hdr
150 {
151     unsigned int   size;
152     unsigned short reserved1;
153     unsigned short reserved2;
154     unsigned int offset;
155 };
156 
157 struct dib_hdr
158 {
159     unsigned int   hdr_size;
160     int            width;
161     int            height;
162     unsigned short nplanes;
163     unsigned short bpp;
164     unsigned int   compress_type;
165     unsigned int   image_size;
166     int            hres;
167     int            vres;
168     unsigned int   ncolors;
169     unsigned int   nimpcolors;
170 };
171 
172 /******************************************************************************/
173 static int
load_bmp_file(int in_fd,char ** data,int * width,int * height)174 load_bmp_file(int in_fd, char **data, int *width, int *height)
175 {
176     struct bmp_magic bmpm;
177     struct bmp_hdr   bmph;
178     struct dib_hdr   dibh;
179     int awidth;
180     int aheight;
181     int line_bytes;
182     int index;
183     int jndex;
184     int red;
185     int gre;
186     int blu;
187     int *dst32;
188     char *line;
189     char *line_ptr;
190 
191     if (read(in_fd, &bmpm, sizeof(struct bmp_magic)) != sizeof(struct bmp_magic))
192     {
193         return 1;
194     }
195     if (read(in_fd, &bmph, sizeof(struct bmp_hdr)) != sizeof(struct bmp_hdr))
196     {
197         return 1;
198     }
199     if (read(in_fd, &dibh, sizeof(struct dib_hdr)) != sizeof(struct dib_hdr))
200     {
201         return 1;
202     }
203     if (dibh.bpp != 24)
204     {
205         printf("only support 24 bpp bmp file now\n");
206         return 1;
207     }
208     printf("bpp %d\n", dibh.bpp);
209     *width = dibh.width;
210     *height = dibh.height;
211     awidth = (dibh.width + 63) & ~63;
212     aheight = (dibh.height + 63) & ~63;
213     *data = (char *) malloc(awidth * aheight * 4);
214 
215     line_bytes = dibh.width * 3;
216     line_bytes = (line_bytes + 3) & ~3;
217     line = (char *) malloc(line_bytes);
218 
219     memset(*data, 0, awidth * aheight);
220     for (index = 0; index < dibh.height; index++)
221     {
222         dst32 = (int *) (*data);
223         dst32 += index * awidth;
224 
225         line_ptr = line;
226         if (read(in_fd, line, line_bytes) != line_bytes)
227         {
228             return 1;
229         }
230         for (jndex = 0; jndex < dibh.width; jndex++)
231         {
232             red = *(line_ptr++);
233             gre = *(line_ptr++);
234             blu = *(line_ptr++);
235             *(dst32++) = (red << 16) | (gre << 8) | blu;
236         }
237     }
238 
239     free(line);
240 
241     return 0;
242 }
243 
244 /******************************************************************************/
245 static int
encode_file(char * data,int width,int height,char * cdata,int * cdata_bytes,const char * quants,int num_quants)246 encode_file(char *data, int width, int height, char *cdata, int *cdata_bytes,
247             const char *quants, int num_quants)
248 {
249     int awidth;
250     int aheight;
251     int num_tiles;
252     int index;
253     int jndex;
254     int error;
255     int num_regions;
256     struct rfx_tile *tiles;
257     struct rfx_tile *tiles_ptr;
258     void *han;
259     struct rfx_rect regions[1];
260 
261     error = rfxcodec_encode_create_ex(1920, 1024, RFX_FORMAT_BGRA, RFX_FLAGS_RLGR1, &han);
262     if (error != 0)
263     {
264         printf("encode_file: rfxcodec_encode_create_ex failed\n");
265         return 1;
266     }
267 
268     awidth = (width + 63) & ~63;
269     aheight = (height + 63) & ~63;
270 
271     num_tiles = (awidth / 64) * (aheight / 64);
272     tiles = (struct rfx_tile *) malloc(num_tiles * sizeof(struct rfx_tile));
273     tiles_ptr = tiles;
274     for (index = 0; index < aheight; index += 64)
275     {
276         for (jndex = 0; jndex < awidth; jndex += 64)
277         {
278             tiles_ptr[0].x = jndex;
279             tiles_ptr[0].y = index;
280             tiles_ptr[0].cx = 64;
281             tiles_ptr[0].cy = 64;
282             tiles_ptr[0].quant_y = 0;
283             tiles_ptr[0].quant_cb = num_quants - 1;
284             tiles_ptr[0].quant_cr = num_quants - 1;
285             tiles_ptr++;
286         }
287     }
288 
289     regions[0].x = 0;
290     regions[0].y = 0;
291     regions[0].cx = width;
292     regions[0].cy = height;
293     num_regions = 1;
294 
295     error = rfxcodec_encode_ex(han, cdata, cdata_bytes, data, width, height, width * 4,
296                                regions, num_regions, tiles, num_tiles,
297                                quants, num_quants, 0);
298     if (error != 0)
299     {
300         printf("encode_file: rfxcodec_encode failed error %d\n", error);
301         return 1;
302     }
303 
304     rfxcodec_encode_destroy(han);
305 
306 
307     free(tiles);
308     return 0;
309 }
310 
311 /******************************************************************************/
312 static int
read_file(int count,const char * quants,int num_quants,const char * in_file,const char * out_file)313 read_file(int count, const char *quants, int num_quants,
314           const char *in_file, const char *out_file)
315 {
316     int in_fd;
317     int out_fd;
318     int width;
319     int height;
320     int cdata_bytes;
321     char *data;
322     char *cdata;
323 
324     in_fd = open(in_file, O_RDONLY);
325     if (in_fd == -1)
326     {
327         printf("error opening %s\n", in_file);
328         return 1;
329     }
330     out_fd = -1;
331     if (out_file[0] != 0)
332     {
333         if (access(out_file, F_OK) == 0)
334         {
335             printf("out files exists\n");
336             return 1;
337         }
338         out_fd = open(out_file, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
339         if (out_fd == -1)
340         {
341             printf("error opening %s\n", out_file);
342             return 1;
343         }
344     }
345 
346     data = 0;
347     width = 0;
348     height = 0;
349     if (load_bmp_file(in_fd, &data, &width, &height) != 0)
350     {
351         printf("load_bmp_file failed\n");
352         return 1;
353     }
354     printf("loaded file ok width %d height %d\n", width, height);
355     cdata_bytes = (width + 64) * (height + 64);
356     cdata = (char *) malloc(cdata_bytes);
357     if (encode_file(data, width, height, cdata, &cdata_bytes, quants, num_quants) != 0)
358     {
359         printf("encode_file failed\n");
360         return 1;
361     }
362     printf("encode data ok bytes %d\n", cdata_bytes);
363 
364     if (out_fd != -1)
365     {
366         if (write(out_fd, cdata, cdata_bytes) != cdata_bytes)
367         {
368             printf("write failed\n");
369         }
370     }
371 
372     free(data);
373     free(cdata);
374     close(in_fd);
375     if (out_fd != -1)
376     {
377         close(out_fd);
378     }
379     return 0;
380 }
381 
382 /******************************************************************************/
383 static int
out_usage(void)384 out_usage(void)
385 {
386     printf("rfxdectest usage\n");
387     printf("this program is used for testing the rfx encoder for both speed "
388            "and integrity\n");
389     printf("examples\n");
390     printf("  ./rfxcodectest --speed --count 1000\n");
391     printf("  ./rfxcodectest -i infile.bmp -o outfile.rfx\n");
392     printf("\n");
393     return 0;
394 }
395 
396 /******************************************************************************/
397 int
main(int argc,char ** argv)398 main(int argc, char **argv)
399 {
400     int index;
401     int do_speed;
402     int do_read;
403     int count;
404     char in_file[256];
405     char out_file[256];
406     const char *quants = (const char *) g_rfx_default_quantization_values;
407 
408     do_speed = 0;
409     do_read = 0;
410     in_file[0] = 0;
411     out_file[0] = 0;
412     count = 1;
413     if (argc < 2)
414     {
415         return out_usage();
416     }
417     for (index = 1; index < argc; index++)
418     {
419         if (strcmp("--speed", argv[index]) == 0)
420         {
421             do_speed = 1;
422         }
423         else if (strcmp("--count", argv[index]) == 0)
424         {
425             index++;
426             count = atoi(argv[index]);
427         }
428         else if (strcmp("-i", argv[index]) == 0)
429         {
430             index++;
431             snprintf(in_file, 255, "%s", argv[index]);
432             do_read = 1;
433         }
434         else if (strcmp("-o", argv[index]) == 0)
435         {
436             index++;
437             snprintf(out_file, 255, "%s", argv[index]);
438         }
439         else
440         {
441             return out_usage();
442         }
443     }
444     if (do_speed)
445     {
446         speed_random(count, quants);
447     }
448     if (do_read)
449     {
450         read_file(count, quants, 2, in_file, out_file);
451     }
452     return 0;
453 }
454