~ubuntu-branches/ubuntu/lucid/gavl/lucid

« back to all changes in this revision

Viewing changes to gavl/scale_context.c

  • Committer: Bazaar Package Importer
  • Author(s): Romain Beauxis
  • Date: 2008-11-07 13:47:46 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20081107134746-s4s970fo1bcde9zw
Tags: 1.0.1-1
* Adopted package for debian, with the blessing of previous maintainer.
* Based new package on Christian Marillat's package for debian-multimedia.
* Removed support for ccache until I figure out how to make it work
  with cdbs.
* Changed library package name since ABI is not backward compatible, but
  upstream did not bump major soversion.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************
2
 
 
3
 
  scale_context.c
4
 
 
5
 
  Copyright (c) 2005 by Burkhard Plaum - plaum@ipf.uni-stuttgart.de
6
 
 
7
 
  http://gmerlin.sourceforge.net
8
 
 
9
 
  This program is distributed in the hope that it will be useful,
10
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
  GNU General Public License for more details.
13
 
 
14
 
  You should have received a copy of the GNU General Public License
15
 
  along with this program; if not, write to the Free Software
16
 
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
17
 
 
18
 
*****************************************************************/
19
 
 
 
2
 * gavl - a general purpose audio/video processing library
 
3
 *
 
4
 * Copyright (c) 2001 - 2008 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
 * *****************************************************************/
20
21
#include <math.h>
21
22
#include <stdlib.h>
22
23
#include <stdio.h>
23
24
#include <string.h>
24
25
 
 
26
#include <config.h>
25
27
#include <gavl/gavl.h>
26
28
#include <scale.h>
27
29
 
 
30
#include <accel.h>
 
31
 
 
32
#ifdef HAVE_MEMALIGN
 
33
/* some systems have memalign() but no declaration for it */
 
34
void * memalign (size_t align, size_t size);
 
35
#else
 
36
/* assume malloc alignment is sufficient */
 
37
#define memalign(align,size) malloc (size)
 
38
#endif
 
39
 
28
40
#define SCALE_X        0
29
41
#define SCALE_Y        1
30
42
#define SCALE_XY       2
31
43
#define SCALE_X_THEN_Y 3
32
44
#define SCALE_Y_THEN_X 4
33
45
 
34
 
#define ALIGNMENT_BYTES 8
 
46
#define ALIGNMENT_BYTES 16
35
47
#define ALIGN(a) a=((a+ALIGNMENT_BYTES-1)/ALIGNMENT_BYTES)*ALIGNMENT_BYTES
36
48
 
37
49
#define EPS 1e-4 /* Needed to determine if a double and an int are equal. */
39
51
static void copy_scanline_noadvance(gavl_video_scale_context_t * ctx)
40
52
  {
41
53
  //  fprintf(stderr, "copy_scanline_noadvance\n");
42
 
  memcpy(ctx->dst, ctx->src, ctx->bytes_per_line);
 
54
  gavl_memcpy(ctx->dst, ctx->src, ctx->bytes_per_line);
43
55
  ctx->src += ctx->src_stride;
44
56
  }
45
57
 
71
83
#endif
72
84
 
73
85
static gavl_video_scale_scanline_func get_func(gavl_scale_func_tab_t * tab,
74
 
                                        gavl_pixelformat_t pixelformat, int * bits)
 
86
                                               gavl_pixelformat_t pixelformat,
 
87
                                               int * bits)
