mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-02-28 01:31:00 +00:00
avfilter/vf_v360: refactor creation of remap data
This commit is contained in:
parent
a09213da23
commit
05ffaa252e
@ -85,6 +85,12 @@ enum RotationOrder {
|
||||
NB_RORDERS,
|
||||
};
|
||||
|
||||
typedef struct XYRemap {
|
||||
uint16_t u[4][4];
|
||||
uint16_t v[4][4];
|
||||
float ker[4][4];
|
||||
} XYRemap;
|
||||
|
||||
typedef struct V360Context {
|
||||
const AVClass *class;
|
||||
int in, out;
|
||||
@ -130,11 +136,23 @@ typedef struct V360Context {
|
||||
int uv_linesize[4];
|
||||
int nb_planes;
|
||||
int nb_allocated;
|
||||
int elements;
|
||||
|
||||
uint16_t *u[4], *v[4];
|
||||
int16_t *ker[4];
|
||||
unsigned map[4];
|
||||
|
||||
void (*in_transform)(const struct V360Context *s,
|
||||
const float *vec, int width, int height,
|
||||
uint16_t us[4][4], uint16_t vs[4][4], float *du, float *dv);
|
||||
|
||||
void (*out_transform)(const struct V360Context *s,
|
||||
int i, int j, int width, int height,
|
||||
float *vec);
|
||||
|
||||
void (*calculate_kernel)(float du, float dv, const XYRemap *rmap,
|
||||
uint16_t *u, uint16_t *v, int16_t *ker);
|
||||
|
||||
int (*remap_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
|
||||
|
||||
void (*remap_line)(uint8_t *dst, int width, const uint8_t *src, ptrdiff_t in_linesize,
|
||||
|
@ -207,12 +207,6 @@ static void remap1_##bits##bit_line_c(uint8_t *dst, int width, const uint8_t *sr
|
||||
DEFINE_REMAP1_LINE( 8, 1)
|
||||
DEFINE_REMAP1_LINE(16, 2)
|
||||
|
||||
typedef struct XYRemap {
|
||||
uint16_t u[4][4];
|
||||
uint16_t v[4][4];
|
||||
float ker[4][4];
|
||||
} XYRemap;
|
||||
|
||||
/**
|
||||
* Generate remapping function with a given window size and pixel depth.
|
||||
*
|
||||
@ -2167,6 +2161,47 @@ static void set_dimensions(int *outw, int *outh, int w, int h, const AVPixFmtDes
|
||||
outh[0] = outh[3] = h;
|
||||
}
|
||||
|
||||
// Calculate remap data
|
||||
static av_always_inline void v360_filter(AVFilterContext *ctx)
|
||||
{
|
||||
V360Context *s = ctx->priv;
|
||||
|
||||
for (int p = 0; p < s->nb_allocated; p++) {
|
||||
const int width = s->pr_width[p];
|
||||
const int uv_linesize = s->uv_linesize[p];
|
||||
const int height = s->pr_height[p];
|
||||
const int in_width = s->inplanewidth[p];
|
||||
const int in_height = s->inplaneheight[p];
|
||||
float du, dv;
|
||||
float vec[3];
|
||||
XYRemap rmap;
|
||||
|
||||
for (int j = 0; j < height; j++) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
uint16_t *u = s->u[p] + (j * uv_linesize + i) * s->elements;
|
||||
uint16_t *v = s->v[p] + (j * uv_linesize + i) * s->elements;
|
||||
int16_t *ker = s->ker[p] + (j * uv_linesize + i) * s->elements;
|
||||
|
||||
if (s->out_transpose)
|
||||
s->out_transform(s, j, i, height, width, vec);
|
||||
else
|
||||
s->out_transform(s, i, j, width, height, vec);
|
||||
av_assert1(!isnan(vec[0]) && !isnan(vec[1]) && !isnan(vec[2]));
|
||||
rotate(s->rot_mat, vec);
|
||||
av_assert1(!isnan(vec[0]) && !isnan(vec[1]) && !isnan(vec[2]));
|
||||
normalize_vector(vec);
|
||||
mirror(s->output_mirror_modifier, vec);
|
||||
if (s->in_transpose)
|
||||
s->in_transform(s, vec, in_height, in_width, rmap.v, rmap.u, &du, &dv);
|
||||
else
|
||||
s->in_transform(s, vec, in_width, in_height, rmap.u, rmap.v, &du, &dv);
|
||||
av_assert1(!isnan(du) && !isnan(dv));
|
||||
s->calculate_kernel(du, dv, &rmap, u, v, ker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int config_output(AVFilterLink *outlink)
|
||||
{
|
||||
AVFilterContext *ctx = outlink->src;
|
||||
@ -2176,20 +2211,11 @@ static int config_output(AVFilterLink *outlink)
|
||||
const int depth = desc->comp[0].depth;
|
||||
int sizeof_uv;
|
||||
int sizeof_ker;
|
||||
int elements;
|
||||
int err;
|
||||
int h, w;
|
||||
int in_offset_h, in_offset_w;
|
||||
int out_offset_h, out_offset_w;
|
||||
float hf, wf;
|
||||
void (*in_transform)(const V360Context *s,
|
||||
const float *vec, int width, int height,
|
||||
uint16_t us[4][4], uint16_t vs[4][4], float *du, float *dv);
|
||||
void (*out_transform)(const V360Context *s,
|
||||
int i, int j, int width, int height,
|
||||
float *vec);
|
||||
void (*calculate_kernel)(float du, float dv, const XYRemap *rmap,
|
||||
uint16_t *u, uint16_t *v, int16_t *ker);
|
||||
int (*prepare_out)(AVFilterContext *ctx);
|
||||
|
||||
s->input_mirror_modifier[0] = s->ih_flip ? -1.f : 1.f;
|
||||
@ -2197,32 +2223,32 @@ static int config_output(AVFilterLink *outlink)
|
||||
|
||||
switch (s->interp) {
|
||||
case NEAREST:
|
||||
calculate_kernel = nearest_kernel;
|
||||
s->calculate_kernel = nearest_kernel;
|
||||
s->remap_slice = depth <= 8 ? remap1_8bit_slice : remap1_16bit_slice;
|
||||
elements = 1;
|
||||
sizeof_uv = sizeof(uint16_t) * elements;
|
||||
s->elements = 1;
|
||||
sizeof_uv = sizeof(uint16_t) * s->elements;
|
||||
sizeof_ker = 0;
|
||||
break;
|
||||
case BILINEAR:
|
||||
calculate_kernel = bilinear_kernel;
|
||||
s->calculate_kernel = bilinear_kernel;
|
||||
s->remap_slice = depth <= 8 ? remap2_8bit_slice : remap2_16bit_slice;
|
||||
elements = 2 * 2;
|
||||
sizeof_uv = sizeof(uint16_t) * elements;
|
||||
sizeof_ker = sizeof(uint16_t) * elements;
|
||||
s->elements = 2 * 2;
|
||||
sizeof_uv = sizeof(uint16_t) * s->elements;
|
||||
sizeof_ker = sizeof(uint16_t) * s->elements;
|
||||
break;
|
||||
case BICUBIC:
|
||||
calculate_kernel = bicubic_kernel;
|
||||
s->calculate_kernel = bicubic_kernel;
|
||||
s->remap_slice = depth <= 8 ? remap4_8bit_slice : remap4_16bit_slice;
|
||||
elements = 4 * 4;
|
||||
sizeof_uv = sizeof(uint16_t) * elements;
|
||||
sizeof_ker = sizeof(uint16_t) * elements;
|
||||
s->elements = 4 * 4;
|
||||
sizeof_uv = sizeof(uint16_t) * s->elements;
|
||||
sizeof_ker = sizeof(uint16_t) * s->elements;
|
||||
break;
|
||||
case LANCZOS:
|
||||
calculate_kernel = lanczos_kernel;
|
||||
s->calculate_kernel = lanczos_kernel;
|
||||
s->remap_slice = depth <= 8 ? remap4_8bit_slice : remap4_16bit_slice;
|
||||
elements = 4 * 4;
|
||||
sizeof_uv = sizeof(uint16_t) * elements;
|
||||
sizeof_ker = sizeof(uint16_t) * elements;
|
||||
s->elements = 4 * 4;
|
||||
sizeof_uv = sizeof(uint16_t) * s->elements;
|
||||
sizeof_ker = sizeof(uint16_t) * s->elements;
|
||||
break;
|
||||
default:
|
||||
av_assert0(0);
|
||||
@ -2277,31 +2303,31 @@ static int config_output(AVFilterLink *outlink)
|
||||
|
||||
switch (s->in) {
|
||||
case EQUIRECTANGULAR:
|
||||
in_transform = xyz_to_equirect;
|
||||
s->in_transform = xyz_to_equirect;
|
||||
err = 0;
|
||||
wf = w;
|
||||
hf = h;
|
||||
break;
|
||||
case CUBEMAP_3_2:
|
||||
in_transform = xyz_to_cube3x2;
|
||||
s->in_transform = xyz_to_cube3x2;
|
||||
err = prepare_cube_in(ctx);
|
||||
wf = w / 3.f * 4.f;
|
||||
hf = h;
|
||||
break;
|
||||
case CUBEMAP_1_6:
|
||||
in_transform = xyz_to_cube1x6;
|
||||
s->in_transform = xyz_to_cube1x6;
|
||||
err = prepare_cube_in(ctx);
|
||||
wf = w * 4.f;
|
||||
hf = h / 3.f;
|
||||
break;
|
||||
case CUBEMAP_6_1:
|
||||
in_transform = xyz_to_cube6x1;
|
||||
s->in_transform = xyz_to_cube6x1;
|
||||
err = prepare_cube_in(ctx);
|
||||
wf = w / 3.f * 2.f;
|
||||
hf = h * 2.f;
|
||||
break;
|
||||
case EQUIANGULAR:
|
||||
in_transform = xyz_to_eac;
|
||||
s->in_transform = xyz_to_eac;
|
||||
err = prepare_eac_in(ctx);
|
||||
wf = w;
|
||||
hf = h / 9.f * 8.f;
|
||||
@ -2310,19 +2336,19 @@ static int config_output(AVFilterLink *outlink)
|
||||
av_log(ctx, AV_LOG_ERROR, "Flat format is not accepted as input.\n");
|
||||
return AVERROR(EINVAL);
|
||||
case DUAL_FISHEYE:
|
||||
in_transform = xyz_to_dfisheye;
|
||||
s->in_transform = xyz_to_dfisheye;
|
||||
err = 0;
|
||||
wf = w;
|
||||
hf = h;
|
||||
break;
|
||||
case BARREL:
|
||||
in_transform = xyz_to_barrel;
|
||||
s->in_transform = xyz_to_barrel;
|
||||
err = 0;
|
||||
wf = w / 5.f * 4.f;
|
||||
hf = h;
|
||||
break;
|
||||
case STEREOGRAPHIC:
|
||||
in_transform = xyz_to_stereographic;
|
||||
s->in_transform = xyz_to_stereographic;
|
||||
err = 0;
|
||||
wf = w;
|
||||
hf = h / 2.f;
|
||||
@ -2338,55 +2364,55 @@ static int config_output(AVFilterLink *outlink)
|
||||
|
||||
switch (s->out) {
|
||||
case EQUIRECTANGULAR:
|
||||
out_transform = equirect_to_xyz;
|
||||
s->out_transform = equirect_to_xyz;
|
||||
prepare_out = NULL;
|
||||
w = roundf(wf);
|
||||
h = roundf(hf);
|
||||
break;
|
||||
case CUBEMAP_3_2:
|
||||
out_transform = cube3x2_to_xyz;
|
||||
s->out_transform = cube3x2_to_xyz;
|
||||
prepare_out = prepare_cube_out;
|
||||
w = roundf(wf / 4.f * 3.f);
|
||||
h = roundf(hf);
|
||||
break;
|
||||
case CUBEMAP_1_6:
|
||||
out_transform = cube1x6_to_xyz;
|
||||
s->out_transform = cube1x6_to_xyz;
|
||||
prepare_out = prepare_cube_out;
|
||||
w = roundf(wf / 4.f);
|
||||
h = roundf(hf * 3.f);
|
||||
break;
|
||||
case CUBEMAP_6_1:
|
||||
out_transform = cube6x1_to_xyz;
|
||||
s->out_transform = cube6x1_to_xyz;
|
||||
prepare_out = prepare_cube_out;
|
||||
w = roundf(wf / 2.f * 3.f);
|
||||
h = roundf(hf / 2.f);
|
||||
break;
|
||||
case EQUIANGULAR:
|
||||
out_transform = eac_to_xyz;
|
||||
s->out_transform = eac_to_xyz;
|
||||
prepare_out = prepare_eac_out;
|
||||
w = roundf(wf);
|
||||
h = roundf(hf / 8.f * 9.f);
|
||||
break;
|
||||
case FLAT:
|
||||
out_transform = flat_to_xyz;
|
||||
s->out_transform = flat_to_xyz;
|
||||
prepare_out = prepare_flat_out;
|
||||
w = roundf(wf);
|
||||
h = roundf(hf);
|
||||
break;
|
||||
case DUAL_FISHEYE:
|
||||
out_transform = dfisheye_to_xyz;
|
||||
s->out_transform = dfisheye_to_xyz;
|
||||
prepare_out = NULL;
|
||||
w = roundf(wf);
|
||||
h = roundf(hf);
|
||||
break;
|
||||
case BARREL:
|
||||
out_transform = barrel_to_xyz;
|
||||
s->out_transform = barrel_to_xyz;
|
||||
prepare_out = NULL;
|
||||
w = roundf(wf / 4.f * 5.f);
|
||||
h = roundf(hf);
|
||||
break;
|
||||
case STEREOGRAPHIC:
|
||||
out_transform = stereographic_to_xyz;
|
||||
s->out_transform = stereographic_to_xyz;
|
||||
prepare_out = prepare_stereographic_out;
|
||||
w = roundf(wf);
|
||||
h = roundf(hf * 2.f);
|
||||
@ -2467,41 +2493,7 @@ static int config_output(AVFilterLink *outlink)
|
||||
calculate_rotation_matrix(s->yaw, s->pitch, s->roll, s->rot_mat, s->rotation_order);
|
||||
set_mirror_modifier(s->h_flip, s->v_flip, s->d_flip, s->output_mirror_modifier);
|
||||
|
||||
// Calculate remap data
|
||||
for (int p = 0; p < s->nb_allocated; p++) {
|
||||
const int width = s->pr_width[p];
|
||||
const int uv_linesize = s->uv_linesize[p];
|
||||
const int height = s->pr_height[p];
|
||||
const int in_width = s->inplanewidth[p];
|
||||
const int in_height = s->inplaneheight[p];
|
||||
float du, dv;
|
||||
float vec[3];
|
||||
XYRemap rmap;
|
||||
|
||||
for (int j = 0; j < height; j++) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
uint16_t *u = s->u[p] + (j * uv_linesize + i) * elements;
|
||||
uint16_t *v = s->v[p] + (j * uv_linesize + i) * elements;
|
||||
int16_t *ker = s->ker[p] + (j * uv_linesize + i) * elements;
|
||||
|
||||
if (s->out_transpose)
|
||||
out_transform(s, j, i, height, width, vec);
|
||||
else
|
||||
out_transform(s, i, j, width, height, vec);
|
||||
av_assert1(!isnan(vec[0]) && !isnan(vec[1]) && !isnan(vec[2]));
|
||||
rotate(s->rot_mat, vec);
|
||||
av_assert1(!isnan(vec[0]) && !isnan(vec[1]) && !isnan(vec[2]));
|
||||
normalize_vector(vec);
|
||||
mirror(s->output_mirror_modifier, vec);
|
||||
if (s->in_transpose)
|
||||
in_transform(s, vec, in_height, in_width, rmap.v, rmap.u, &du, &dv);
|
||||
else
|
||||
in_transform(s, vec, in_width, in_height, rmap.u, rmap.v, &du, &dv);
|
||||
av_assert1(!isnan(du) && !isnan(dv));
|
||||
calculate_kernel(du, dv, &rmap, u, v, ker);
|
||||
}
|
||||
}
|
||||
}
|
||||
v360_filter(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user