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