75
88
  {
76
89
  switch(pixelformat)
77
90
    {
89
102
      break;
90
103
    case GAVL_RGB_24:
91
104
    case GAVL_BGR_24:
92
 
      *bits = tab->bits_uint8;
 
105
      *bits = tab->bits_uint8_noadvance;
93
106
      return tab->scale_uint8_x_3;
94
107
      break;
95
108
    case GAVL_RGB_32:
96
109
    case GAVL_BGR_32:
97
 
      *bits = tab->bits_uint8;
 
110
      *bits = tab->bits_uint8_noadvance;
98
111
      return tab->scale_uint8_x_3;
99
112
      break;
 
113
    case GAVL_GRAYA_16:
 
114
      *bits = tab->bits_uint8_noadvance;
 
115
      return tab->scale_uint8_x_2;
 
116
      break;
 
117
    case GAVL_GRAY_16:
 
118
      *bits = tab->bits_uint16;
 
119
      return tab->scale_uint16_x_1;
 
120
      break;
 
121
    case GAVL_GRAYA_32:
 
122
      *bits = tab->bits_uint16;
 
123
      return tab->scale_uint16_x_2;
 
124
      break;
100
125
    case GAVL_YUVA_32:
101
126
    case GAVL_RGBA_32:
102
 
      *bits = tab->bits_uint8;
 
127
      *bits = tab->bits_uint8_noadvance;
103
128
      return tab->scale_uint8_x_4;
104
129
      break;
105
130
    case GAVL_YUY2:
106
 
      *bits = tab->bits_uint8;
107
 
      return tab->scale_uint8_x_1;
 
131
      *bits = tab->bits_uint8_advance;
 
132
      return tab->scale_uint8_x_1_noadvance;
108
133
      break;
109
134
    case GAVL_UYVY:
110
 
      *bits = tab->bits_uint8;
111
 
      return tab->scale_uint8_x_1;
 
135
      *bits = tab->bits_uint8_advance;
 
136
      return tab->scale_uint8_x_1_advance;
112
137
      break;
113
138
    case GAVL_YUV_420_P:
114
139
    case GAVL_YUV_422_P:
115
140
    case GAVL_YUV_444_P:
116
141
    case GAVL_YUV_411_P:
117
142
    case GAVL_YUV_410_P:
118
 
      *bits = tab->bits_uint8;
119
 
      return tab->scale_uint8_x_1;
120
 
      break;
121
143
    case GAVL_YUVJ_420_P:
122
144
    case GAVL_YUVJ_422_P:
123
145
    case GAVL_YUVJ_444_P:
124
 
      *bits = tab->bits_uint8;
125
 
      return tab->scale_uint8_x_1;
 
146
    case GAVL_GRAY_8:
 
147
      *bits = tab->bits_uint8_noadvance;
 
148
      return tab->scale_uint8_x_1_noadvance;
126
149
      break;
127
150
    case GAVL_YUV_444_P_16:
128
151
    case GAVL_YUV_422_P_16:
134
157
      return tab->scale_uint16_x_3;
135
158
      break;
136
159
    case GAVL_RGBA_64:
 
160
    case GAVL_YUVA_64:
137
161
      *bits = tab->bits_uint16;
138
162
      return tab->scale_uint16_x_4;
139
163
      break;
 
164
    case GAVL_GRAY_FLOAT:
 
165
      *bits = 0;
 
166
      return tab->scale_float_x_1;
 
167
      break;
 
168
    case GAVL_GRAYA_FLOAT:
 
169
      *bits = 0;
 
170
      return tab->scale_float_x_2;
 
171
      break;
 
172
    case GAVL_YUV_FLOAT:
140
173
    case GAVL_RGB_FLOAT:
141
174
      *bits = 0;
142
175
      return tab->scale_float_x_3;
143
176
      break;
144
177
    case GAVL_RGBA_FLOAT:
 
178
    case GAVL_YUVA_FLOAT:
145
179
      *bits = 0;
146
180
      return tab->scale_float_x_4;
147
181
      break;
149
183
  return (gavl_video_scale_scanline_func)0;
150
184
  }
151
185
 
152
 
static void get_offsets(gavl_pixelformat_t pixelformat,
153
 
                        int plane,
154
 
                        int * advance, int * offset)
 
186
static void get_offset_internal(gavl_pixelformat_t pixelformat,
 
187
                                int plane,
 
188
                                int * advance, int * offset)
155
189
  {
156
190
  switch(pixelformat)
157
191
    {
162
196
      *advance = 2;
163
197
      *offset = 0;
164
198
      break;
 
199
    case GAVL_GRAY_8:
 
200
      *advance = 1;
 
201
      *offset = 0;
 
202
      break;
165
203
    case GAVL_RGB_16:
166
204
    case GAVL_BGR_16:
 
205
    case GAVL_GRAY_16:
 
206
    case GAVL_GRAYA_16:
167
207
      *advance = 2;
168
208
      *offset = 0;
169
209
      break;
174
214
      break;
175
215
    case GAVL_RGB_32:
176
216
    case GAVL_BGR_32:
177
 
      *advance = 4;
178
 
      *offset = 0;
179
 
      break;
180
217
    case GAVL_YUVA_32:
181
218
    case GAVL_RGBA_32:
 
219
    case GAVL_GRAYA_32:
182
220
      *advance = 4;
183
221
      *offset = 0;
184
222
      break;
242
280
      *offset = 0;
243
281
      break;
244
282
    case GAVL_RGBA_64:
 
283
    case GAVL_YUVA_64:
245
284
      *advance = 8;
246
285
      *offset = 0;
247
286
      break;
 
287
    case GAVL_GRAY_FLOAT:
 
288
      *advance = sizeof(float);
 
289
      *offset = 0;
 
290
      break;
 
291
    case GAVL_GRAYA_FLOAT:
 
292
      *advance = 2 * sizeof(float);
 
293
      *offset = 0;
 
294
      break;
248
295
    case GAVL_RGB_FLOAT:
 
296
    case GAVL_YUV_FLOAT:
249
297
      *advance = 3 * sizeof(float);
250
298
      *offset = 0;
251
299
      break;
252
300
    case GAVL_RGBA_FLOAT:
 
301
    case GAVL_YUVA_FLOAT:
253
302
      *advance = 4 * sizeof(float);
254
303
      *offset = 0;
255
304
      break;
257
306
  }
258
307
 
259
308
static void get_minmax(gavl_pixelformat_t pixelformat,
260
 
                       uint32_t * min, uint32_t * max)
 
309
                       int * min, int * max, float * min_f, float * max_f)
261
310
  {
 
311
  int i;
 
312
  for(i = 0; i < GAVL_MAX_PLANES; i++)
 
313
    {
 
314
    min[i] = 0;
 
315
    max[i] = 0;
 
316
    min_f[i] = 0.0;
 
317
    max_f[i] = 0.0;
 
318
    }
 
319
 
262
320
  switch(pixelformat)
263
321
    {
264
322
    case GAVL_PIXELFORMAT_NONE:
289
347
    case GAVL_YUVJ_422_P:
290
348
    case GAVL_YUVJ_444_P:
291
349
    case GAVL_RGBA_32:
 
350
    case GAVL_GRAY_8:
 
351
    case GAVL_GRAYA_16:
292
352
      min[0] = 0;
293
353
      min[1] = 0;
294
354
      min[2] = 0;
324
384
      break;
325
385
    case GAVL_YUV_444_P_16:
326
386
    case GAVL_YUV_422_P_16:
 
387
    case GAVL_YUVA_64:
327
388
      min[0] = 16<<8;
328
389
      min[1] = 16<<8;
329
390
      min[2] = 16<<8;
330
391
      max[0] = 235<<8;
331
392
      max[1] = 240<<8;
332
393
      max[2] = 240<<8;
 
394
      max[3] = (1<<16)-1;
333
395
      break;
 
396
    case GAVL_GRAY_16:
 
397
    case GAVL_GRAYA_32:
334
398
    case GAVL_RGB_48:
335
399
    case GAVL_RGBA_64:
336
400
      min[0] = 0;
344
408
      break;
345
409
    case GAVL_RGB_FLOAT:
346
410
    case GAVL_RGBA_FLOAT:
 
411
    case GAVL_GRAY_FLOAT:
 
412
    case GAVL_GRAYA_FLOAT:
 
413
      max_f[0] = 1.0;
 
414
      max_f[1] = 1.0;
 
415
      max_f[2] = 1.0;
 
416
      max_f[3] = 1.0;
 
417
      break;
 
418
    case GAVL_YUV_FLOAT:
 
419
    case GAVL_YUVA_FLOAT:
 
420
      max_f[0] =  1.0;
 
421
      min_f[1] = -0.5;
 
422
      max_f[1] =  0.5;
 
423
      min_f[2] = -0.5;
 
424
      max_f[2] =  0.5;
 
425
      max_f[3] =  1.0;
347
426
      break;
348
427
    }
349
428
  }
354
433
  if((pixelformat == GAVL_YUY2) || (pixelformat == GAVL_UYVY))
355
434
    ctx->buffer_stride = ctx->buffer_width;
356
435
  else if(gavl_pixelformat_is_planar(pixelformat))
357
 
    ctx->buffer_stride = ctx->buffer_width * gavl_pixelformat_bytes_per_component(pixelformat);
 
436
    ctx->buffer_stride = ctx->buffer_width *
 
437
      gavl_pixelformat_bytes_per_component(pixelformat);
358
438
  else
359
 
    ctx->buffer_stride = ctx->buffer_width * gavl_pixelformat_bytes_per_pixel(pixelformat);
 
439
    ctx->buffer_stride = ctx->buffer_width *
 
440
      gavl_pixelformat_bytes_per_pixel(pixelformat);
360
441
  
361
442
  ALIGN(ctx->buffer_stride);
362
443
 
364
445
 
365
446
  if(ctx->buffer_alloc < size)
366
447
    {
 
448
    if(ctx->buffer)
 
449
      free(ctx->buffer);
367
450
    ctx->buffer_alloc = size + 8192;
368
 
    ctx->buffer = realloc(ctx->buffer, ctx->buffer_alloc);
 
451
    ctx->buffer = memalign(ALIGNMENT_BYTES, ctx->buffer_alloc);
369
452
    }
370
 
  
371
453
  }
372
454
 
