提交 cb8c3530 编写于 作者: P Paul B Mahol

avfilter/vf_v360: add option to pick rotation order

上级 d1315414
...@@ -18065,6 +18065,20 @@ Default resolution depends on formats. ...@@ -18065,6 +18065,20 @@ Default resolution depends on formats.
@item roll @item roll
Set rotation for the output video. Values in degrees. Set rotation for the output video. Values in degrees.
@item rorder
Set rotation order for the output video. Choose one item for each position.
@table @samp
@item y, Y
yaw
@item p, P
pitch
@item r, R
roll
@end table
Default value is @b{@samp{ypr}}.
@item h_flip @item h_flip
@item v_flip @item v_flip
@item d_flip @item d_flip
......
...@@ -70,20 +70,29 @@ enum Rotation { ...@@ -70,20 +70,29 @@ enum Rotation {
NB_ROTATIONS, NB_ROTATIONS,
}; };
enum RotationOrder {
YAW,
PITCH,
ROLL,
NB_RORDERS,
};
typedef struct V360Context { typedef struct V360Context {
const AVClass *class; const AVClass *class;
int in, out; int in, out;
int interp; int interp;
int width, height; int width, height;
char* in_forder; char *in_forder;
char* out_forder; char *out_forder;
char* in_frot; char *in_frot;
char* out_frot; char *out_frot;
char *rorder;
int in_cubemap_face_order[6]; int in_cubemap_face_order[6];
int out_cubemap_direction_order[6]; int out_cubemap_direction_order[6];
int in_cubemap_face_rotation[6]; int in_cubemap_face_rotation[6];
int out_cubemap_face_rotation[6]; int out_cubemap_face_rotation[6];
int rotation_order[3];
float in_pad, out_pad; float in_pad, out_pad;
......
...@@ -90,6 +90,7 @@ static const AVOption v360_options[] = { ...@@ -90,6 +90,7 @@ static const AVOption v360_options[] = {
{ "yaw", "yaw rotation", OFFSET(yaw), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "yaw"}, { "yaw", "yaw rotation", OFFSET(yaw), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "yaw"},
{ "pitch", "pitch rotation", OFFSET(pitch), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "pitch"}, { "pitch", "pitch rotation", OFFSET(pitch), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "pitch"},
{ "roll", "roll rotation", OFFSET(roll), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "roll"}, { "roll", "roll rotation", OFFSET(roll), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, -180.f, 180.f, FLAGS, "roll"},
{ "rorder", "rotation order", OFFSET(rorder), AV_OPT_TYPE_STRING, {.str="ypr"}, 0, 0, FLAGS, "rorder"},
{ "h_fov", "horizontal field of view", OFFSET(h_fov), AV_OPT_TYPE_FLOAT, {.dbl=90.f}, 0.f, 180.f, FLAGS, "h_fov"}, { "h_fov", "horizontal field of view", OFFSET(h_fov), AV_OPT_TYPE_FLOAT, {.dbl=90.f}, 0.f, 180.f, FLAGS, "h_fov"},
{ "v_fov", "vertical field of view", OFFSET(v_fov), AV_OPT_TYPE_FLOAT, {.dbl=45.f}, 0.f, 90.f, FLAGS, "v_fov"}, { "v_fov", "vertical field of view", OFFSET(v_fov), AV_OPT_TYPE_FLOAT, {.dbl=45.f}, 0.f, 90.f, FLAGS, "v_fov"},
{ "h_flip", "flip video horizontally", OFFSET(h_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "h_flip"}, { "h_flip", "flip video horizontally", OFFSET(h_flip), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "h_flip"},
...@@ -499,6 +500,26 @@ static int get_rotation(char c) ...@@ -499,6 +500,26 @@ static int get_rotation(char c)
} }
} }
/**
* Convert char to corresponding rotation order.
*/
static int get_rorder(char c)
{
switch (c) {
case 'Y':
case 'y':
return YAW;
case 'P':
case 'p':
return PITCH;
case 'R':
case 'r':
return ROLL;
default:
return -1;
}
}
/** /**
* Prepare data for processing cubemap input format. * Prepare data for processing cubemap input format.
* *
...@@ -1849,11 +1870,26 @@ static void xyz_to_barrel(const V360Context *s, ...@@ -1849,11 +1870,26 @@ static void xyz_to_barrel(const V360Context *s,
} }
static void multiply_matrix(float c[3][3], const float a[3][3], const float b[3][3])
{
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
float sum = 0;
for (int k = 0; k < 3; k++)
sum += a[i][k] * b[k][j];
c[i][j] = sum;
}
}
}
/** /**
* Calculate rotation matrix for yaw/pitch/roll angles. * Calculate rotation matrix for yaw/pitch/roll angles.
*/ */
static inline void calculate_rotation_matrix(float yaw, float pitch, float roll, static inline void calculate_rotation_matrix(float yaw, float pitch, float roll,
float rot_mat[3][3]) float rot_mat[3][3],
const int rotation_order[3])
{ {
const float yaw_rad = yaw * M_PI / 180.f; const float yaw_rad = yaw * M_PI / 180.f;
const float pitch_rad = pitch * M_PI / 180.f; const float pitch_rad = pitch * M_PI / 180.f;
...@@ -1866,17 +1902,23 @@ static inline void calculate_rotation_matrix(float yaw, float pitch, float roll, ...@@ -1866,17 +1902,23 @@ static inline void calculate_rotation_matrix(float yaw, float pitch, float roll,
const float sin_roll = sinf(roll_rad); const float sin_roll = sinf(roll_rad);
const float cos_roll = cosf(roll_rad); const float cos_roll = cosf(roll_rad);
rot_mat[0][0] = sin_yaw * sin_pitch * sin_roll + cos_yaw * cos_roll; float m[3][3][3];
rot_mat[0][1] = sin_yaw * sin_pitch * cos_roll - cos_yaw * sin_roll; float temp[3][3];
rot_mat[0][2] = sin_yaw * cos_pitch;
m[0][0][0] = cos_yaw; m[0][0][1] = 0; m[0][0][2] = sin_yaw;
m[0][1][0] = 0; m[0][1][1] = 1; m[0][1][2] = 0;
m[0][2][0] = -sin_yaw; m[0][2][1] = 0; m[0][2][2] = cos_yaw;
rot_mat[1][0] = cos_pitch * sin_roll; m[1][0][0] = 1; m[1][0][1] = 0; m[1][0][2] = 0;
rot_mat[1][1] = cos_pitch * cos_roll; m[1][1][0] = 0; m[1][1][1] = cos_pitch; m[1][1][2] = -sin_pitch;
rot_mat[1][2] = -sin_pitch; m[1][2][0] = 0; m[1][2][1] = sin_pitch; m[1][2][2] = cos_pitch;
rot_mat[2][0] = cos_yaw * sin_pitch * sin_roll - sin_yaw * cos_roll; m[2][0][0] = cos_roll; m[2][0][1] = -sin_roll; m[2][0][2] = 0;
rot_mat[2][1] = cos_yaw * sin_pitch * cos_roll + sin_yaw * sin_roll; m[2][1][0] = sin_roll; m[2][1][1] = cos_roll; m[2][1][2] = 0;
rot_mat[2][2] = cos_yaw * cos_pitch; m[2][2][0] = 0; m[2][2][1] = 0; m[2][2][2] = 1;
multiply_matrix(temp, m[rotation_order[0]], m[rotation_order[1]]);
multiply_matrix(rot_mat, temp, m[rotation_order[2]]);
} }
/** /**
...@@ -1986,6 +2028,26 @@ static int config_output(AVFilterLink *outlink) ...@@ -1986,6 +2028,26 @@ static int config_output(AVFilterLink *outlink)
ff_v360_init(s, depth); ff_v360_init(s, depth);
for (int order = 0; order < NB_RORDERS; order++) {
const char c = s->rorder[order];
int rorder;
if (c == '\0') {
av_log(ctx, AV_LOG_ERROR,
"Incomplete rorder option. Direction for all 3 rotation orders should be specified.\n");
return AVERROR(EINVAL);
}
rorder = get_rorder(c);
if (rorder == -1) {
av_log(ctx, AV_LOG_ERROR,
"Incorrect rotation order symbol '%c' in rorder option.\n", c);
return AVERROR(EINVAL);
}
s->rotation_order[order] = rorder;
}
switch (s->in) { switch (s->in) {
case EQUIRECTANGULAR: case EQUIRECTANGULAR:
in_transform = xyz_to_equirect; in_transform = xyz_to_equirect;
...@@ -2141,7 +2203,7 @@ static int config_output(AVFilterLink *outlink) ...@@ -2141,7 +2203,7 @@ static int config_output(AVFilterLink *outlink)
allocate_plane(s, sizeof_uv, sizeof_ker, 2); allocate_plane(s, sizeof_uv, sizeof_ker, 2);
} }
calculate_rotation_matrix(s->yaw, s->pitch, s->roll, rot_mat); calculate_rotation_matrix(s->yaw, s->pitch, s->roll, rot_mat, s->rotation_order);
set_mirror_modifier(s->h_flip, s->v_flip, s->d_flip, mirror_modifier); set_mirror_modifier(s->h_flip, s->v_flip, s->d_flip, mirror_modifier);
// Calculate remap data // Calculate remap data
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册