X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_v360.c;h=94473cd5b3d806ee826d6e32a2396d9d1580c67d;hb=c67d2a287502845baadf986a9c63e6117a25be3f;hp=2a51f24c34bb91595d1dbebc2661f6839303ac19;hpb=3a035a8cd2ca6875073e59a76f9862dc02ad1d9b;p=ffmpeg diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index 2a51f24c34b..94473cd5b3d 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -3133,8 +3133,8 @@ static int perspective_to_xyz(const V360Context *s, const float cos_theta = cosf(theta); vec[0] = cos_theta * sin_phi; - vec[1] = sin_theta; - vec[2] = cos_theta * cos_phi; + vec[1] = cos_theta * cos_phi; + vec[2] = sin_theta; } else { vec[0] = 0.f; vec[1] = 1.f; @@ -3142,7 +3142,6 @@ static int perspective_to_xyz(const V360Context *s, return 0; } - normalize_vector(vec); return 1; } @@ -3863,73 +3862,76 @@ static int xyz_to_octahedron(const V360Context *s, return 1; } -static void multiply_matrix(float c[3][3], const float a[3][3], const float b[3][3]) +static void multiply_quaternion(float c[4], const float a[4], const float b[4]) { - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - float sum = 0.f; - - for (int k = 0; k < 3; k++) - sum += a[i][k] * b[k][j]; + c[0] = a[0] * b[0] - a[1] * b[1] - a[2] * b[2] - a[3] * b[3]; + c[1] = a[1] * b[0] + a[0] * b[1] + a[2] * b[3] - a[3] * b[2]; + c[2] = a[2] * b[0] + a[0] * b[2] + a[3] * b[1] - a[1] * b[3]; + c[3] = a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1]; +} - c[i][j] = sum; - } - } +static void conjugate_quaternion(float d[4], const float q[4]) +{ + d[0] = q[0]; + d[1] = -q[1]; + d[2] = -q[2]; + d[3] = -q[3]; } /** - * Calculate rotation matrix for yaw/pitch/roll angles. + * Calculate rotation quaternion for yaw/pitch/roll angles. */ -static inline void calculate_rotation_matrix(float yaw, float pitch, float roll, - float rot_mat[3][3], - const int rotation_order[3]) +static inline void calculate_rotation(float yaw, float pitch, float roll, + float rot_quaternion[2][4], + const int rotation_order[3]) { const float yaw_rad = yaw * M_PI / 180.f; const float pitch_rad = pitch * M_PI / 180.f; const float roll_rad = roll * M_PI / 180.f; - const float sin_yaw = sinf(yaw_rad); - const float cos_yaw = cosf(yaw_rad); - const float sin_pitch = sinf(pitch_rad); - const float cos_pitch = cosf(pitch_rad); - const float sin_roll = sinf(roll_rad); - const float cos_roll = cosf(roll_rad); - - float m[3][3][3]; - float temp[3][3]; + const float sin_yaw = sinf(yaw_rad * 0.5f); + const float cos_yaw = cosf(yaw_rad * 0.5f); + const float sin_pitch = sinf(pitch_rad * 0.5f); + const float cos_pitch = cosf(pitch_rad * 0.5f); + const float sin_roll = sinf(roll_rad * 0.5f); + const float cos_roll = cosf(roll_rad * 0.5f); - 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; + float m[3][4]; + float tmp[2][4]; - m[1][0][0] = 1; m[1][0][1] = 0; m[1][0][2] = 0; - m[1][1][0] = 0; m[1][1][1] = cos_pitch; m[1][1][2] = -sin_pitch; - m[1][2][0] = 0; m[1][2][1] = sin_pitch; m[1][2][2] = cos_pitch; + m[0][0] = cos_yaw; m[0][1] = 0.f; m[0][2] = sin_yaw; m[0][3] = 0.f; + m[1][0] = cos_pitch; m[1][1] = sin_pitch; m[1][2] = 0.f; m[1][3] = 0.f; + m[2][0] = cos_roll; m[2][1] = 0.f; m[2][2] = 0.f; m[2][3] = sin_roll; - m[2][0][0] = cos_roll; m[2][0][1] = -sin_roll; m[2][0][2] = 0; - m[2][1][0] = sin_roll; m[2][1][1] = cos_roll; m[2][1][2] = 0; - m[2][2][0] = 0; m[2][2][1] = 0; m[2][2][2] = 1; + multiply_quaternion(tmp[0], rot_quaternion[0], m[rotation_order[0]]); + multiply_quaternion(tmp[1], tmp[0], m[rotation_order[1]]); + multiply_quaternion(rot_quaternion[0], tmp[1], m[rotation_order[2]]); - multiply_matrix(temp, m[rotation_order[0]], m[rotation_order[1]]); - multiply_matrix(rot_mat, temp, m[rotation_order[2]]); + conjugate_quaternion(rot_quaternion[1], rot_quaternion[0]); } /** - * Rotate vector with given rotation matrix. + * Rotate vector with given rotation quaternion. * - * @param rot_mat rotation matrix + * @param rot_quaternion rotation quaternion * @param vec vector */ -static inline void rotate(const float rot_mat[3][3], +static inline void rotate(const float rot_quaternion[2][4], float *vec) { - const float x_tmp = vec[0] * rot_mat[0][0] + vec[1] * rot_mat[0][1] + vec[2] * rot_mat[0][2]; - const float y_tmp = vec[0] * rot_mat[1][0] + vec[1] * rot_mat[1][1] + vec[2] * rot_mat[1][2]; - const float z_tmp = vec[0] * rot_mat[2][0] + vec[1] * rot_mat[2][1] + vec[2] * rot_mat[2][2]; + float qv[4], temp[4], rqv[4]; + + qv[0] = 0.f; + qv[1] = vec[0]; + qv[2] = vec[1]; + qv[3] = vec[2]; + + multiply_quaternion(temp, rot_quaternion[0], qv); + multiply_quaternion(rqv, temp, rot_quaternion[1]); - vec[0] = x_tmp; - vec[1] = y_tmp; - vec[2] = z_tmp; + vec[0] = rqv[1]; + vec[1] = rqv[2]; + vec[2] = rqv[3]; } static inline void set_mirror_modifier(int h_flip, int v_flip, int d_flip, @@ -4109,7 +4111,7 @@ static av_always_inline int v360_slice(AVFilterContext *ctx, void *arg, int jobn else out_mask = 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); + rotate(s->rot_quaternion, vec); av_assert1(!isnan(vec[0]) && !isnan(vec[1]) && !isnan(vec[2])); normalize_vector(vec); mirror(s->output_mirror_modifier, vec); @@ -4667,7 +4669,9 @@ static int config_output(AVFilterLink *outlink) return err; } - calculate_rotation_matrix(s->yaw, s->pitch, s->roll, s->rot_mat, s->rotation_order); + calculate_rotation(s->yaw, s->pitch, s->roll, + s->rot_quaternion, s->rotation_order); + set_mirror_modifier(s->h_flip, s->v_flip, s->d_flip, s->output_mirror_modifier); ctx->internal->execute(ctx, v360_slice, NULL, NULL, s->nb_threads); @@ -4702,8 +4706,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags) { + V360Context *s = ctx->priv; int ret; + s->yaw = s->pitch = s->roll = 0.f; + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); if (ret < 0) return ret; @@ -4711,6 +4718,16 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar return config_output(ctx->outputs[0]); } +static av_cold int init(AVFilterContext *ctx) +{ + V360Context *s = ctx->priv; + + s->rot_quaternion[0][0] = 1.f; + s->rot_quaternion[0][1] = s->rot_quaternion[0][2] = s->rot_quaternion[0][3] = 0.f; + + return 0; +} + static av_cold void uninit(AVFilterContext *ctx) { V360Context *s = ctx->priv; @@ -4752,6 +4769,7 @@ AVFilter ff_vf_v360 = { .name = "v360", .description = NULL_IF_CONFIG_SMALL("Convert 360 projection of video."), .priv_size = sizeof(V360Context), + .init = init, .uninit = uninit, .query_formats = query_formats, .inputs = inputs,