373
455
/*
477
559
                                  int src_field, int dst_field,
478
560
                                  int src_fields, int dst_fields)
479
561
  {
480
 
  int bits, i;
 
562
  int bits_h = 0, bits_v = 0;
481
563
  int sub_h_in = 1, sub_v_in = 1, sub_h_out = 1, sub_v_out = 1;
482
564
  int scale_x, scale_y;
483
565
  gavl_video_options_t tmp_opt, tmp_opt_y;
490
572
  float offset_x, offset_y;
491
573
  
492
574
  gavl_scale_funcs_t funcs;
493
 
  
 
575
 
 
576
  ctx->first_scanline = 0;
 
577
 
494
578
#if 0  
495
579
  fprintf(stderr, "scale_context_init: src_field: %d, dst_field: %d plane: %d\n",
496
580
          src_field, dst_field, plane);
587
671
          offset_x, offset_y, ctx->dst_rect.w / ctx->src_rect.w,
588
672
          ctx->dst_rect.h / ctx->src_rect.h);
589
673
#endif  
590
 
  //  ctx->src_rect.x += offset_x;
591
 
  //  ctx->src_rect.y += offset_y;
 
674
  offset_x += ctx->src_rect.x;
 
675
  offset_y += ctx->src_rect.y;
592
676
 
593
677
  ctx->func1 = NULL;
594
678
  ctx->func2 = NULL;
610
694
    ctx->dst_frame_plane = plane;
611
695
  else
612
696
    ctx->dst_frame_plane = 0;
613
 
  
614
 
  if(!ctx->num_directions)
615
 
    {
616
 
    ctx->bytes_per_line = gavl_pixelformat_is_planar(src_format->pixelformat) ?
617
 
      ctx->dst_rect.w * gavl_pixelformat_bytes_per_component(src_format->pixelformat) :
618
 
      ctx->dst_rect.w * gavl_pixelformat_bytes_per_pixel(src_format->pixelformat);
619
 
 
 
697
 
 
698
  /* Set bytes per line. We need this for copying */
 
699
  ctx->bytes_per_line = gavl_pixelformat_is_planar(src_format->pixelformat) ?
 
700
    ctx->dst_rect.w * gavl_pixelformat_bytes_per_component(src_format->pixelformat) :
 
701
    ctx->dst_rect.w * gavl_pixelformat_bytes_per_pixel(src_format->pixelformat);
 
702
  
 
703
  /* Set source and destination offsets */
 
704
  
 
705
  if(ctx->num_directions == 1)
 
