1 /*****************************************************************
2 * gavl - a general purpose audio/video processing library
3 *
4 * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5 * gmerlin-general@lists.sourceforge.net
6 * http://gmerlin.sourceforge.net
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * *****************************************************************/
21
22
23 #include <config.h>
24 #include <gavl.h>
25 #include <gavldsp.h>
26 #include <accel.h> /* Private header */
27
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <unistd.h>
33
34 #include <sys/time.h>
35 #include <time.h>
36 #include <errno.h>
37
38 #ifdef HAVE_SYS_TIMES_H
39 #include <sys/times.h>
40 #endif
41
42 #ifdef HAVE_SCHED_SETAFFINITY
43 #define __USE_GNU
44 #include <sched.h>
45 #endif
46
47 // #undef ARCH_X86
48
49 #define OUT_PFMT GAVL_RGB_24
50 #define IN_PFMT GAVL_PIXELFORMAT_NONE
51
52 #define SCALE_X (1<<0)
53 #define SCALE_Y (1<<1)
54
55 static int opt_scaledir = 0;
56
57 // #define INIT_RUNS 5
58 // #define NUM_RUNS 10
59
60 #define INIT_RUNS 10
61 #define NUM_RUNS 200
62
63 int do_html = 0;
64 gavl_pixelformat_t opt_pfmt1 = GAVL_PIXELFORMAT_NONE;
65 gavl_pixelformat_t opt_pfmt2 = GAVL_PIXELFORMAT_NONE;
66
67 typedef struct
68 {
69 uint64_t times[NUM_RUNS];
70 uint64_t min;
71 uint64_t max;
72 uint64_t avg;
73
74 void (*func)(void*);
75 void (*init)(void*);
76 void *data;
77
78 int accel_supported;
79 int num_discard;
80
81 } gavl_benchmark_t;
82
83 /* Fill frames with random numbers */
84
init_video_frame(gavl_video_format_t * format,gavl_video_frame_t * f)85 static void init_video_frame(gavl_video_format_t * format, gavl_video_frame_t * f)
86 {
87 int i, j, num;
88 int num_planes;
89 int32_t * pixels_i;
90 float * pixels_f;
91 int sub_h, sub_v;
92
93 switch(format->pixelformat)
94 {
95 case GAVL_RGB_FLOAT:
96 for(i = 0; i < format->image_height; i++)
97 {
98 pixels_f = (float*)(f->planes[0] + i * f->strides[0]);
99 for(j = 0; j < format->image_width; j++)
100 {
101 pixels_f[0] = (float)rand() / RAND_MAX;
102 pixels_f[1] = (float)rand() / RAND_MAX;
103 pixels_f[2] = (float)rand() / RAND_MAX;
104 pixels_f+=3;
105 }
106 }
107 break;
108 case GAVL_RGBA_FLOAT:
109 for(i = 0; i < format->image_height; i++)
110 {
111 pixels_f = (float*)(f->planes[0] + i * f->strides[0]);
112 for(j = 0; j < format->image_width; j++)
113 {
114 pixels_f[0] = (float)rand() / RAND_MAX;
115 pixels_f[1] = (float)rand() / RAND_MAX;
116 pixels_f[2] = (float)rand() / RAND_MAX;
117 pixels_f[4] = (float)rand() / RAND_MAX;
118 pixels_f+=4;
119 }
120 }
121 break;
122 default:
123 num_planes = gavl_pixelformat_num_planes(format->pixelformat);
124 gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
125 num = 0;
126 for(i = 0; i < num_planes; i++)
127 {
128 num += (f->strides[i] * format->image_height)
129 / (1 + (!!i) * (sub_v-1));
130 }
131
132 pixels_i = (int*)(f->planes[0]);
133
134 for(i = 0; i < format->image_height/sub_v; i++)
135 {
136 pixels_i[i] = rand();
137 }
138
139 break;
140 }
141
142 }
143
144
gavl_benchmark_run(gavl_benchmark_t * b)145 static void gavl_benchmark_run(gavl_benchmark_t * b)
146 {
147 int i;
148 uint64_t time_before;
149 uint64_t time_after;
150 b->accel_supported = gavl_accel_supported();
151 b->avg = 0;
152
153 for(i = 0; i < INIT_RUNS + NUM_RUNS; i++)
154 {
155 if(b->init)
156 b->init(b->data);
157 time_before = gavl_benchmark_get_time(b->accel_supported);
158 b->func(b->data);
159 time_after = gavl_benchmark_get_time(b->accel_supported);
160
161 if(i >= INIT_RUNS)
162 {
163 b->times[i-INIT_RUNS] = time_after - time_before;
164 b->avg += b->times[i-INIT_RUNS];
165 }
166 }
167
168 b->avg /= NUM_RUNS;
169 b->num_discard = 0;
170
171 for(i = 0; i < NUM_RUNS; i++)
172 {
173 if(b->times[i] > (3 * b->avg)/2)
174 {
175 b->times[i] = 0;
176 b->num_discard++;
177 }
178 }
179 i = 0;
180 while(!b->times[i])
181 i++;
182
183 b->min = b->times[i];
184 b->max = b->times[i];
185 b->avg = b->times[i];
186 i++;
187
188 while(i < NUM_RUNS)
189 {
190 if(!b->times[i])
191 {
192 i++;
193 continue;
194 }
195 if(b->times[i] > b->max)
196 b->max = b->times[i];
197 if(b->times[i] < b->min)
198 b->min = b->times[i];
199
200 b->avg += b->times[i];
201 i++;
202 }
203 b->avg /= (NUM_RUNS-b->num_discard);
204 }
205
gavl_benchmark_print_header(gavl_benchmark_t * b)206 static void gavl_benchmark_print_header(gavl_benchmark_t * b)
207 {
208 if(do_html)
209 {
210 printf("<td align=\"right\">Average</td><td align=\"right\">Minimum</td><td align=\"right\">Maximum</td><td align=\"right\">Discarded</td>");
211 }
212 else
213 {
214 printf(" Average Minimum Maximum Discarded");
215 }
216 }
217
gavl_benchmark_print_results(gavl_benchmark_t * b)218 static void gavl_benchmark_print_results(gavl_benchmark_t * b)
219 {
220 if(do_html)
221 {
222 printf("<td align=\"right\">%"PRId64"</td><td align=\"right\">%"PRId64"</td><td align=\"right\">%"PRId64"</td><td align=\"right\">%d</td>",
223 b->avg, b->min, b->max, b->num_discard);
224 }
225 else
226 printf("%8"PRId64" %8"PRId64" %8"PRId64" %4d",
227 b->avg, b->min, b->max, b->num_discard);
228 }
229
230 /* Audio conversions */
231
232 typedef struct
233 {
234 gavl_audio_format_t in_format;
235 gavl_audio_format_t out_format;
236
237 gavl_audio_converter_t * cnv;
238 gavl_audio_options_t * opt;
239
240 gavl_audio_frame_t * in_frame;
241 gavl_audio_frame_t * out_frame;
242
243 } audio_convert_context_t;
244
audio_convert_context_create(audio_convert_context_t * ctx)245 static void audio_convert_context_create(audio_convert_context_t * ctx)
246 {
247 ctx->cnv = gavl_audio_converter_create();
248 ctx->opt = gavl_audio_converter_get_options(ctx->cnv);
249 }
250
251
audio_convert_context_init(audio_convert_context_t * ctx)252 static void audio_convert_context_init(audio_convert_context_t * ctx)
253 {
254 ctx->in_frame = gavl_audio_frame_create(&ctx->in_format);
255 ctx->out_frame = gavl_audio_frame_create(&ctx->out_format);
256 gavl_audio_converter_init(ctx->cnv, &ctx->in_format, &ctx->out_format);
257 }
258
audio_convert_context_cleanup(audio_convert_context_t * ctx)259 static void audio_convert_context_cleanup(audio_convert_context_t * ctx)
260 {
261 gavl_audio_frame_destroy(ctx->in_frame);
262 gavl_audio_frame_destroy(ctx->out_frame);
263 }
264
audio_convert_context_destroy(audio_convert_context_t * ctx)265 static void audio_convert_context_destroy(audio_convert_context_t * ctx)
266 {
267 gavl_audio_converter_destroy(ctx->cnv);
268 }
269
audio_convert_init(void * data)270 static void audio_convert_init(void * data)
271 {
272 audio_convert_context_t * ctx = data;
273 ctx->in_frame->valid_samples = ctx->in_format.samples_per_frame;
274 }
275
audio_convert_func(void * data)276 static void audio_convert_func(void * data)
277 {
278 audio_convert_context_t * ctx = data;
279 gavl_audio_convert(ctx->cnv, ctx->in_frame, ctx->out_frame);
280 }
281
282 static const gavl_sample_format_t sampleformats[] =
283 {
284 GAVL_SAMPLE_U8, /*!< Unsigned 8 bit */
285 GAVL_SAMPLE_S8, /*!< Signed 8 bit */
286 GAVL_SAMPLE_U16, /*!< Unsigned 16 bit */
287 GAVL_SAMPLE_S16, /*!< Signed 16 bit */
288 GAVL_SAMPLE_S32, /*!< Signed 32 bit */
289 GAVL_SAMPLE_FLOAT, /*!< Floating point (-1.0 .. 1.0) */
290 GAVL_SAMPLE_DOUBLE /*!< Double (-1.0 .. 1.0) */
291 };
292
293 static const struct
294 {
295 gavl_audio_dither_mode_t mode;
296 const char * name;
297 }
298 dither_modes[] =
299 {
300 { GAVL_AUDIO_DITHER_NONE, "None" },
301 { GAVL_AUDIO_DITHER_RECT, "Rect"},
302 { GAVL_AUDIO_DITHER_TRI, "Triangular" },
303 { GAVL_AUDIO_DITHER_SHAPED, "Shaped" }
304 };
305
benchmark_sampleformat()306 static void benchmark_sampleformat()
307 {
308 int num_sampleformats;
309 int num_dither_modes;
310 gavl_sample_format_t in_format;
311 gavl_sample_format_t out_format;
312
313 int i, j, k;
314
315 audio_convert_context_t ctx;
316 gavl_benchmark_t b;
317 memset(&ctx, 0, sizeof(ctx));
318 memset(&b, 0, sizeof(b));
319
320 b.init = audio_convert_init;
321 b.func = audio_convert_func;
322 b.data = &ctx;
323
324 ctx.in_format.num_channels = 2;
325 ctx.in_format.samplerate = 48000;
326 ctx.in_format.interleave_mode = GAVL_INTERLEAVE_NONE;
327 ctx.in_format.channel_locations[0] = GAVL_CHID_NONE;
328 ctx.in_format.samples_per_frame = 10240;
329
330 gavl_set_channel_setup(&ctx.in_format);
331
332 gavl_audio_format_copy(&ctx.out_format, &ctx.in_format);
333
334 num_sampleformats = sizeof(sampleformats)/sizeof(sampleformats[0]);
335 num_dither_modes = sizeof(dither_modes)/sizeof(dither_modes[0]);
336
337 audio_convert_context_create(&ctx);
338
339 printf("Conversion of %d samples, %d channels\n", ctx.in_format.samples_per_frame,
340 ctx.in_format.num_channels);
341
342 if(do_html)
343 {
344 printf("<p><table border=\"1\" width=\"100%%\"><tr><td>Conversion</td><td>Dithering</td>");
345 gavl_benchmark_print_header(&b);
346 printf("</tr>\n");
347 }
348 else
349 {
350 printf("\nConversion Dithering ");
351 gavl_benchmark_print_header(&b);
352 printf("\n");
353 }
354
355 for(i = 0; i < num_sampleformats; i++)
356 {
357 in_format = sampleformats[i];
358 ctx.in_format.sample_format = in_format;
359 for(j = 0; j < num_sampleformats; j++)
360 {
361 out_format = sampleformats[j];
362 if(in_format == out_format)
363 continue;
364
365 ctx.out_format.sample_format = out_format;
366
367 if((gavl_bytes_per_sample(out_format) > 2) ||
368 (in_format < GAVL_SAMPLE_FLOAT))
369 {
370 if(do_html)
371 {
372 printf("<td>%s -> %s</td><td>Not available</td>",
373 gavl_sample_format_to_string(in_format),
374 gavl_sample_format_to_string(out_format));
375 }
376 else
377 printf("%-16s -> %-16s - ",
378 gavl_sample_format_to_string(in_format),
379 gavl_sample_format_to_string(out_format));
380
381 gavl_audio_options_set_dither_mode(ctx.opt, GAVL_AUDIO_DITHER_NONE);
382 audio_convert_context_init(&ctx);
383 gavl_benchmark_run(&b);
384 audio_convert_context_cleanup(&ctx);
385 gavl_benchmark_print_results(&b);
386
387 if(do_html)
388 {
389 printf("</tr>");
390 }
391 printf("\n");
392 fflush(stdout);
393 }
394 else
395 {
396 for(k = 0; k < num_dither_modes; k++)
397 {
398 if(do_html)
399 {
400 printf("<td>%s -> %s</td><td>%s</td>",
401 gavl_sample_format_to_string(in_format),
402 gavl_sample_format_to_string(out_format),
403 dither_modes[k].name);
404 }
405 else
406 printf("%-16s -> %-16s %-10s ",
407 gavl_sample_format_to_string(in_format),
408 gavl_sample_format_to_string(out_format),
409 dither_modes[k].name);
410
411 gavl_audio_options_set_dither_mode(ctx.opt, dither_modes[k].mode);
412 audio_convert_context_init(&ctx);
413 gavl_benchmark_run(&b);
414 audio_convert_context_cleanup(&ctx);
415 gavl_benchmark_print_results(&b);
416
417 if(do_html)
418 {
419 printf("</tr>");
420 }
421 printf("\n");
422 fflush(stdout);
423 }
424 }
425 }
426 }
427 audio_convert_context_destroy(&ctx);
428
429 if(do_html)
430 printf("</table>\n");
431
432 }
433
benchmark_mix()434 static void benchmark_mix()
435 {
436 int num_sampleformats;
437 gavl_sample_format_t in_format;
438
439 int i;
440
441 audio_convert_context_t ctx;
442 gavl_benchmark_t b;
443 memset(&ctx, 0, sizeof(ctx));
444 memset(&b, 0, sizeof(b));
445
446 b.init = audio_convert_init;
447 b.func = audio_convert_func;
448 b.data = &ctx;
449
450 ctx.in_format.num_channels = 6;
451 ctx.in_format.samplerate = 48000;
452 ctx.in_format.interleave_mode = GAVL_INTERLEAVE_NONE;
453 ctx.in_format.channel_locations[0] = GAVL_CHID_NONE;
454 ctx.in_format.samples_per_frame = 102400;
455
456 gavl_set_channel_setup(&ctx.in_format);
457
458 gavl_audio_format_copy(&ctx.out_format, &ctx.in_format);
459
460 ctx.out_format.num_channels = 2;
461 ctx.out_format.channel_locations[0] = GAVL_CHID_NONE;
462 gavl_set_channel_setup(&ctx.out_format);
463
464 num_sampleformats = sizeof(sampleformats)/sizeof(sampleformats[0]);
465 audio_convert_context_create(&ctx);
466
467 printf("Mixing of %d samples, from %d to %d channels\n",
468 ctx.in_format.samples_per_frame,
469 ctx.in_format.num_channels,
470 ctx.out_format.num_channels);
471
472 if(do_html)
473 {
474 printf("<p>\n<table border=\"1\" width=\"100%%\"><tr><td>Sampleformat</td>");
475 gavl_benchmark_print_header(&b);
476 printf("</tr>\n");
477 }
478 else
479 {
480 printf("\nSampleformat ");
481 gavl_benchmark_print_header(&b);
482 printf("\n");
483 }
484
485
486 for(i = 0; i < num_sampleformats; i++)
487 {
488 in_format = sampleformats[i];
489 ctx.in_format.sample_format = in_format;
490 ctx.out_format.sample_format = in_format;
491 if(do_html)
492 {
493 printf("<td>%s</td>", gavl_sample_format_to_string(in_format));
494 }
495 else
496 printf("%-16s ", gavl_sample_format_to_string(in_format));
497 audio_convert_context_init(&ctx);
498 gavl_benchmark_run(&b);
499 audio_convert_context_cleanup(&ctx);
500 gavl_benchmark_print_results(&b);
501
502 if(do_html)
503 {
504 printf("</tr>");
505 }
506 printf("\n");
507 fflush(stdout);
508 }
509
510 audio_convert_context_destroy(&ctx);
511
512 if(do_html)
513 printf("</table>\n");
514
515 }
516
517 static const struct
518 {
519 gavl_resample_mode_t mode;
520 char * name;
521 }
522 resample_modes[] =
523 {
524 { GAVL_RESAMPLE_ZOH, "Zero order hold" },
525 { GAVL_RESAMPLE_LINEAR, "Linear" },
526 { GAVL_RESAMPLE_SINC_FAST, "Sinc fast" },
527 { GAVL_RESAMPLE_SINC_MEDIUM, "Sinc medium" },
528 { GAVL_RESAMPLE_SINC_BEST, "Sinc best" }
529 };
530
531 static const gavl_sample_format_t resample_sampleformats[] =
532 {
533 // GAVL_SAMPLE_U8, /*!< Unsigned 8 bit */
534 // GAVL_SAMPLE_S8, /*!< Signed 8 bit */
535 // GAVL_SAMPLE_U16, /*!< Unsigned 16 bit */
536 // GAVL_SAMPLE_S16, /*!< Signed 16 bit */
537 // GAVL_SAMPLE_S32, /*!< Signed 32 bit */
538 GAVL_SAMPLE_FLOAT, /*!< Floating point (-1.0 .. 1.0) */
539 GAVL_SAMPLE_DOUBLE /*!< Double (-1.0 .. 1.0) */
540 };
541
benchmark_resample()542 static void benchmark_resample()
543 {
544 int num_sampleformats;
545 int num_resample_modes;
546 gavl_sample_format_t in_format;
547
548 int i, j;
549
550 audio_convert_context_t ctx;
551 gavl_benchmark_t b;
552 memset(&ctx, 0, sizeof(ctx));
553 memset(&b, 0, sizeof(b));
554
555 b.init = audio_convert_init;
556 b.func = audio_convert_func;
557 b.data = &ctx;
558
559 ctx.in_format.num_channels = 2;
560 ctx.in_format.samplerate = 48000;
561 ctx.in_format.interleave_mode = GAVL_INTERLEAVE_NONE;
562 ctx.in_format.channel_locations[0] = GAVL_CHID_NONE;
563 ctx.in_format.samples_per_frame = 48000;
564 gavl_set_channel_setup(&ctx.in_format);
565
566 gavl_audio_format_copy(&ctx.out_format, &ctx.in_format);
567
568 ctx.out_format.samplerate = 44100;
569
570 num_sampleformats =
571 sizeof(resample_sampleformats)/sizeof(resample_sampleformats[0]);
572 num_resample_modes =
573 sizeof(resample_modes)/sizeof(resample_modes[0]);
574
575 audio_convert_context_create(&ctx);
576
577 printf("Resampling of %d samples (%d channels), from %d to %d\n",
578 ctx.in_format.samples_per_frame,
579 ctx.in_format.num_channels,
580 ctx.in_format.samplerate,
581 ctx.out_format.samplerate);
582
583 if(do_html)
584 {
585 printf("<p>\n<table border=\"1\" width=\"100%%\"><tr><td>Sampleformat</td><td>Method</td>");
586 gavl_benchmark_print_header(&b);
587 printf("</tr>\n");
588 }
589 else
590 {
591 printf("\nSampleformat Method ");
592 gavl_benchmark_print_header(&b);
593 printf("\n");
594
595 }
596
597 for(i = 0; i < num_sampleformats; i++)
598 {
599 in_format = resample_sampleformats[i];
600 ctx.in_format.sample_format = in_format;
601 ctx.out_format.sample_format = in_format;
602
603 for(j = 0; j < num_resample_modes; j++)
604 {
605 gavl_audio_options_set_resample_mode(ctx.opt, resample_modes[j].mode);
606
607 if(do_html)
608 {
609 printf("<td>%s</td><td>%s</td>",
610 gavl_sample_format_to_string(in_format),
611 resample_modes[j].name);
612 }
613 else
614 {
615 printf("%-16s %-15s ",
616 gavl_sample_format_to_string(in_format),
617 resample_modes[j].name);
618
619 }
620
621 audio_convert_context_init(&ctx);
622 gavl_benchmark_run(&b);
623 audio_convert_context_cleanup(&ctx);
624 gavl_benchmark_print_results(&b);
625
626 if(do_html)
627 printf("</tr>");
628 printf("\n");
629 fflush(stdout);
630 }
631 }
632
633 audio_convert_context_destroy(&ctx);
634
635 if(do_html)
636 printf("</table>\n");
637
638 }
639
640
641 /* Video converter */
642
643 typedef struct
644 {
645 gavl_video_format_t in_format;
646 gavl_video_format_t out_format;
647
648 gavl_video_converter_t * cnv;
649 gavl_video_options_t * opt;
650
651 gavl_video_frame_t * in_frame;
652 gavl_video_frame_t * out_frame;
653
654 } video_convert_context_t;
655
video_convert_context_create(video_convert_context_t * ctx)656 static void video_convert_context_create(video_convert_context_t * ctx)
657 {
658 ctx->cnv = gavl_video_converter_create();
659 ctx->opt = gavl_video_converter_get_options(ctx->cnv);
660 }
661
video_convert_context_init(video_convert_context_t * ctx)662 static int video_convert_context_init(video_convert_context_t * ctx)
663 {
664 int result;
665 ctx->in_frame = gavl_video_frame_create(&ctx->in_format);
666 ctx->out_frame = gavl_video_frame_create(&ctx->out_format);
667 result = gavl_video_converter_init(ctx->cnv, &ctx->in_format, &ctx->out_format);
668 // fprintf(stderr, "Result: %d\n", result);
669 return result <= 0 ? 0 : 1;
670 }
671
video_convert_context_cleanup(video_convert_context_t * ctx)672 static void video_convert_context_cleanup(video_convert_context_t * ctx)
673 {
674 gavl_video_frame_destroy(ctx->in_frame);
675 gavl_video_frame_destroy(ctx->out_frame);
676 }
677
video_convert_context_destroy(video_convert_context_t * ctx)678 static void video_convert_context_destroy(video_convert_context_t * ctx)
679 {
680 gavl_video_converter_destroy(ctx->cnv);
681 }
682
683
video_convert_init(void * data)684 static void video_convert_init(void * data)
685 {
686
687 video_convert_context_t * ctx = data;
688 /* Fill frame with random numbers */
689 init_video_frame(&ctx->in_format, ctx->in_frame);
690 }
691
video_convert_func(void * data)692 static void video_convert_func(void * data)
693 {
694 video_convert_context_t * ctx = data;
695 gavl_video_convert(ctx->cnv, ctx->in_frame, ctx->out_frame);
696 }
697
698 static const struct
699 {
700 gavl_scale_mode_t mode;
701 const char * name;
702 }
703 scale_modes[] =
704 {
705 { GAVL_SCALE_NEAREST, "Nearest" },
706 { GAVL_SCALE_BILINEAR, "Linear"},
707 { GAVL_SCALE_QUADRATIC, "Quadratic" },
708 { GAVL_SCALE_CUBIC_BSPLINE, "Cubic B-Spline" },
709 { GAVL_SCALE_CUBIC_CATMULL, "Cubic Catmull-Rom" },
710 { GAVL_SCALE_CUBIC_MITCHELL, "Cubic Mitchell-Netravali" },
711 { GAVL_SCALE_SINC_LANCZOS, "Sinc" },
712 };
713
do_pixelformat(video_convert_context_t * ctx,gavl_benchmark_t * b,gavl_pixelformat_t in_format,gavl_pixelformat_t out_format,char * name)714 static void do_pixelformat(video_convert_context_t * ctx,
715 gavl_benchmark_t * b, gavl_pixelformat_t in_format,
716 gavl_pixelformat_t out_format, char * name)
717 {
718 int flags;
719 int in_sub_h;
720 int in_sub_v;
721 int out_sub_h;
722 int out_sub_v;
723 int i;
724
725 gavl_pixelformat_chroma_sub(in_format, &in_sub_h, &in_sub_v);
726 gavl_pixelformat_chroma_sub(out_format, &out_sub_h, &out_sub_v);
727 ctx->in_format.pixelformat = in_format;
728 ctx->out_format.pixelformat = out_format;
729
730 if((in_sub_h == out_sub_h) && (in_sub_v == out_sub_v))
731 {
732 flags = gavl_video_options_get_conversion_flags(ctx->opt);
733 flags &= ~GAVL_RESAMPLE_CHROMA;
734 gavl_video_options_set_conversion_flags(ctx->opt, flags);
735
736 if(video_convert_context_init(ctx))
737 {
738 if(do_html)
739 {
740 printf("<tr><td>%s</td><td>Not needed</td>", name);
741 }
742 else
743 printf("%-6s - ", name);
744
745 gavl_benchmark_run(b);
746 gavl_benchmark_print_results(b);
747 if(do_html)
748 printf("</tr>\n");
749 else
750 printf("\n");
751 }
752 video_convert_context_cleanup(ctx);
753 }
754 else
755 {
756 flags = gavl_video_options_get_conversion_flags(ctx->opt);
757 flags &= ~GAVL_RESAMPLE_CHROMA;
758 gavl_video_options_set_conversion_flags(ctx->opt, flags);
759
760 if(video_convert_context_init(ctx))
761 {
762 if(do_html)
763 {
764 printf("<tr><td>%s<td>Off</td>", name);
765 }
766 else
767 printf( "%-6s Off ", name);
768 gavl_benchmark_run(b);
769 gavl_benchmark_print_results(b);
770
771 if(do_html)
772 printf("</tr>\n");
773 else
774 printf("\n");
775 }
776 video_convert_context_cleanup(ctx);
777
778 flags = gavl_video_options_get_conversion_flags(ctx->opt);
779 flags |= GAVL_RESAMPLE_CHROMA;
780 gavl_video_options_set_conversion_flags(ctx->opt, flags);
781
782 for(i = 1; i < sizeof(scale_modes)/sizeof(scale_modes[0]); i++)
783 {
784 gavl_video_options_set_scale_mode(ctx->opt, scale_modes[i].mode);
785
786 if(video_convert_context_init(ctx))
787 {
788 if(do_html)
789 {
790 printf("<tr><td>%s</td><td>%s</td>", name, scale_modes[i].name);
791 }
792 else
793 printf("%-6s %-24s ", name, scale_modes[i].name);
794 gavl_benchmark_run(b);
795 gavl_benchmark_print_results(b);
796 if(do_html)
797 printf("</tr>\n");
798 else
799 printf("\n");
800 }
801 video_convert_context_cleanup(ctx);
802 }
803 }
804 }
805
benchmark_pixelformat()806 static void benchmark_pixelformat()
807 {
808 int num_pixelformats;
809 gavl_pixelformat_t in_format;
810 gavl_pixelformat_t out_format;
811 int i, j;
812
813 video_convert_context_t ctx;
814 gavl_benchmark_t b;
815
816 memset(&ctx, 0, sizeof(ctx));
817 memset(&b, 0, sizeof(b));
818
819 b.init = video_convert_init;
820 b.func = video_convert_func;
821 b.data = &ctx;
822
823 ctx.in_format.image_width = 720;
824 ctx.in_format.image_height = 576;
825
826 ctx.in_format.frame_width = 720;
827 ctx.in_format.frame_height = 576;
828 ctx.in_format.pixel_width = 1;
829 ctx.in_format.pixel_height = 1;
830
831 gavl_video_format_copy(&ctx.out_format, &ctx.in_format);
832 printf("Image size: %d x %d\n",
833 ctx.in_format.image_width,
834 ctx.in_format.image_height);
835
836 if(do_html)
837 {
838 printf("<p>\n<table border=\"1\" width=\"100%%\"><tr><td>Flavour</td><td>Chroma resampling</td>");
839 gavl_benchmark_print_header(&b);
840 printf("</tr>\n");
841 }
842 else
843 {
844 printf("\nFlavour Chroma resampling ");
845 gavl_benchmark_print_header(&b);
846 printf("\n");
847
848 }
849
850 num_pixelformats = gavl_num_pixelformats();
851
852 video_convert_context_create(&ctx);
853 /* Disable autoselection */
854 gavl_video_options_set_quality(ctx.opt, 0);
855
856 /* Must set this to prevent a crash (not in gavl but due to
857 * the benchmarking logic)
858 */
859 gavl_video_options_set_alpha_mode(ctx.opt, GAVL_ALPHA_BLEND_COLOR);
860
861 for(i = 0; i < num_pixelformats; i++)
862 {
863 in_format = gavl_get_pixelformat(i);
864
865 if((opt_pfmt1 != GAVL_PIXELFORMAT_NONE) && (opt_pfmt1 != in_format))
866 continue;
867
868 for(j = 0; j < num_pixelformats; j++)
869 {
870 out_format = gavl_get_pixelformat(j);
871
872 if((opt_pfmt2 != GAVL_PIXELFORMAT_NONE) && (opt_pfmt2 != out_format))
873 continue;
874
875
876 if(in_format == out_format)
877 continue;
878
879 if(do_html)
880 printf("<tr><td colspan=\"6\"><b>");
881 printf("%s -> %s", gavl_pixelformat_to_string(in_format),
882 gavl_pixelformat_to_string(out_format));
883 if(do_html)
884 printf("<b></td></tr>");
885 printf("\n");
886
887 /* C-Version */
888
889 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_C);
890 do_pixelformat(&ctx, &b, in_format, out_format, "C");
891 fflush(stdout);
892 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_MMX);
893 do_pixelformat(&ctx, &b, in_format, out_format, "MMX");
894
895 fflush(stdout);
896 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_MMXEXT);
897 do_pixelformat(&ctx, &b, in_format, out_format, "MMXEXT");
898
899 fflush(stdout);
900 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_C_HQ);
901 do_pixelformat(&ctx, &b, in_format, out_format, "HQ");
902 fflush(stdout);
903
904 fflush(stdout);
905 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_SSE);
906 do_pixelformat(&ctx, &b, in_format, out_format, "SSE");
907 fflush(stdout);
908
909 fflush(stdout);
910 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_SSE3);
911 do_pixelformat(&ctx, &b, in_format, out_format, "SSE3");
912 fflush(stdout);
913
914 }
915 }
916
917 if(do_html)
918 printf("</table>\n");
919
920 video_convert_context_destroy(&ctx);
921
922 }
923
924
do_scale(video_convert_context_t * ctx,gavl_benchmark_t * b,gavl_pixelformat_t in_format,const char * name,const char * dirs)925 static void do_scale(video_convert_context_t * ctx,
926 gavl_benchmark_t * b, gavl_pixelformat_t in_format,
927 const char * name, const char * dirs)
928 {
929 int num_scale_modes, i;
930 num_scale_modes = sizeof(scale_modes)/sizeof(scale_modes[0]);
931
932 ctx->in_format.pixelformat = in_format;
933 ctx->out_format.pixelformat = in_format;
934
935 for(i = 0; i < num_scale_modes; i++)
936 {
937 gavl_video_options_set_scale_mode(ctx->opt, scale_modes[i].mode);
938
939 if(video_convert_context_init(ctx))
940 {
941 if(do_html)
942 printf("<tr><td>%s</td><td>%s</td><td>%s</td>", dirs, name, scale_modes[i].name);
943 else
944 printf("%-2s %-6s %-24s ", dirs, name, scale_modes[i].name);
945
946 gavl_benchmark_run(b);
947 gavl_benchmark_print_results(b);
948 if(do_html)
949 printf("</tr>");
950
951 printf("\n");
952
953 }
954
955 fflush(stdout);
956 video_convert_context_cleanup(ctx);
957 }
958 }
959
do_scale_direction(video_convert_context_t * ctx,gavl_benchmark_t * b)960 static void do_scale_direction(video_convert_context_t * ctx,
961 gavl_benchmark_t * b)
962 {
963 int num_pixelformats;
964 gavl_pixelformat_t in_format;
965 int i;
966
967 const char * dir;
968
969 printf("\nDestination size: 1024 x 1024, source size 512 for each scaled direction\n");
970
971 if(do_html)
972 {
973 printf("<p>\n<table border=\"1\" width=\"100%%\"><tr><td>Direction</td><td>Flavour</td><td>Scale method</td>");
974 gavl_benchmark_print_header(b);
975 printf("</tr>\n");
976 }
977 else
978 {
979 printf("Direction Flavour Scale method ");
980 gavl_benchmark_print_header(b);
981 printf("\n");
982 }
983
984 num_pixelformats = gavl_num_pixelformats();
985
986
987 for(i = 0; i < num_pixelformats; i++)
988 // for(i = 0; i < 3; i++)
989 {
990 in_format = gavl_get_pixelformat(i);
991 if((opt_pfmt1 != GAVL_PIXELFORMAT_NONE) &&
992 (opt_pfmt1 != in_format))
993 continue;
994
995 if(do_html)
996 printf("<tr><td colspan=\"7\"><b>%s<b></td></tr>\n",
997 gavl_pixelformat_to_string(in_format));
998 else
999 printf("%s\n", gavl_pixelformat_to_string(in_format));
1000
1001 ctx->out_format.image_width = 1024;
1002 ctx->out_format.image_height = 1024;
1003 ctx->out_format.frame_width = 1024;
1004 ctx->out_format.frame_height = 1024;
1005
1006 ctx->out_format.pixel_width = 1;
1007 ctx->out_format.pixel_height = 1;
1008
1009 /* X */
1010
1011 if(!opt_scaledir || (opt_scaledir == SCALE_X))
1012 {
1013 dir = "x";
1014
1015 gavl_video_format_copy(&ctx->in_format, &ctx->out_format);
1016
1017 ctx->in_format.image_width = 512;
1018 ctx->in_format.frame_width = 512;
1019
1020 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_C);
1021 do_scale(ctx, b, in_format, "C", dir);
1022
1023 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_MMX);
1024 do_scale(ctx, b, in_format, "MMX", dir);
1025
1026 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_MMXEXT);
1027 do_scale(ctx, b, in_format, "MMXEXT", dir);
1028
1029 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_SSE);
1030 do_scale(ctx, b, in_format, "SSE", dir);
1031
1032 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_SSE2);
1033 do_scale(ctx, b, in_format, "SSE2", dir);
1034
1035 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_SSE3);
1036 do_scale(ctx, b, in_format, "SSE3", dir);
1037
1038 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_C_HQ);
1039 do_scale(ctx, b, in_format, "HQ", dir);
1040 }
1041
1042
1043 /* Y */
1044 if(!opt_scaledir || (opt_scaledir == SCALE_Y))
1045 {
1046
1047 dir = "y";
1048
1049 gavl_video_format_copy(&ctx->in_format, &ctx->out_format);
1050
1051 ctx->in_format.image_height = 512;
1052 ctx->in_format.frame_height = 512;
1053
1054 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_C);
1055 do_scale(ctx, b, in_format, "C", dir);
1056
1057 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_MMX);
1058 do_scale(ctx, b, in_format, "MMX", dir);
1059
1060 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_MMXEXT);
1061 do_scale(ctx, b, in_format, "MMXEXT", dir);
1062
1063 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_SSE);
1064 do_scale(ctx, b, in_format, "SSE", dir);
1065
1066 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_SSE2);
1067 do_scale(ctx, b, in_format, "SSE2", dir);
1068
1069 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_SSE3);
1070 do_scale(ctx, b, in_format, "SSE3", dir);
1071
1072 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_C_HQ);
1073 do_scale(ctx, b, in_format, "HQ", dir);
1074 }
1075 /* X+Y */
1076
1077 if(!opt_scaledir || (opt_scaledir == (SCALE_X|SCALE_Y)))
1078 {
1079 // fprintf(stderr, "%d\n", opt_scaledir);
1080 dir = "x+y";
1081 gavl_video_format_copy(&ctx->in_format, &ctx->out_format);
1082
1083 ctx->in_format.image_width = 512;
1084 ctx->in_format.frame_width = 512;
1085 ctx->in_format.image_height = 512;
1086 ctx->in_format.frame_height = 512;
1087
1088 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_C);
1089 do_scale(ctx, b, in_format, "C", dir);
1090
1091 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_MMX);
1092 do_scale(ctx, b, in_format, "MMX", dir);
1093
1094 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_MMXEXT);
1095 do_scale(ctx, b, in_format, "MMXEXT", dir);
1096
1097 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_SSE);
1098 do_scale(ctx, b, in_format, "SSE", dir);
1099
1100 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_SSE2);
1101 do_scale(ctx, b, in_format, "SSE2", dir);
1102
1103 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_SSE3);
1104 do_scale(ctx, b, in_format, "SSE3", dir);
1105
1106 gavl_video_options_set_accel_flags(ctx->opt, GAVL_ACCEL_C_HQ);
1107 do_scale(ctx, b, in_format, "HQ", dir);
1108 }
1109 }
1110 if(do_html)
1111 printf("</table>\n");
1112
1113 }
1114
benchmark_scale()1115 static void benchmark_scale()
1116 {
1117 video_convert_context_t ctx;
1118 gavl_benchmark_t b;
1119
1120 memset(&ctx, 0, sizeof(ctx));
1121 memset(&b, 0, sizeof(b));
1122
1123 b.init = video_convert_init;
1124 b.func = video_convert_func;
1125 b.data = &ctx;
1126
1127 video_convert_context_create(&ctx);
1128
1129 /* Disable autoselection */
1130 gavl_video_options_set_quality(ctx.opt, 0);
1131
1132 do_scale_direction(&ctx, &b);
1133
1134 video_convert_context_destroy(&ctx);
1135 }
1136
1137 static const struct
1138 {
1139 const char * name;
1140 gavl_deinterlace_mode_t mode;
1141 }
1142 deinterlace_modes[] =
1143 {
1144 { "Scanline doubler", GAVL_DEINTERLACE_COPY },
1145 { "Upscale", GAVL_DEINTERLACE_SCALE },
1146 { "Blend", GAVL_DEINTERLACE_BLEND },
1147 };
1148
benchmark_deinterlace()1149 static void benchmark_deinterlace()
1150 {
1151 video_convert_context_t ctx;
1152 gavl_benchmark_t b;
1153 int num_pixelformats;
1154 int num_modes;
1155 int num_scale_modes;
1156 int i, j;
1157 memset(&ctx, 0, sizeof(ctx));
1158 memset(&b, 0, sizeof(b));
1159
1160 b.init = video_convert_init;
1161 b.func = video_convert_func;
1162 b.data = &ctx;
1163
1164 ctx.in_format.image_width = 720;
1165 ctx.in_format.image_height = 576;
1166 ctx.in_format.frame_width = 720;
1167 ctx.in_format.frame_height = 576;
1168 ctx.in_format.pixel_width = 1;
1169 ctx.in_format.pixel_height = 1;
1170 ctx.in_format.interlace_mode = GAVL_INTERLACE_TOP_FIRST;
1171
1172 printf("Size: %d x %d\n",
1173 ctx.in_format.image_width,
1174 ctx.in_format.image_height);
1175
1176 if(do_html)
1177 {
1178 printf("<p><table border=\"1\" width=\"100%%\"><tr><td>Method</td><td>Flavour</td><td>Scale method</td>");
1179 gavl_benchmark_print_header(&b);
1180 printf("</tr>\n");
1181 }
1182 else
1183 {
1184 printf("Method Flavour Scale method ");
1185 gavl_benchmark_print_header(&b);
1186 printf("\n");
1187 }
1188
1189 gavl_video_format_copy(&ctx.out_format, &ctx.in_format);
1190 ctx.out_format.interlace_mode = GAVL_INTERLACE_NONE;
1191
1192 video_convert_context_create(&ctx);
1193
1194 /* Disable autoselection */
1195 gavl_video_options_set_quality(ctx.opt, 0);
1196
1197 num_pixelformats = gavl_num_pixelformats();
1198 num_modes = sizeof(deinterlace_modes)/sizeof(deinterlace_modes[0]);
1199 num_scale_modes = sizeof(scale_modes)/sizeof(scale_modes[0]);
1200
1201 for(i = 0; i < num_pixelformats; i++)
1202 {
1203 ctx.in_format.pixelformat = gavl_get_pixelformat(i);
1204 ctx.out_format.pixelformat = ctx.in_format.pixelformat;
1205
1206 if(do_html)
1207 printf("<tr><td colspan=\"7\"><b>%s<b></td></tr>\n",
1208 gavl_pixelformat_to_string(ctx.in_format.pixelformat));
1209 else
1210 printf("%s\n",
1211 gavl_pixelformat_to_string(ctx.in_format.pixelformat));
1212
1213 for(j = 0; j < num_modes; j++)
1214 {
1215 if(deinterlace_modes[j].mode == GAVL_DEINTERLACE_SCALE)
1216 continue;
1217
1218 gavl_video_options_set_deinterlace_mode(ctx.opt, deinterlace_modes[j].mode);
1219
1220 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_C);
1221
1222 if(video_convert_context_init(&ctx))
1223 {
1224 if(do_html)
1225 printf("<tr><td>%s</td><td>C</td><td></td>",
1226 deinterlace_modes[j].name);
1227 else
1228 printf("%-16s C - ",
1229 deinterlace_modes[j].name);
1230
1231 gavl_benchmark_run(&b);
1232 gavl_benchmark_print_results(&b);
1233 if(do_html)
1234 printf("</tr>");
1235 printf("\n");
1236 }
1237 fflush(stdout);
1238 video_convert_context_cleanup(&ctx);
1239
1240 if(deinterlace_modes[j].mode == GAVL_DEINTERLACE_COPY)
1241 continue;
1242
1243 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_MMX);
1244
1245 if(video_convert_context_init(&ctx))
1246 {
1247 if(do_html)
1248 printf("<tr><td>%s</td><td>MMX</td><td></td>",
1249 deinterlace_modes[j].name);
1250 else
1251 printf("%-16s MMX - ",
1252 deinterlace_modes[j].name);
1253
1254 gavl_benchmark_run(&b);
1255 gavl_benchmark_print_results(&b);
1256 if(do_html)
1257 printf("</tr>");
1258 printf("\n");
1259 }
1260 fflush(stdout);
1261 video_convert_context_cleanup(&ctx);
1262
1263
1264 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_MMXEXT);
1265
1266 if(video_convert_context_init(&ctx))
1267 {
1268 if(do_html)
1269 printf("<tr><td>%s</td><td>MMXEXT</td><td></td>",
1270 deinterlace_modes[j].name);
1271 else
1272 printf("%-16s MMXEXT - ",
1273 deinterlace_modes[j].name);
1274
1275 gavl_benchmark_run(&b);
1276 gavl_benchmark_print_results(&b);
1277 if(do_html)
1278 printf("</tr>");
1279 printf("\n");
1280 }
1281 fflush(stdout);
1282 video_convert_context_cleanup(&ctx);
1283 }
1284
1285 gavl_video_options_set_deinterlace_mode(ctx.opt, GAVL_DEINTERLACE_SCALE);
1286 for(j = 1; j < num_scale_modes; j++)
1287 {
1288 gavl_video_options_set_scale_mode(ctx.opt, scale_modes[j].mode);
1289
1290 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_C);
1291
1292 if(video_convert_context_init(&ctx))
1293 {
1294 if(do_html)
1295 printf("<tr><td>Upscale</td><td>C</td><td>%s</td>",
1296 scale_modes[j].name);
1297 else
1298 printf("Upscale C %-24s ", scale_modes[j].name);
1299
1300 gavl_benchmark_run(&b);
1301 gavl_benchmark_print_results(&b);
1302 if(do_html)
1303 printf("</tr>");
1304 printf("\n");
1305 }
1306 fflush(stdout);
1307 video_convert_context_cleanup(&ctx);
1308
1309 if(deinterlace_modes[j].mode == GAVL_DEINTERLACE_COPY)
1310 continue;
1311
1312 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_MMX);
1313
1314 if(video_convert_context_init(&ctx))
1315 {
1316 if(do_html)
1317 printf("<tr><td>Upscale</td><td>MMX</td><td>%s</td>",
1318 scale_modes[j].name);
1319 else
1320 printf("Upscale MMX %-24s ", scale_modes[j].name);
1321
1322
1323 gavl_benchmark_run(&b);
1324 gavl_benchmark_print_results(&b);
1325 if(do_html)
1326 printf("</tr>");
1327 printf("\n");
1328 }
1329 fflush(stdout);
1330 video_convert_context_cleanup(&ctx);
1331 }
1332 }
1333 if(do_html)
1334 printf("</table>\n");
1335
1336 video_convert_context_destroy(&ctx);
1337 }
1338
1339 /* Video DSP */
1340
1341 typedef struct
1342 {
1343 gavl_video_format_t format;
1344
1345 gavl_dsp_context_t * ctx;
1346
1347 gavl_video_frame_t * frames[3];
1348 int num_frames;
1349
1350 } video_dsp_context_t;
1351
video_dsp_context_create(video_dsp_context_t * ctx,int num_frames)1352 static void video_dsp_context_create(video_dsp_context_t * ctx, int num_frames)
1353 {
1354 ctx->ctx = gavl_dsp_context_create();
1355 ctx->num_frames = num_frames;
1356 }
1357
video_dsp_context_init(video_dsp_context_t * ctx)1358 static void video_dsp_context_init(video_dsp_context_t * ctx)
1359 {
1360 int i;
1361
1362 for(i = 0; i < ctx->num_frames; i++)
1363 ctx->frames[i] = gavl_video_frame_create(&ctx->format);
1364 return;
1365 }
1366
video_dsp_context_cleanup(video_dsp_context_t * ctx)1367 static void video_dsp_context_cleanup(video_dsp_context_t * ctx)
1368 {
1369 int i;
1370 for(i = 0; i < ctx->num_frames; i++)
1371 gavl_video_frame_destroy(ctx->frames[i]);
1372 }
1373
video_dsp_context_destroy(video_dsp_context_t * ctx)1374 static void video_dsp_context_destroy(video_dsp_context_t * ctx)
1375 {
1376 gavl_dsp_context_destroy(ctx->ctx);
1377 }
1378
video_dsp_init(void * data)1379 static void video_dsp_init(void * data)
1380 {
1381 int i;
1382 video_dsp_context_t * ctx = data;
1383 /* Fill frame with random numbers */
1384 for(i = 0; i < ctx->num_frames; i++)
1385 {
1386 init_video_frame(&ctx->format, ctx->frames[0]);
1387 }
1388 }
1389
interpolate_func(void * data)1390 static void interpolate_func(void * data)
1391 {
1392 video_dsp_context_t * ctx = data;
1393
1394 gavl_dsp_interpolate_video_frame(ctx->ctx,
1395 &ctx->format,
1396 ctx->frames[0],
1397 ctx->frames[1],
1398 ctx->frames[2],
1399 0.5);
1400 }
1401
1402 /* Video interpolation */
1403
benchmark_dsp_interpolate()1404 static void benchmark_dsp_interpolate()
1405 {
1406 video_dsp_context_t ctx;
1407 gavl_benchmark_t b;
1408 int num_pixelformats;
1409 int i;
1410 memset(&ctx, 0, sizeof(ctx));
1411 memset(&b, 0, sizeof(b));
1412
1413 b.init = video_dsp_init;
1414 b.func = interpolate_func;
1415 b.data = &ctx;
1416
1417 ctx.format.image_width = 720;
1418 ctx.format.image_height = 576;
1419 ctx.format.frame_width = 720;
1420 ctx.format.frame_height = 576;
1421 ctx.format.pixel_width = 1;
1422 ctx.format.pixel_height = 1;
1423
1424 printf("Size: %d x %d\n",
1425 ctx.format.image_width,
1426 ctx.format.image_height);
1427
1428 if(do_html)
1429 {
1430 printf("<p><table border=\"1\" width=\"100%%\"><tr><td>Format</td><td>Flavour</td>");
1431 gavl_benchmark_print_header(&b);
1432 printf("</tr>\n");
1433 }
1434 else
1435 {
1436 printf("Format Flavour ");
1437 gavl_benchmark_print_header(&b);
1438 printf("\n");
1439 }
1440
1441 video_dsp_context_create(&ctx, 3);
1442
1443 /* Disable autoselection */
1444 gavl_dsp_context_set_quality(ctx.ctx, 0);
1445
1446 num_pixelformats = gavl_num_pixelformats();
1447
1448 for(i = 0; i < num_pixelformats; i++)
1449 {
1450 ctx.format.pixelformat = gavl_get_pixelformat(i);
1451
1452 /* C */
1453
1454 gavl_dsp_context_set_accel_flags(ctx.ctx, GAVL_ACCEL_C);
1455
1456 video_dsp_context_init(&ctx);
1457
1458 if(gavl_dsp_interpolate_video_frame(ctx.ctx,
1459 &ctx.format,
1460 ctx.frames[0],
1461 ctx.frames[1],
1462 ctx.frames[2],
1463 0.5))
1464 {
1465 if(do_html)
1466 printf("<tr><td>%s</td><td>C</td>",
1467 gavl_pixelformat_to_string(ctx.format.pixelformat));
1468 else
1469 printf("%-23s C ",
1470 gavl_pixelformat_to_string(ctx.format.pixelformat));
1471
1472 gavl_benchmark_run(&b);
1473 gavl_benchmark_print_results(&b);
1474 if(do_html)
1475 printf("</tr>");
1476 printf("\n");
1477 fflush(stdout);
1478 }
1479 video_dsp_context_cleanup(&ctx);
1480
1481 /* MMX */
1482
1483 gavl_dsp_context_set_accel_flags(ctx.ctx, GAVL_ACCEL_MMX);
1484
1485 video_dsp_context_init(&ctx);
1486
1487 if(gavl_dsp_interpolate_video_frame(ctx.ctx,
1488 &ctx.format,
1489 ctx.frames[0],
1490 ctx.frames[1],
1491 ctx.frames[2],
1492 0.5))
1493 {
1494 if(do_html)
1495 printf("<tr><td>%s</td><td>MMX</td>",
1496 gavl_pixelformat_to_string(ctx.format.pixelformat));
1497 else
1498 printf("%-23s MMX ",
1499 gavl_pixelformat_to_string(ctx.format.pixelformat));
1500
1501 gavl_benchmark_run(&b);
1502 gavl_benchmark_print_results(&b);
1503 if(do_html)
1504 printf("</tr>");
1505 printf("\n");
1506 fflush(stdout);
1507 }
1508 video_dsp_context_cleanup(&ctx);
1509
1510 }
1511
1512 video_dsp_context_destroy(&ctx);
1513 if(do_html)
1514 printf("</table>\n");
1515
1516 }
1517
1518 /* Image transformation */
1519
1520 static const struct
1521 {
1522 gavl_scale_mode_t mode;
1523 const char * name;
1524 }
1525 transform_modes[] =
1526 {
1527 { GAVL_SCALE_NEAREST, "Nearest" },
1528 { GAVL_SCALE_BILINEAR, "Linear"},
1529 { GAVL_SCALE_QUADRATIC, "Quadratic" },
1530 { GAVL_SCALE_CUBIC_BSPLINE, "Cubic B-Spline" },
1531 };
1532
1533 static const gavl_pixelformat_t transform_pixelformats[] =
1534 {
1535 GAVL_GRAY_8,
1536 GAVL_GRAY_16,
1537 GAVL_GRAY_FLOAT,
1538 GAVL_GRAYA_16,
1539 GAVL_GRAYA_32,
1540 GAVL_GRAYA_FLOAT,
1541 GAVL_RGB_15,
1542 GAVL_RGB_16,
1543 GAVL_RGB_24,
1544 GAVL_RGB_32,
1545 GAVL_RGBA_32,
1546 GAVL_RGB_48,
1547 GAVL_RGBA_64,
1548 GAVL_RGB_FLOAT,
1549 GAVL_RGBA_FLOAT,
1550 GAVL_YUY2,
1551 GAVL_UYVY,
1552 GAVL_YUV_420_P,
1553 GAVL_YUV_422_P,
1554 GAVL_YUV_444_P,
1555 GAVL_YUV_411_P,
1556 GAVL_YUV_410_P,
1557 GAVL_YUV_444_P_16,
1558 GAVL_YUV_422_P_16,
1559 GAVL_PIXELFORMAT_NONE,
1560 };
1561
1562 typedef struct
1563 {
1564 gavl_video_format_t format;
1565
1566 gavl_image_transform_t * transform;
1567 gavl_video_options_t * opt;
1568
1569 gavl_video_frame_t * in_frame;
1570 gavl_video_frame_t * out_frame;
1571 } image_transform_context_t;
1572
image_transform_context_create(image_transform_context_t * ctx)1573 static void image_transform_context_create(image_transform_context_t * ctx)
1574 {
1575 ctx->transform = gavl_image_transform_create();
1576 ctx->opt = gavl_image_transform_get_options(ctx->transform);
1577 }
1578
transform_func(void * priv,double xdst,double ydst,double * xsrc,double * ysrc)1579 static void transform_func(void *priv, double xdst,
1580 double ydst, double *xsrc, double *ysrc)
1581 {
1582 *xsrc = xdst + 0.5;
1583 *ysrc = ydst + 0.5;
1584 }
1585
image_transform_context_init(image_transform_context_t * ctx)1586 static int image_transform_context_init(image_transform_context_t * ctx)
1587 {
1588 ctx->in_frame = gavl_video_frame_create(&ctx->format);
1589 ctx->out_frame = gavl_video_frame_create(&ctx->format);
1590
1591 return gavl_image_transform_init(ctx->transform, &ctx->format, transform_func, NULL);
1592 }
1593
image_transform_context_cleanup(image_transform_context_t * ctx)1594 static void image_transform_context_cleanup(image_transform_context_t * ctx)
1595 {
1596 gavl_video_frame_destroy(ctx->in_frame);
1597 gavl_video_frame_destroy(ctx->out_frame);
1598 }
1599
image_transform_context_destroy(image_transform_context_t * ctx)1600 static void image_transform_context_destroy(image_transform_context_t * ctx)
1601 {
1602 gavl_image_transform_destroy(ctx->transform);
1603 }
1604
image_transform_init(void * data)1605 static void image_transform_init(void * data)
1606 {
1607 image_transform_context_t * ctx = data;
1608 /* Fill frame with random numbers */
1609 init_video_frame(&ctx->format, ctx->in_frame);
1610 }
1611
image_transform_func(void * data)1612 static void image_transform_func(void * data)
1613 {
1614 image_transform_context_t * ctx = data;
1615
1616 gavl_image_transform_transform(ctx->transform,
1617 ctx->in_frame,
1618 ctx->out_frame);
1619 }
1620
1621
benchmark_image_transform()1622 static void benchmark_image_transform()
1623 {
1624 image_transform_context_t ctx;
1625 gavl_benchmark_t b;
1626 int num_pixelformats;
1627 int i, j;
1628 memset(&ctx, 0, sizeof(ctx));
1629 memset(&b, 0, sizeof(b));
1630
1631 b.init = image_transform_init;
1632 b.func = image_transform_func;
1633 b.data = &ctx;
1634
1635 ctx.format.image_width = 720;
1636 ctx.format.image_height = 576;
1637 ctx.format.frame_width = 720;
1638 ctx.format.frame_height = 576;
1639 ctx.format.pixel_width = 1;
1640 ctx.format.pixel_height = 1;
1641
1642 printf("Size: %d x %d\n",
1643 ctx.format.image_width,
1644 ctx.format.image_height);
1645
1646 if(do_html)
1647 {
1648 printf("<p><table border=\"1\" width=\"100%%\"><tr><td>Format</td><td>Flavour</td>");
1649 gavl_benchmark_print_header(&b);
1650 printf("</tr>\n");
1651 }
1652 else
1653 {
1654 printf("Format Mode Flavour ");
1655 gavl_benchmark_print_header(&b);
1656 printf("\n");
1657 }
1658
1659 image_transform_context_create(&ctx);
1660
1661 /* Disable autoselection */
1662 gavl_video_options_set_quality(ctx.opt, 0);
1663
1664 num_pixelformats = gavl_num_pixelformats();
1665
1666 for(j = 0; j < sizeof(transform_modes)/sizeof(transform_modes[0]); j++)
1667 {
1668 gavl_video_options_set_scale_mode(ctx.opt, transform_modes[j].mode);
1669
1670 i = 0;
1671
1672 while(transform_pixelformats[i] != GAVL_PIXELFORMAT_NONE)
1673 {
1674 ctx.format.pixelformat = transform_pixelformats[i];
1675
1676 /* C */
1677
1678 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_C);
1679
1680 image_transform_context_init(&ctx);
1681
1682 if(do_html)
1683 printf("<tr><td>%s</td><td>%s</td><td>C</td>",
1684 gavl_pixelformat_to_string(ctx.format.pixelformat), transform_modes[j].name);
1685 else
1686 printf("%-23s %-14s C ",
1687 gavl_pixelformat_to_string(ctx.format.pixelformat), transform_modes[j].name);
1688
1689 gavl_benchmark_run(&b);
1690 gavl_benchmark_print_results(&b);
1691 if(do_html)
1692 printf("</tr>");
1693 printf("\n");
1694 fflush(stdout);
1695 image_transform_context_cleanup(&ctx);
1696
1697 /* MMX */
1698 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_MMX);
1699
1700 if(image_transform_context_init(&ctx))
1701 {
1702 if(do_html)
1703 printf("<tr><td>%s</td><td>%s</td><td>MMX</td>",
1704 gavl_pixelformat_to_string(ctx.format.pixelformat), transform_modes[j].name);
1705 else
1706 printf("%-23s %-14s MMX ",
1707 gavl_pixelformat_to_string(ctx.format.pixelformat), transform_modes[j].name);
1708
1709 gavl_benchmark_run(&b);
1710 gavl_benchmark_print_results(&b);
1711 if(do_html)
1712 printf("</tr>");
1713 printf("\n");
1714 fflush(stdout);
1715 image_transform_context_cleanup(&ctx);
1716 }
1717
1718 /* MMXEXT */
1719 gavl_video_options_set_accel_flags(ctx.opt, GAVL_ACCEL_MMXEXT);
1720
1721 if(image_transform_context_init(&ctx))
1722 {
1723 if(do_html)
1724 printf("<tr><td>%s</td><td>%s</td><td>MMXEXT</td>",
1725 gavl_pixelformat_to_string(ctx.format.pixelformat), transform_modes[j].name);
1726 else
1727 printf("%-23s %-14s MMXEXT ",
1728 gavl_pixelformat_to_string(ctx.format.pixelformat), transform_modes[j].name);
1729
1730 gavl_benchmark_run(&b);
1731 gavl_benchmark_print_results(&b);
1732 if(do_html)
1733 printf("</tr>");
1734 printf("\n");
1735 fflush(stdout);
1736 image_transform_context_cleanup(&ctx);
1737 }
1738
1739 // else
1740 // fprintf(stderr, "No MMX version\n");
1741
1742 i++;
1743 }
1744 }
1745
1746 image_transform_context_destroy(&ctx);
1747 if(do_html)
1748 printf("</table>\n");
1749
1750 }
1751
1752
1753
1754 #define BENCHMARK_SAMPLEFORMAT (1<<0)
1755 #define BENCHMARK_MIX (1<<1)
1756 #define BENCHMARK_VOLUME (1<<2)
1757 #define BENCHMARK_PEAK_DETECT (1<<3)
1758 #define BENCHMARK_INTERLEAVE (1<<4)
1759 #define BENCHMARK_RESAMPLE (1<<5)
1760
1761 #define BENCHMARK_PIXELFORMAT (1<<6)
1762 #define BENCHMARK_SCALE (1<<7)
1763 #define BENCHMARK_DEINTERLACE (1<<8)
1764 #define BENCHMARK_INTERPOLATE (1<<9)
1765 #define BENCHMARK_SAD (1<<10)
1766 #define BENCHMARK_TRANSFORM (1<<11)
1767
1768 static const struct
1769 {
1770 const char * option;
1771 const char * help;
1772 int flag;
1773 }
1774 benchmark_flags[] =
1775 {
1776 { "-sfmt", "Sampleformat conversions", BENCHMARK_SAMPLEFORMAT },
1777 { "-mix", "Audio mixing", BENCHMARK_MIX },
1778 { "-rs", "Resample routines", BENCHMARK_RESAMPLE},
1779 // { "-vol", "Volume control", BENCHMARK_VOLUME},
1780 // { "-pd", "Peak detection", BENCHMARK_PEAK_DETECT},
1781 // { "-il", "Interleaving conversion", BENCHMARK_INTERLEAVE},
1782 { "-pfmt", "Pixelformat conversions", BENCHMARK_PIXELFORMAT },
1783 { "-scale", "Scale", BENCHMARK_SCALE},
1784 { "-deint", "Deinterlacing", BENCHMARK_DEINTERLACE},
1785 { "-ip", "Video frame interpolation", BENCHMARK_INTERPOLATE},
1786 { "-it", "Image transformation", BENCHMARK_TRANSFORM},
1787 // { "-sad", "SAD routines", BENCHMARK_SAD},
1788 };
1789
get_flag(char * opt,int * flag_ret)1790 static int get_flag(char * opt, int * flag_ret)
1791 {
1792 int i;
1793 for(i = 0; i < sizeof(benchmark_flags)/sizeof(benchmark_flags[0]); i++)
1794 {
1795 if(!strcmp(benchmark_flags[i].option, opt))
1796 {
1797 *flag_ret = benchmark_flags[i].flag;
1798 return 1;
1799 }
1800 }
1801 return 0;
1802 }
1803
print_header(const char * title)1804 static void print_header(const char * title)
1805 {
1806 if(do_html)
1807 printf("<h2>%s</h2>\n", title);
1808 else
1809 printf("\n%s\n\n", title);
1810 }
1811
print_help()1812 static void print_help()
1813 {
1814 int i;
1815 printf("Usage: benchmark [-scaledir <dir>] [-pfmt1 <pfmt>] [-pfmt2 <pfmt>] [function ...] [-html]\n");
1816 printf(" benchmark -help\n\n");
1817 printf(" benchmark -listpfmt\n\n");
1818 printf("-html\n Produce html output\n");
1819 printf("-help\n Print this help and exit\n\n");
1820 printf("-listpfmt\n List pixelformats and exit\n\n");
1821 printf("Function can be any combination of the following\n\n");
1822
1823 for(i = 0; i < sizeof(benchmark_flags)/sizeof(benchmark_flags[0]); i++)
1824 {
1825 printf("%s\n %s\n", benchmark_flags[i].option, benchmark_flags[i].help);
1826 }
1827 printf("-a\n Do all of the above\n");
1828 }
1829
list_pfmts()1830 static void list_pfmts()
1831 {
1832 int i, num;
1833 num = gavl_num_pixelformats();
1834
1835 for(i = 0; i < num; i++)
1836 {
1837 printf("%s\n", gavl_pixelformat_to_string(gavl_get_pixelformat(i)));
1838 }
1839 }
1840
main(int argc,char ** argv)1841 int main(int argc, char ** argv)
1842 {
1843 int i;
1844 int flags = 0;
1845 int flag;
1846
1847
1848 #ifdef HAVE_SCHED_SETAFFINITY
1849 /* Force ourselves into processor 0 */
1850 cpu_set_t cpuset;
1851
1852 CPU_ZERO(&cpuset);
1853 CPU_SET(0, &cpuset);
1854 if(!sched_setaffinity(0, sizeof(cpuset), &cpuset))
1855 fprintf(stderr, "Running on processor 0 exclusively\n");
1856 else
1857 fprintf(stderr, "sched_setaffinity failed: %s\n", strerror(errno));
1858 #endif
1859
1860 i = 1;
1861
1862 while(i < argc)
1863 {
1864 if(get_flag(argv[i], &flag))
1865 flags |= flag;
1866 else if(!strcmp(argv[i], "-a"))
1867 flags = ~0x0;
1868 else if(!strcmp(argv[i], "-html"))
1869 do_html = 1;
1870 else if(!strcmp(argv[i], "-pfmt1"))
1871 {
1872 opt_pfmt1 = gavl_string_to_pixelformat(argv[i+1]);
1873 i++;
1874 }
1875 else if(!strcmp(argv[i], "-scaledir"))
1876 {
1877 if(!strcmp(argv[i+1], "x"))
1878 opt_scaledir = SCALE_X;
1879 else if(!strcmp(argv[i+1], "y"))
1880 opt_scaledir = SCALE_Y;
1881 else if(!strcmp(argv[i+1], "xy"))
1882 opt_scaledir = SCALE_X | SCALE_Y;
1883 i++;
1884 }
1885 else if(!strcmp(argv[i], "-pfmt2"))
1886 {
1887 opt_pfmt2 = gavl_string_to_pixelformat(argv[i+1]);
1888 i++;
1889 }
1890 else if(!strcmp(argv[i], "-help"))
1891 {
1892 print_help();
1893 return 0;
1894 }
1895 else if(!strcmp(argv[i], "-listpfmt"))
1896 {
1897 list_pfmts();
1898 return 0;
1899 }
1900 i++;
1901 }
1902
1903 if(do_html)
1904 {
1905 printf("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n");
1906 printf("<html>\n");
1907 printf("<head>\n");
1908 printf("<title>gavl benchmarks</title>\n");
1909 printf("<link rel=\"stylesheet\" href=\"css/style.css\">\n");
1910 printf("</head>\n");
1911 printf("<body>\n");
1912 printf("<h1>gavl Benchmarks</h1>");
1913 printf("These benchmarks are generated with the benchmark tool in the src/ directory of gavl.<br>");
1914 printf("Number of init runs: %d, number of counted runs: %d<br>\n", INIT_RUNS, NUM_RUNS);
1915 printf("Times are %s<br>\n", gavl_benchmark_get_desc(gavl_accel_supported()));
1916 printf("<h2>/proc/cpuinfo</h2>\n");
1917 printf("<pre>\n");
1918 fflush(stdout);
1919 system("cat /proc/cpuinfo");
1920 printf("</pre>\n");
1921
1922 if(flags & BENCHMARK_SAMPLEFORMAT)
1923 printf("<a href=\"#sfmt\">Sampleformat conversions</a><br>\n");
1924
1925 if(flags & BENCHMARK_MIX)
1926 printf("<a href=\"#mix\">Mixing routines</a><br>\n");
1927 if(flags & BENCHMARK_RESAMPLE)
1928 printf("<a href=\"#rs\">Resampling routines</a><br>\n");
1929 if(flags & BENCHMARK_PIXELFORMAT)
1930 printf("<a href=\"#pfmt\">Pixelformat conversions</a><br>\n");
1931 if(flags & BENCHMARK_SCALE)
1932 printf("<a href=\"#scale\">Scaling routines</a><br>\n");
1933 if(flags & BENCHMARK_DEINTERLACE)
1934 printf("<a href=\"#deint\">Deinterlacing routines</a><br>\n");
1935 if(flags & BENCHMARK_INTERPOLATE)
1936 printf("<a href=\"#ip\">Video frame interpolation</a><br>\n");
1937 if(flags & BENCHMARK_TRANSFORM)
1938 printf("<a href=\"#it\">Video image transformation</a><br>\n");
1939 }
1940 else
1941 printf("Times are %s\n", gavl_benchmark_get_desc(gavl_accel_supported()));
1942
1943
1944 if(flags & BENCHMARK_SAMPLEFORMAT)
1945 {
1946 if(do_html)
1947 {
1948 printf("<a name=\"sfmt\"></a>");
1949 }
1950 print_header("Sampleformat conversions");
1951 benchmark_sampleformat();
1952 }
1953
1954 if(flags & BENCHMARK_MIX)
1955 {
1956 if(do_html)
1957 {
1958 printf("<a name=\"mix\"></a>");
1959 }
1960 print_header("Mixing routines");
1961 benchmark_mix();
1962 }
1963 if(flags & BENCHMARK_RESAMPLE)
1964 {
1965 if(do_html)
1966 {
1967 printf("<a name=\"rs\"></a>");
1968 }
1969 print_header("Resampling routines");
1970 benchmark_resample();
1971 }
1972 if(flags & BENCHMARK_PIXELFORMAT)
1973 {
1974 if(do_html)
1975 {
1976 printf("<a name=\"pfmt\"></a>");
1977 }
1978 print_header("Pixelformat conversions");
1979 benchmark_pixelformat();
1980 }
1981 if(flags & BENCHMARK_SCALE)
1982 {
1983 if(do_html)
1984 {
1985 printf("<a name=\"scale\"></a>");
1986 }
1987 print_header("Scaling routines");
1988 benchmark_scale();
1989 }
1990 if(flags & BENCHMARK_DEINTERLACE)
1991 {
1992 if(do_html)
1993 {
1994 printf("<a name=\"deint\"></a>");
1995 }
1996 print_header("Deinterlacing routines");
1997 benchmark_deinterlace();
1998 }
1999 if(flags & BENCHMARK_INTERPOLATE)
2000 {
2001 if(do_html)
2002 {
2003 printf("<a name=\"ip\"></a>");
2004 }
2005 print_header("Video frame interpolation");
2006 benchmark_dsp_interpolate();
2007 }
2008 if(flags & BENCHMARK_TRANSFORM)
2009 {
2010 if(do_html)
2011 {
2012 printf("<a name=\"it\"></a>");
2013 }
2014 print_header("Video image transformation");
2015 benchmark_image_transform();
2016 }
2017
2018 if(do_html)
2019 {
2020 printf("</body>\n</html>\n");
2021 }
2022
2023 return 0;
2024 }
2025