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,
744
888
ctx->src_rect.w, ctx->dst_rect.w, src_width);
745
889
// fprintf(stderr, "Initializing x table done\n");
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);
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);
898
gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
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,
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);
764
gavl_video_scale_table_init_int(&(ctx->table_v), bits);
767
/* Set source and destination offsets */
769
if(ctx->num_directions == 1)
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);
776
/* We set this once here */
778
ctx->offset = &(ctx->offset1);
779
ctx->dst_size = ctx->dst_rect.w;
781
else if(ctx->num_directions == 2)
783
get_offsets(src_format->pixelformat,
784
plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
786
get_offsets(src_format->pixelformat,
787
plane, &ctx->offset1.dst_advance, &ctx->offset1.dst_offset);
788
ctx->offset1.dst_offset = 0;
790
if((src_format->pixelformat == GAVL_YUY2) ||
791
(src_format->pixelformat == GAVL_UYVY))
793
ctx->offset1.dst_advance = 1;
795
ctx->offset2.src_advance = ctx->offset1.dst_advance;
796
ctx->offset2.src_offset = ctx->offset1.dst_offset;
798
get_offsets(dst_format->pixelformat,
799
plane, &ctx->offset2.dst_advance, &ctx->offset2.dst_offset);
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);
914
gavl_video_scale_table_init_int(&(ctx->table_v), bits_v);
917
if(!ctx->func1 || ((ctx->num_directions == 2) && !ctx->func2))
919
// fprintf(stderr, "Initializing scale context failed: %d %p %p\n",
920
// ctx->num_directions,
921
// ctx->func1, ctx->func2);
803
925
/* Dump final scale tables */
804
926
fprintf(stderr, "Horizontal table:\n");
975
/* Factor must be a power of 2 */
977
static void downsample_coeffs(int factor,
978
float * coeffs, int num_coeffs,
980
int * num_coeffs_ret)
989
int last_coeffs_total;
991
*num_coeffs_ret = num_coeffs;
992
coeffs_total = *num_coeffs_ret * 2 + 1;
994
coeffs_1 = malloc(coeffs_total * sizeof(*coeffs_1));
995
coeffs_2 = malloc(coeffs_total * sizeof(*coeffs_2));
997
memcpy(coeffs_1, coeffs, coeffs_total * sizeof(*coeffs));
999
// fprintf(stderr, "downsample_coeffs: num_coeffs: %d, factor: %d\n",
1000
// num_coeffs, factor);
1004
*num_coeffs_ret = (*num_coeffs_ret + 1)/2;
1005
last_coeffs_total = coeffs_total;
1006
coeffs_total = *num_coeffs_ret * 2 + 1;
1008
if(!(*num_coeffs_ret & 1))
1010
coeffs_2[0] = 0.5 * coeffs_1[0] + coeffs_1[1];
1012
for(i = 1; i < coeffs_total - 1; i++)
1014
coeffs_2[i] = 0.5 * (coeffs_1[src_index-1] +
1015
coeffs_1[src_index+1]) +
1016
coeffs_1[src_index];
1019
coeffs_2[coeffs_total - 1] =
1020
0.5 * coeffs_1[last_coeffs_total - 1] +
1021
coeffs_1[last_coeffs_total - 2];
1025
coeffs_2[0] = 0.5 * coeffs_1[0];
1027
for(i = 1; i < coeffs_total - 1; i++)
1029
coeffs_2[i] = 0.5 * (coeffs_1[src_index-1] +
1030
coeffs_1[src_index+1]) +
1031
coeffs_1[src_index];
1034
coeffs_2[coeffs_total-1] =
1035
0.5 * coeffs_1[last_coeffs_total-1];
1038
coeffs_1 = coeffs_2;
1042
*coeffs_ret = coeffs_1;
1047
gavl_video_scale_context_init_convolve(gavl_video_scale_context_t* ctx,
1048
gavl_video_options_t * opt,
1050
const gavl_video_format_t * format,
1052
int h_radius, float * h_coeffs,
1053
int v_radius, float * v_coeffs)
1055
int bits_h = 1, bits_v = 1, i;
1056
int sub_h = 1, sub_v = 1;
1057
int scale_x, scale_y;
1062
gavl_video_options_t tmp_opt, tmp_opt_y;
1063
gavl_rectangle_i_t src_rect_i;
1066
float * h_coeffs_real, *h_c = (float*)0;
1068
float * v_coeffs_real, *v_c = (float*)0;
1070
int src_width, src_height; /* Needed for generating the scale table */
1072
gavl_scale_funcs_t funcs;
1075
fprintf(stderr, "scale_context_init: src_field: %d, dst_field: %d plane: %d\n",
1076
src_field, dst_field, plane);
1079
gavl_rectangle_f_set_all(&(ctx->src_rect), format);
1080
gavl_rectangle_i_set_all(&(ctx->dst_rect), format);
1082
ctx->first_scanline = 0;
1088
/* Get chroma subsampling factors for source and destination */
1089
gavl_pixelformat_chroma_sub(format->pixelformat, &sub_h, &sub_v);
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;
1099
src_width = format->image_width / sub_h;
1100
src_height = format->image_height / sub_v;
1104
src_width = format->image_width;
1105
src_height = format->image_height;
1110
ctx->src_rect.h /= 2.0;
1111
ctx->dst_rect.h /= 2;
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");
1124
/* Calculate chroma offsets */
1125
if(plane && !(opt->conversion_flags & GAVL_CONVOLVE_CHROMA))
1143
/* Downsample coefficients */
1145
h_radius_real = h_radius;
1146
v_radius_real = v_radius;
1152
downsample_coeffs(fac_h, h_coeffs, h_radius,
1153
&h_c, &h_radius_real);
1154
h_coeffs_real = h_c;
1157
h_coeffs_real = h_coeffs;
1163
downsample_coeffs(fac_v, v_coeffs, v_radius,
1164
&v_c, &v_radius_real);
1165
v_coeffs_real = v_c;
1168
v_coeffs_real = v_coeffs;
1174
ctx->num_directions = 0;
1176
ctx->num_directions++;
1178
ctx->num_directions++;
1180
/* Set source and destination frame planes */
1182
if(gavl_pixelformat_is_planar(format->pixelformat))
1184
ctx->src_frame_plane = plane;
1185
ctx->dst_frame_plane = plane;
1189
ctx->src_frame_plane = 0;
1190
ctx->dst_frame_plane = 0;
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);
1200
/* Set source and destination offsets */
1202
if(ctx->num_directions == 1)
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);
1209
/* We set this once here */
1211
ctx->offset = &(ctx->offset1);
1212
ctx->dst_size = ctx->dst_rect.w;
1214
else if(ctx->num_directions == 2)
1216
get_offset_internal(format->pixelformat,
1217
plane, &ctx->offset1.src_advance, &ctx->offset1.src_offset);
1219
get_offset_internal(format->pixelformat,
1220
plane, &ctx->offset2.dst_advance, &ctx->offset2.dst_offset);
1222
ctx->offset1.dst_offset = 0;
1223
ctx->offset1.dst_advance = ctx->offset1.src_advance;
1225
if((format->pixelformat == GAVL_YUY2) ||
1226
(format->pixelformat == GAVL_UYVY))
1228
ctx->offset1.dst_advance = 1;
1230
ctx->offset2.src_advance = ctx->offset1.dst_advance;
1231
ctx->offset2.src_offset = ctx->offset1.dst_offset;
1237
if(!ctx->num_directions)
1239
if((format->pixelformat == GAVL_YUY2) ||
1240
(format->pixelformat == GAVL_UYVY))
1241
ctx->func1 = copy_scanline_advance;
1243
ctx->func1 = copy_scanline_noadvance;
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);
1251
/* We set this once here */
1253
ctx->offset = &(ctx->offset1);
1254
ctx->dst_size = ctx->dst_rect.w;
1256
ctx->num_directions = 1;
1260
else if(scale_x && scale_y)
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),
1269
// fprintf(stderr, "Initializing x table done\n");
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),
1279
// fprintf(stderr, "Initializing y table done\n");
1281
/* Check if we can scale in x and y-directions at once */
1283
if((tmp_opt.scale_mode == tmp_opt_y.scale_mode) &&
1284
(tmp_opt.scale_order == tmp_opt_y.scale_order))
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");
1294
if(ctx->func1) /* Scaling routines for x-y are there, good */
1296
ctx->num_directions = 1;
1298
gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
1299
gavl_video_scale_table_init_int(&(ctx->table_v), bits_h);
1303
gavl_video_scale_table_get_src_indices(&(ctx->table_h),
1307
gavl_video_scale_table_get_src_indices(&(ctx->table_v),
1311
// fprintf(stderr, "X then Y\n");
1314
ctx->buffer_width = ctx->dst_rect.w;
1315
ctx->buffer_height = src_rect_i.h;
1317
gavl_video_scale_table_shift_indices(&(ctx->table_v),
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);
1325
gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
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);
1334
gavl_video_scale_table_init_int(&(ctx->table_v), bits_v);
1336
/* Allocate temporary buffer */
1337
alloc_temp(ctx, format->pixelformat);
1342
// fprintf(stderr, "Initializing x table\n");
1343
gavl_video_options_copy(&tmp_opt, opt);
1344
tmp_opt.scale_mode = GAVL_SCALE_NONE;
1346
gavl_video_scale_table_init_convolve(&(ctx->table_h),
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);
1357
gavl_video_scale_table_init_int(&(ctx->table_h), bits_h);
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),
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);
1376
gavl_video_scale_table_init_int(&(ctx->table_v), bits_v);
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));
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++)
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;
832
1404
void gavl_video_scale_context_cleanup(gavl_video_scale_context_t * ctx)
834
1406
gavl_video_scale_table_cleanup(&(ctx->table_h));
835
1407
gavl_video_scale_table_cleanup(&(ctx->table_v));
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)
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)