706
    {
 
707
    get_offset_internal(src_format->pixelformat,
 
708
                plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
 
709
    get_offset_internal(dst_format->pixelformat,
 
710
                plane, &ctx->offset1.dst_advance, &ctx->offset1.dst_offset);
 
711
 
 
712
    /* We set this once here */
 
713
 
 
714
    ctx->offset = &(ctx->offset1);
 
715
    ctx->dst_size = ctx->dst_rect.w;
 
716
    }
 
717
  else if(ctx->num_directions == 2)
 
718
    {
 
719
    get_offset_internal(src_format->pixelformat,
 
720
                plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
 
721
    get_offset_internal(dst_format->pixelformat,
 
722
                plane, &ctx->offset2.dst_advance, &ctx->offset2.dst_offset);
 
723
 
 
724
    ctx->offset1.dst_offset = 0;
 
725
    ctx->offset1.dst_advance = ctx->offset1.src_advance;
 
726
 
 
727
    if((src_format->pixelformat == GAVL_YUY2) || 
 
728
       (src_format->pixelformat == GAVL_UYVY))
 
729
      {
 
730
      ctx->offset1.dst_advance = 1;
 
731
      }
 
732
    ctx->offset2.src_advance = ctx->offset1.dst_advance;
 
733
    ctx->offset2.src_offset  = ctx->offset1.dst_offset;
 
734
    }
 
735
  else if(!ctx->num_directions)
 
736
    {
620
737
    if((src_format->pixelformat == GAVL_YUY2) ||
621
738
       (src_format->pixelformat == GAVL_UYVY) ||
622
739
       (dst_format->pixelformat == GAVL_YUY2) ||
626
743
      ctx->func1 = copy_scanline_noadvance;
627
744
 
628
745
    /* Set source and destination offsets */
629
 
    get_offsets(src_format->pixelformat,
 
746
    get_offset_internal(src_format->pixelformat,
630
747
                plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
631
 
    get_offsets(dst_format->pixelformat,
 
748
    get_offset_internal(dst_format->pixelformat,
632
749
                plane, &ctx->offset1.dst_advance, &ctx->offset1.dst_offset);
633
750
 
634
751
    /* We set this once here */
637
754
    ctx->dst_size = ctx->dst_rect.w;
638
755
 
639
756
    ctx->num_directions = 1;
640
 
    return 0;
 
757
    return 1;
641
758
    }
642
759
 
643
 
  else if(scale_x && scale_y)
 
760
  if(scale_x && scale_y)
644
761
    {
645
 
    //    fprintf(stderr, "Initializing x table\n");
 
762
    // fprintf(stderr, "Initializing x table %f\n", ctx->src_rect.x + offset_x);
646
763
    gavl_video_options_copy(&tmp_opt, opt);
647
 
    gavl_video_scale_table_init(&(ctx->table_h), &tmp_opt, ctx->src_rect.x + offset_x,
 
764
    gavl_video_scale_table_init(&(ctx->table_h), &tmp_opt,
 
765
                                offset_x,
648
766
                                ctx->src_rect.w, ctx->dst_rect.w, src_width);
649
767
    //    fprintf(stderr, "Initializing x table done\n");
650
768
 
651
 
    //    fprintf(stderr, "Initializing y table\n");
 
769
    //    fprintf(stderr, "Initializing y table %f\n",
 
770
    //            ctx->src_rect.y + offset_y);
652
771
    gavl_video_options_copy(&tmp_opt_y, opt);
653
 
    gavl_video_scale_table_init(&(ctx->table_v), &tmp_opt_y, ctx->src_rect.y + offset_y,
 
772
    gavl_video_scale_table_init(&(ctx->table_v), &tmp_opt_y,
 
773
                                offset_y,
654
774
                                ctx->src_rect.h, ctx->dst_rect.h, src_height);
655
775
    
656
776
    //    fprintf(stderr, "Initializing y table done\n");
661
781
       (tmp_opt.scale_order == tmp_opt_y.scale_order))
662
782
      {
663
783
      memset(&funcs, 0, sizeof(funcs));
664
 
      gavl_init_scale_funcs(&funcs, &tmp_opt);
665
 
      ctx->func1 = get_func(&(funcs.funcs_xy), src_format->pixelformat, &bits);
666
 
      //      fprintf(stderr, "X AND Y\n");
 
784
      gavl_init_scale_funcs(&funcs, &tmp_opt, ctx->offset1.src_advance,
 
785
                            ctx->offset2.dst_advance);
 
786
      ctx->func1 = get_func(&(funcs.funcs_xy), src_format->pixelformat, &bits_h);
 
787
      //      fprintf(stderr, "X AND Y %d\n");
667
788
      }
668
789
    
669
790
    if(ctx->func1) /* Scaling routines for x-y are there, good */
670
791
      {
671
792
      ctx->num_directions = 1;
672
793
            
673
 
      gavl_video_scale_table_init_int(&(ctx->table_h), bits);
674
 
      gavl_video_scale_table_init_int(&(ctx->table_v), bits);
 
794
      gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
 
795
      /* Must be bits_h since we have only one function (and thus one accuracy) */
 
796
      gavl_video_scale_table_init_int(&(ctx->table_v), bits_h);
 
797
      ctx->offset = &(ctx->offset1);
 
798
      ctx->dst_size = ctx->dst_rect.w;
 
799
      
 
800
      /* Switch offsets back */
 
801
      ctx->offset1.dst_advance = ctx->offset2.dst_advance;
 
802
      ctx->offset1.dst_offset  = ctx->offset2.dst_offset;
675
803
      }
676
804
    else
677
805
      {
683
811
      /* Decide the scale order depending on whats computationally less expensive */
684
812
      /* We calculate the sizes (in pixels) of the temporary frame for both options and
685
813
         take the smaller one */
686
 
#if 0
 
814
#if 0 
687
815
      fprintf(stderr, "Src rect: ");
688
816
      gavl_rectangle_i_dump(&src_rect_i);
689
817
      fprintf(stderr, "\nDst rect: ");
699
827
        ctx->buffer_height = src_rect_i.h;
700
828
        
701
829
        gavl_video_scale_table_shift_indices(&(ctx->table_v), -src_rect_i.y);
702
 
        
703
 
        memset(&funcs, 0, sizeof(funcs));
704
 
        gavl_init_scale_funcs(&funcs, &tmp_opt);
705
 
        ctx->func1 = get_func(&funcs.funcs_x, src_format->pixelformat, &bits);
706
 
        gavl_video_scale_table_init_int(&(ctx->table_h), bits);
707
 
 
708
 
        memset(&funcs, 0, sizeof(funcs));
709
 
        gavl_init_scale_funcs(&funcs, &tmp_opt_y);
710
 
        ctx->func2 = get_func(&funcs.funcs_y, src_format->pixelformat, &bits);
711
 
        gavl_video_scale_table_init_int(&(ctx->table_v), bits);
712
 
        
 
830
        ctx->first_scanline = src_rect_i.y;
 
831
        
 
832
        memset(&funcs, 0, sizeof(funcs));
 
833
        gavl_init_scale_funcs(&funcs, &tmp_opt,
 
834
                              ctx->offset1.src_advance,
 
835
                              ctx->offset1.dst_advance);
 
836
        ctx->func1 = get_func(&funcs.funcs_x, src_format->pixelformat, &bits_h);
 
837
        
 
838
        gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
 
839
 
 
840
        memset(&funcs, 0, sizeof(funcs));
 
841
        gavl_init_scale_funcs(&funcs, &tmp_opt_y,
 
842
                              ctx->offset2.src_advance,
 
843
                              ctx->offset2.dst_advance);
 
844
        ctx->func2 = get_func(&funcs.funcs_y,
 
845
                              src_format->pixelformat, &bits_v);
 
846
 
 
847
        gavl_video_scale_table_init_int(&(ctx->table_v), bits_v);
713
848
        }
714
849
      else
715
850
        {
719
854
        ctx->buffer_width = src_rect_i.w;
720
855
        ctx->buffer_height = ctx->dst_rect.h;
721
856
        
 
857
        ctx->offset1.src_offset += src_rect_i.x * ctx->offset1.src_advance;
 
858
        
722
859
        gavl_video_scale_table_shift_indices(&(ctx->table_h), -src_rect_i.x);
723
860
 
724
861
        memset(&funcs, 0, sizeof(funcs));
725
 
        gavl_init_scale_funcs(&funcs, &tmp_opt_y);
726
 
        ctx->func1 = get_func(&funcs.funcs_y, src_format->pixelformat, &bits);
727
 
        gavl_video_scale_table_init_int(&(ctx->table_v), bits);
 
862
        gavl_init_scale_funcs(&funcs, &tmp_opt_y,
 
863
                              ctx->offset1.src_advance,
 
864
                              ctx->offset1.dst_advance);
 
865
        ctx->func1 = get_func(&funcs.funcs_y, src_format->pixelformat, &bits_v);
 
866
 
 
867
        gavl_video_scale_table_init_int(&(ctx->table_v), bits_v);
728
868
 
729
869
        memset(&funcs, 0, sizeof(funcs));
730
 
        gavl_init_scale_funcs(&funcs, &tmp_opt);
731
 
        ctx->func2 = get_func(&(funcs.funcs_x), src_format->pixelformat, &bits);
732
 
        gavl_video_scale_table_init_int(&(ctx->table_h), bits);
 
870
        gavl_init_scale_funcs(&funcs, &tmp_opt,
 
871
                              ctx->offset2.src_advance,
 
872
                              ctx->offset2.dst_advance);
 
873
        ctx->func2 = get_func(&(funcs.funcs_x),
 
874
                              src_format->pixelformat, &bits_h);
 
875
        
 
876
        gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
733
877
        }
734
878
      
735
879
      /* Allocate temporary buffer */
738
882
    }
739
883
  else if(scale_x)
740
884
    {
741
 
    //    fprintf(stderr, "Initializing x table\n");
742
885
    gavl_video_options_copy(&tmp_opt, opt);
743
 
    gavl_video_scale_table_init(&(ctx->table_h), &tmp_opt, ctx->src_rect.x + offset_x,
 
886
    gavl_video_scale_table_init(&(ctx->table_h), &tmp_opt,
 
887
                                offset_x,
744
888
                                ctx->src_rect.w, ctx->dst_rect.w, src_width);
745
889
    //    fprintf(stderr, "Initializing x table done\n");
746
890
 
747
891
    memset(&funcs, 0, sizeof(funcs));
748
 
    gavl_init_scale_funcs(&funcs, &tmp_opt);
749
 
    ctx->func1 = get_func(&(funcs.funcs_x), src_format->pixelformat, &bits);
750
 
    
751
 
    gavl_video_scale_table_init_int(&(ctx->table_h), bits);
 
892
    gavl_init_scale_funcs(&funcs, &tmp_opt,
 
893
                          ctx->offset1.src_advance,
 
894
                          ctx->offset1.dst_advance);
 
895
    ctx->func1 = get_func(&(funcs.funcs_x), src_format->pixelformat, &bits_h);
 
896
 
 
897
 
 
898
    gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
752
899
    }
753
900
  else if(scale_y)
754
901
    {
755
902
    //    fprintf(stderr, "Initializing y table\n");
756
903
    gavl_video_options_copy(&tmp_opt, opt);
757
 
    gavl_video_scale_table_init(&(ctx->table_v), &tmp_opt, ctx->src_rect.y + offset_y,
 
904
 
 
905
    gavl_video_scale_table_init(&(ctx->table_v), &tmp_opt, offset_y,
758
906
                                ctx->src_rect.h, ctx->dst_rect.h, src_height);
759
907
    //    fprintf(stderr, "Initializing y table done\n");
760
908
    memset(&funcs, 0, sizeof(funcs));
761
 
    gavl_init_scale_funcs(&funcs, &tmp_opt);
762
 
    ctx->func1 = get_func(&(funcs.funcs_y), src_format->pixelformat, &bits);
763
 
    
764
 
    gavl_video_scale_table_init_int(&(ctx->table_v), bits);
765
 
    }
766
 
  
767
 
  /* Set source and destination offsets */
768
 
 
769
 
  if(ctx->num_directions == 1)
770
 
    {
771
 
    get_offsets(src_format->pixelformat,
772
 
                plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
773
 
    get_offsets(dst_format->pixelformat,
774
 
                plane, &ctx->offset1.dst_advance, &ctx->offset1.dst_offset);
775
 
 
776
 
    /* We set this once here */
777
 
 
778
 
    ctx->offset = &(ctx->offset1);
779
 
    ctx->dst_size = ctx->dst_rect.w;
780
 
    }
781
 
  else if(ctx->num_directions == 2)
782
 
    {
783
 
    get_offsets(src_format->pixelformat,
784
 
                plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
785
 
 
786
 
    get_offsets(src_format->pixelformat,
787
 
                plane, &ctx->offset1.dst_advance, &ctx->offset1.dst_offset);
788
 
    ctx->offset1.dst_offset = 0;
789
 
 
790
 
    if((src_format->pixelformat == GAVL_YUY2) || 
791
 
       (src_format->pixelformat == GAVL_UYVY))
792
 
      {
793
 
      ctx->offset1.dst_advance = 1;
794
 
      }
795
 
    ctx->offset2.src_advance = ctx->offset1.dst_advance;
796
 
    ctx->offset2.src_offset  = ctx->offset1.dst_offset;
797
 
    
798
 
    get_offsets(dst_format->pixelformat,
799
 
                plane, &ctx->offset2.dst_advance, &ctx->offset2.dst_offset);
800
 
    }
801
 
  
 
909
    gavl_init_scale_funcs(&funcs, &tmp_opt,
 
910
                          ctx->offset1.src_advance,
 
911
                          ctx->offset1.dst_advance);
 
912
    ctx->func1 = get_func(&(funcs.funcs_y), src_format->pixelformat, &bits_v);
 
913
    
 
914
    gavl_video_scale_table_init_int(&(ctx->table_v), bits_v);
 
915
    }
 
916
 
 
917
  if(!ctx->func1 || ((ctx->num_directions == 2) && !ctx->func2))
 
918
    {
 
919
    //    fprintf(stderr, "Initializing scale context failed: %d %p %p\n",
 
920
    //            ctx->num_directions,
 
921
    //            ctx->func1, ctx->func2);
 
922
    return 0;
 
923
    }
802
924
#if 0  
803
925
  /* Dump final scale tables */
804
926
  fprintf(stderr, "Horizontal table:\n");
807
929
  gavl_video_scale_table_dump(&(ctx->table_v));
808
930
#endif
809
931
 
810
 
  if(scale_x)
811
 
    ctx->num_taps = ctx->table_h.factors_per_pixel;
812
 
  else
813
 
    ctx->num_taps = ctx->table_v.factors_per_pixel;
814
932
  
815
 
  get_minmax(src_format->pixelformat, ctx->min_values, ctx->max_values);
 
933
  get_minmax(src_format->pixelformat, ctx->min_values_h, ctx->max_values_h, ctx->min_values_f, ctx->max_values_f);
 
934
  get_minmax(src_format->pixelformat, ctx->min_values_v, ctx->max_values_v, ctx->min_values_f, ctx->max_values_f);
 
935
 
 
936
#if 0
 
937
  fprintf(stderr, "Min: %d %d %d, max: %d %d %d\n",
 
938
          ctx->min_values_h[0],
 
939
          ctx->min_values_h[1],
 
940
          ctx->min_values_h[2],
 
941
          ctx->max_values_h[0],
 
942
          ctx->max_values_h[1],
 
943
          ctx->max_values_h[2]);
 
944
#endif
 
945
#if 0
816
946
  for(i = 0; i < 4; i++)
817
947
    {
818
 
    ctx->min_values[i] <<= bits;
819
 
    ctx->max_values[i] <<= bits;
 
948
    ctx->min_values_h[i] <<= bits_h;
 
949
    ctx->max_values_h[i] <<= bits_h;
 
950
 
 
951
    ctx->min_values_v[i] <<= bits_v;
 
952
    ctx->max_values_v[i] <<= bits_v;
820
953
    }
821
 
 
 
954
#endif
 
955
#if 0
 
956
  fprintf(stderr, "Min: %d %d %d, max: %d %d %d\n",
 
957
          ctx->min_values_h[0],
 
958
          ctx->min_values_h[1],
 
959
          ctx->min_values_h[2],
 
960
          ctx->max_values_h[0],
 
961
          ctx->max_values_h[1],
 
962
          ctx->max_values_h[2]);
 
963
#endif
 
964
    
822
965
#if 0
823
966
  for(i = 0; i < 4; i++)
824
967
    {
829
972
  return 1;
830
973
  }
831
974
 
 
975
/* Factor must be a power of 2 */
 
976
 
 
977
static void downsample_coeffs(int factor,
 
978
                              float * coeffs, int num_coeffs,
 
979
                              float ** coeffs_ret, 
 
980
                              int * num_coeffs_ret)
 
981
  {
 
982
  int i;
 
983
  int fac = 1;
 
984
  int src_index;
 
985
  float * coeffs_1;
 
986
  float * coeffs_2;
 
987
  float * swp;
 
988
  int coeffs_total;
 
989
  int last_coeffs_total;
 
990
 
 
991
  *num_coeffs_ret = num_coeffs;
 
992
  coeffs_total = *num_coeffs_ret * 2 + 1;
 
993
 
 
994
  coeffs_1 = malloc(coeffs_total * sizeof(*coeffs_1));
 
995
  coeffs_2 = malloc(coeffs_total * sizeof(*coeffs_2));
 
996
 
 
997
  memcpy(coeffs_1, coeffs, coeffs_total * sizeof(*coeffs));
 
998
 
 
999
  //  fprintf(stderr, "downsample_coeffs: num_coeffs: %d, factor: %d\n",
 
1000
  //          num_coeffs, factor);
 
1001
  
 
1002
  while(fac < factor)
 
1003
    {
 
1004
    *num_coeffs_ret = (*num_coeffs_ret + 1)/2;
 
1005
    last_coeffs_total = coeffs_total;
 
1006
    coeffs_total = *num_coeffs_ret * 2 + 1;
 
1007
 
 
1008
    if(!(*num_coeffs_ret & 1))
 
1009
      {
 
1010
      coeffs_2[0] = 0.5 * coeffs_1[0] + coeffs_1[1];
 
1011
      src_index = 2;
 
1012
      for(i = 1; i < coeffs_total - 1; i++)
 
1013
        {
 
1014
        coeffs_2[i] = 0.5 * (coeffs_1[src_index-1] + 
 
1015
                             coeffs_1[src_index+1]) +
 
1016
                      coeffs_1[src_index];
 
1017
        src_index += 2;
 
1018
        }
 
1019
      coeffs_2[coeffs_total - 1] = 
 
1020
        0.5 * coeffs_1[last_coeffs_total - 1] + 
 
1021
              coeffs_1[last_coeffs_total - 2];
 
1022
      }
 
1023
    else
 
1024
      {
 
1025
      coeffs_2[0] =  0.5 * coeffs_1[0];
 
1026
      src_index = 1;
 
1027
      for(i = 1; i < coeffs_total - 1; i++)
 
1028
        {
 
1029
        coeffs_2[i] = 0.5 * (coeffs_1[src_index-1] + 
 
1030
                             coeffs_1[src_index+1]) +
 
1031
          coeffs_1[src_index];
 
1032
        src_index += 2;
 
1033
        }
 
1034
      coeffs_2[coeffs_total-1] = 
 
1035
        0.5 * coeffs_1[last_coeffs_total-1];
 
1036
      }
 
1037
    swp = coeffs_1;
 
1038
    coeffs_1 = coeffs_2;
 
1039
    coeffs_2 = swp;
 
1040
    fac *= 2;
 
1041
    }
 
1042
  *coeffs_ret = coeffs_1;
 
1043
  free(coeffs_2);
 
1044
  }
 
1045
 
 
1046
int 
 
1047
gavl_video_scale_context_init_convolve(gavl_video_scale_context_t* ctx,
 
1048
                                       gavl_video_options_t * opt,
 
1049
                                       int plane,
 
1050
                                       const gavl_video_format_t * format,
 
1051
                                       int num_fields,
 
1052
                                       int h_radius, float * h_coeffs,
 
1053
                                       int v_radius, float * v_coeffs)
 
1054
  {
 
1055
  int bits_h = 1, bits_v = 1, i;
 
1056
  int sub_h = 1, sub_v = 1;
 
1057
  int scale_x, scale_y;
 
1058
 
 
1059
  int fac_h = 1;
 
1060
  int fac_v = 1;
 
1061
 
 
1062
  gavl_video_options_t tmp_opt, tmp_opt_y;
 
1063
  gavl_rectangle_i_t src_rect_i;
 
1064
 
 
1065
  int h_radius_real;
 
1066
  float * h_coeffs_real, *h_c = (float*)0;
 
1067
  int v_radius_real;
 
1068
  float * v_coeffs_real, *v_c = (float*)0;
 
1069
 
 
1070
  int src_width, src_height; /* Needed for generating the scale table */
 
1071
 
 
1072
  gavl_scale_funcs_t funcs;
 
1073
  
 
1074
#if 0  
 
1075
  fprintf(stderr, "scale_context_init: src_field: %d, dst_field: %d plane: %d\n",
 
1076
          src_field, dst_field, plane);
 
1077
#endif  
 
1078
 
 
1079
  gavl_rectangle_f_set_all(&(ctx->src_rect), format);
 
1080
  gavl_rectangle_i_set_all(&(ctx->dst_rect), format);
 
1081
 
 
1082
  ctx->first_scanline = 0;
 
1083
  
 
1084
  ctx->plane = plane;
 
1085
  
 
1086
  if(plane)
 
1087
    {
 
1088
    /* Get chroma subsampling factors for source and destination */
 
1089
    gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
 
1090
    
 
1091
    ctx->src_rect.w /= sub_h;
 
1092
    ctx->src_rect.h /= sub_v;
 
1093
    ctx->dst_rect.w /= sub_h;
 
1094
    ctx->dst_rect.h /= sub_v;
 
1095
 
 
1096
    fac_h *= sub_h;
 
1097
    fac_v *= sub_v;
 
1098
    
 
1099
    src_width = format->image_width / sub_h;
 
1100
    src_height = format->image_height / sub_v;
 
1101
    }
 
1102
  else
 
1103
    {
 
1104
    src_width =  format->image_width;
 
1105
    src_height = format->image_height;
 
1106
    }
 
1107
  
 
1108
  if(num_fields == 2)
 
1109
    {
 
1110
    ctx->src_rect.h /= 2.0;
 
1111
    ctx->dst_rect.h /= 2;
 
1112
    src_height /= 2;
 
1113
    fac_v *= 2;
 
1114
    }
 
1115
  
 
1116
#if 0
 
1117
  fprintf(stderr, "gavl_video_scale_context_init\n");
 
1118
  gavl_rectangle_f_dump(&(ctx->src_rect));
 
1119
  fprintf(stderr, "\n");
 
1120
  gavl_rectangle_i_dump(&(ctx->dst_rect));
 
1121
  fprintf(stderr, "\n");
 
1122
#endif
 
1123
  
 
1124
  /* Calculate chroma offsets  */
 
1125
  if(plane && !(opt->conversion_flags & GAVL_CONVOLVE_CHROMA))
 
1126
    {
 
1127
    scale_x = 0;
 
1128
    scale_y = 0;
 
1129
    }
 
1130
  else
 
1131
    {
 
1132
    if(h_radius > 0)
 
1133
      scale_x = 1;
 
1134
    else
 
1135
      scale_x = 0;
 
1136
 
 
1137
    if(v_radius > 0)
 
1138
      scale_y = 1;
 
1139
    else
 
1140
      scale_y = 0;
 
1141
    }
 
1142
 
 
1143
  /* Downsample coefficients */
 
1144
 
 
1145
  h_radius_real = h_radius;
 
1146
  v_radius_real = v_radius;
 
1147
 
 
1148
  if(scale_x)
 
1149
    {
 
1150
    if(fac_h > 1)
 
1151
      {
 
1152
      downsample_coeffs(fac_h, h_coeffs, h_radius,
 
1153
                        &h_c, &h_radius_real);
 
1154
      h_coeffs_real = h_c;
 
1155
      }
 
1156
    else
 
1157
      h_coeffs_real = h_coeffs;
 
1158
    }
 
1159
  if(scale_y)
 
1160
    {
 
1161
    if(fac_v > 1)
 
1162
      {
 
1163
      downsample_coeffs(fac_v, v_coeffs, v_radius,
 
1164
                        &v_c, &v_radius_real);
 
1165
      v_coeffs_real = v_c;
 
1166
      }
 
1167
    else
 
1168
      v_coeffs_real = v_coeffs;
 
1169
    }
 
1170
 
 
1171
  ctx->func1 = NULL;
 
1172
  ctx->func2 = NULL;
 
1173
  
 
1174
  ctx->num_directions = 0;
 
1175
  if(scale_x)
 
1176
    ctx->num_directions++;
 
1177
  if(scale_y)
 
1178
    ctx->num_directions++;
 
1179
  
 
1180
  /* Set source and destination frame planes */
 
1181
  
 
1182
  if(gavl_pixelformat_is_planar(format->pixelformat))
 
1183
    {
 
1184
    ctx->src_frame_plane = plane;
 
1185
    ctx->dst_frame_plane = plane;
 
1186
    }
 
1187
  else
 
1188
    {
 
1189
    ctx->src_frame_plane = 0;
 
1190
    ctx->dst_frame_plane = 0;
 
1191
    }
 
1192
 
 
1193
  
 
1194
  ctx->bytes_per_line = 
 
1195
    gavl_pixelformat_is_planar(format->pixelformat) ?
 
1196
    ctx->dst_rect.w * gavl_pixelformat_bytes_per_component(format->pixelformat) :
 
1197
    ctx->dst_rect.w * gavl_pixelformat_bytes_per_pixel(format->pixelformat);
 
1198
 
 
1199
  
 
1200
  /* Set source and destination offsets */
 
1201
 
 
1202
  if(ctx->num_directions == 1)
 
1203
    {
 
1204
    get_offset_internal(format->pixelformat,
 
1205
                plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
 
1206
    get_offset_internal(format->pixelformat,
 
1207
                plane, &ctx->offset1.dst_advance, &ctx->offset1.dst_offset);
 
1208
 
 
1209
    /* We set this once here */
 
1210
 
 
1211
    ctx->offset = &(ctx->offset1);
 
1212
    ctx->dst_size = ctx->dst_rect.w;
 
1213
    }
 
1214
  else if(ctx->num_directions == 2)
 
1215
    {
 
1216
    get_offset_internal(format->pixelformat,
 
1217
                plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
 
1218
 
 
1219
    get_offset_internal(format->pixelformat,
 
1220
                plane, &ctx->offset2.dst_advance, &ctx->offset2.dst_offset);
 
1221
 
 
1222
    ctx->offset1.dst_offset = 0;
 
1223
    ctx->offset1.dst_advance = ctx->offset1.src_advance;
 
1224
 
 
1225
    if((format->pixelformat == GAVL_YUY2) || 
 
1226
       (format->pixelformat == GAVL_UYVY))
 
1227
      {
 
1228
      ctx->offset1.dst_advance = 1;
 
1229
      }
 
1230
    ctx->offset2.src_advance = ctx->offset1.dst_advance;
 
1231
    ctx->offset2.src_offset  = ctx->offset1.dst_offset;
 
1232
    
 
1233
    }
 
1234
  
 
1235
  /* Set functions */
 
1236
  
 
1237
  if(!ctx->num_directions)
 
1238
    {
 
1239
    if((format->pixelformat == GAVL_YUY2) ||
 
1240
       (format->pixelformat == GAVL_UYVY))
 
1241
      ctx->func1 = copy_scanline_advance;
 
1242
    else
 
1243
      ctx->func1 = copy_scanline_noadvance;
 
1244
    
 
1245
    /* Set source and destination offsets */
 
1246
    get_offset_internal(format->pixelformat,
 
1247
                plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
 
1248
    get_offset_internal(format->pixelformat,
 
1249
                plane, &ctx->offset1.dst_advance, &ctx->offset1.dst_offset);
 
1250
 
 
1251
    /* We set this once here */
 
1252
 
 
1253
    ctx->offset = &(ctx->offset1);
 
1254
    ctx->dst_size = ctx->dst_rect.w;
 
1255
 
 
1256
    ctx->num_directions = 1;
 
1257
    return 0;
 
1258
    }
 
1259
 
 
1260
  else if(scale_x && scale_y)
 
1261
    {
 
1262
    //    fprintf(stderr, "Initializing x table\n");
 
1263
    gavl_video_options_copy(&tmp_opt, opt);
 
1264
    tmp_opt.scale_mode = GAVL_SCALE_NONE;
 
1265
    gavl_video_scale_table_init_convolve(&(ctx->table_h),
 
1266
                                         &tmp_opt,
 
1267
                                         h_radius, h_coeffs,
 
1268
                                         src_width);
 
1269
    //    fprintf(stderr, "Initializing x table done\n");
 
1270
 
 
1271
    //    fprintf(stderr, "Initializing y table\n");
 
1272
    gavl_video_options_copy(&tmp_opt_y, opt);
 
1273
    tmp_opt_y.scale_mode = GAVL_SCALE_NONE;
 
1274
    gavl_video_scale_table_init_convolve(&(ctx->table_v),
 
1275
                                         &tmp_opt_y,
 
1276
                                         v_radius, v_coeffs,
 
1277
                                         src_height);
 
1278
   
 
1279
    //    fprintf(stderr, "Initializing y table done\n");
 
1280
    
 
1281
    /* Check if we can scale in x and y-directions at once */
 
1282
 
 
1283
    if((tmp_opt.scale_mode == tmp_opt_y.scale_mode) &&
 
1284
       (tmp_opt.scale_order == tmp_opt_y.scale_order))
 
1285
      {
 
1286
      memset(&funcs, 0, sizeof(funcs));
 
1287
      gavl_init_scale_funcs(&funcs, &tmp_opt,
 
1288
                          ctx->offset1.src_advance,
 
1289
                          ctx->offset2.dst_advance);
 
1290
      ctx->func1 = get_func(&(funcs.funcs_xy), format->pixelformat, &bits_h);
 
1291
      //      fprintf(stderr, "X AND Y\n");
 
1292
      }
 
1293
    
 
1294
    if(ctx->func1) /* Scaling routines for x-y are there, good */
 
1295
      {
 
1296
      ctx->num_directions = 1;
 
1297
            
 
1298
      gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
 
1299
      gavl_video_scale_table_init_int(&(ctx->table_v), bits_h);
 
1300
      }
 
1301
    else
 
1302
      {
 
1303
      gavl_video_scale_table_get_src_indices(&(ctx->table_h),
 
1304
                                             &src_rect_i.x,
 
1305
                                             &src_rect_i.w);
 
1306
      
 
1307
      gavl_video_scale_table_get_src_indices(&(ctx->table_v),
 
1308
                                             &src_rect_i.y,
 
1309
                                             &src_rect_i.h);
 
1310
      
 
1311
      //        fprintf(stderr, "X then Y\n");
 
1312
      /* X then Y */
 
1313
      
 
1314
      ctx->buffer_width  = ctx->dst_rect.w;
 
1315
      ctx->buffer_height = src_rect_i.h;
 
1316
        
 
1317
      gavl_video_scale_table_shift_indices(&(ctx->table_v),
 
1318
                                           -src_rect_i.y);
 
1319
      memset(&funcs, 0, sizeof(funcs));
 
1320
      gavl_init_scale_funcs(&funcs, &tmp_opt,
 
1321
                          ctx->offset1.src_advance,
 
1322
                          ctx->offset1.dst_advance);
 
1323
      ctx->func1 = get_func(&funcs.funcs_x, format->pixelformat, &bits_h);
 
1324
 
 
1325
      gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
 
1326
 
 
1327
      memset(&funcs, 0, sizeof(funcs));
 
1328
      gavl_init_scale_funcs(&funcs, &tmp_opt_y,
 
1329
                            ctx->offset2.src_advance,
 
1330
                            ctx->offset2.dst_advance);
 
1331
      ctx->func2 = get_func(&funcs.funcs_y, format->pixelformat, &bits_v);
 
1332
 
 
1333
 
 
1334
      gavl_video_scale_table_init_int(&(ctx->table_v), bits_v);
 
1335
     
 
1336
      /* Allocate temporary buffer */
 
1337
      alloc_temp(ctx, format->pixelformat);
 
1338
      }
 
1339
    }
 
1340
  else if(scale_x)
 
1341
    {
 
1342
    //    fprintf(stderr, "Initializing x table\n");
 
1343
    gavl_video_options_copy(&tmp_opt, opt);
 
1344
    tmp_opt.scale_mode = GAVL_SCALE_NONE;
 
1345
 
 
1346
    gavl_video_scale_table_init_convolve(&(ctx->table_h),
 
1347
                                         &tmp_opt,
 
1348
                                         h_radius, h_coeffs,
 
1349
                                         src_width);
 
1350
    //    fprintf(stderr, "Initializing x table done\n");
 
1351
    memset(&funcs, 0, sizeof(funcs));
 
1352
    gavl_init_scale_funcs(&funcs, &tmp_opt,
 
1353
                          ctx->offset1.src_advance,
 
1354
                          ctx->offset1.dst_advance);
 
1355
    ctx->func1 = get_func(&(funcs.funcs_x), format->pixelformat, &bits_h);
 
1356
    
 
1357
    gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
 
1358
    }
 
1359
  else if(scale_y)
 
1360
    {
 
1361
    //    fprintf(stderr, "Initializing y table\n");
 
1362
    gavl_video_options_copy(&tmp_opt, opt);
 
1363
    tmp_opt.scale_mode = GAVL_SCALE_NONE;
 
1364
    gavl_video_scale_table_init_convolve(&(ctx->table_v),
 
1365
                                         &tmp_opt,
 
1366
                                         v_radius, v_coeffs,
 
1367
                                         src_height);
 
1368
    
 
1369
    //    fprintf(stderr, "Initializing y table done\n");
 
1370
    memset(&funcs, 0, sizeof(funcs));
 
1371
    gavl_init_scale_funcs(&funcs, &tmp_opt,
 
1372
                          ctx->offset1.src_advance,
 
1373
                          ctx->offset1.dst_advance);
 
1374
    ctx->func1 = get_func(&(funcs.funcs_y), format->pixelformat, &bits_v);
 
1375
    
 
1376
    gavl_video_scale_table_init_int(&(ctx->table_v), bits_v);
 
1377
    }
 
1378
  
 
1379
#if 0
 
1380
  /* Dump final scale tables */
 
1381
  fprintf(stderr, "Horizontal table:\n");
 
1382
  gavl_video_scale_table_dump(&(ctx->table_h));
 
1383
  fprintf(stderr, "Vertical table:\n");
 
1384
  gavl_video_scale_table_dump(&(ctx->table_v));
 
1385
#endif
 
1386
 
 
1387
  
 
1388
  get_minmax(format->pixelformat, ctx->min_values_h, ctx->max_values_h, ctx->min_values_f, ctx->max_values_f);
 
1389
  get_minmax(format->pixelformat, ctx->min_values_v, ctx->max_values_v, ctx->min_values_f, ctx->max_values_f);
 
1390
  for(i = 0; i < 4; i++)
 
1391
    {
 
1392
    ctx->min_values_h[i] <<= bits_h;
 
1393
    ctx->max_values_h[i] <<= bits_h;
 
1394
    ctx->min_values_v[i] <<= bits_v;
 
1395
    ctx->max_values_v[i] <<= bits_v;
 
1396
    }
 
1397
 
 
1398
  if(h_c) free(h_c);
 
1399
  if(v_c) free(v_c);
 
1400
  
 
1401
  return 1;
 
1402
  }
 
1403
 
832
1404
void gavl_video_scale_context_cleanup(gavl_video_scale_context_t * ctx)
833
1405
  {
834
1406
  gavl_video_scale_table_cleanup(&(ctx->table_h));
835
1407
  gavl_video_scale_table_cleanup(&(ctx->table_v));
 
1408
  if(ctx->buffer)
 
1409
    free(ctx->buffer);
836
1410
  }
837
1411
 
838
1412
 
839
1413
void gavl_video_scale_context_scale(gavl_video_scale_context_t * ctx,
840
 
                                    gavl_video_frame_t * src, gavl_video_frame_t * dst)
 
1414
                                    const gavl_video_frame_t * src,
 
1415
                                    gavl_video_frame_t * dst)
841
1416
  {
842
1417
  uint8_t * dst_save;
843
 
  //  fprintf(stderr, "gavl_video_scale_context_scale %p %p %d %d\n", src, dst, ctx->num_directions, ctx->dst_rect.h);
 
1418
  //  fprintf(stderr, "gavl_video_scale_context_scale, plane %d\n",
 
1419
  //          ctx->dst_frame_plane);
844
1420
  switch(ctx->num_directions)
845
1421
    {
846
1422
    case 0:
863
1439
      break;
864
1440
    case 2:
865
1441
      /* First step */
866
 
      //      fprintf(stderr, "First direction...\n");
867
1442
      ctx->offset = &(ctx->offset1);
868
 
      //      dump_offset(ctx->offset);
869
 
      ctx->src = src->planes[ctx->src_frame_plane] + ctx->offset->src_offset;
 
1443
      
 
1444
      ctx->src = src->planes[ctx->src_frame_plane] +
 
1445
        ctx->offset->src_offset +
 
1446
        src->strides[ctx->src_frame_plane] * ctx->first_scanline;
 
1447
      
870
1448
      ctx->src_stride = src->strides[ctx->src_frame_plane];
871
1449
      ctx->dst_size = ctx->buffer_width;
872
1450
 
873
1451
      dst_save = ctx->buffer;
874
 
            
 
1452
#if 0
 
1453
      fprintf(stderr, "First direction\n");
 
1454
      dump_offset(ctx->offset);
 
1455
#endif
 
1456
      
875
1457
      for(ctx->scanline = 0; ctx->scanline < ctx->buffer_height; ctx->scanline++)
876
1458
        {
877
1459
        ctx->dst = dst_save;
881
1463
      //      fprintf(stderr, "done\n");
882
1464
 
883
1465
      /* Second step */
884
 
      //      fprintf(stderr, "Second direction...\n");
885
1466
      ctx->offset = &(ctx->offset2);
886
 
 
887
 
      //      dump_offset(ctx->offset);
888
 
 
 
1467
#if 0
 
1468
      fprintf(stderr, "Second direction\n");
 
1469
      dump_offset(ctx->offset);
 
1470
#endif
889
1471
      ctx->src = ctx->buffer;
890
1472
      ctx->src_stride = ctx->buffer_stride;
891
1473
      ctx->dst_size = ctx->dst_rect.w;
892
 
      dst_save = dst->planes[ctx->dst_frame_plane] + ctx->offset->dst_offset;
 
1474
      dst_save =
 
1475
        dst->planes[ctx->dst_frame_plane] + ctx->offset->dst_offset;
893
1476
      for(ctx->scanline = 0; ctx->scanline < ctx->dst_rect.h; ctx->scanline++)
894
1477
        {
895
1478
        //        fprintf(stderr, "i: %d\n", ctx->scanline);
900
1483
      //      fprintf(stderr, "done\n");
901
1484
      break;
902
1485
    }
 
1486
#ifdef HAVE_MMX
 
1487
  if(ctx->need_emms)
 
1488
    {
 
1489
    __asm__ __volatile__ ("emms");
 
1490
    ctx->need_emms = 0;
 
1491
    }
 
1492
#endif
903
1493
  }
904
1494