1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

avfilter/vf_v360: add truncated square pyramid output format

This commit is contained in:
Paul B Mahol 2020-03-02 17:40:21 +01:00
parent 1281399135
commit 3dd81be866
3 changed files with 71 additions and 1 deletions

View File

@ -19027,6 +19027,10 @@ Set perspective parameter.
@item tetrahedron
Tetrahedron projection.
@item tsp
Truncated square pyramid projection. @i{(output only)}
@end table
@item interp

View File

@ -49,6 +49,7 @@ enum Projections {
PERSPECTIVE,
TETRAHEDRON,
BARREL_SPLIT,
TSPYRAMID,
NB_PROJECTIONS,
};

View File

@ -101,6 +101,7 @@ static const AVOption v360_options[] = {
{"perspective", "perspective", 0, AV_OPT_TYPE_CONST, {.i64=PERSPECTIVE}, 0, 0, FLAGS, "out" },
{"tetrahedron", "tetrahedron", 0, AV_OPT_TYPE_CONST, {.i64=TETRAHEDRON}, 0, 0, FLAGS, "out" },
{"barrelsplit", "barrel split facebook's 360 format", 0, AV_OPT_TYPE_CONST, {.i64=BARREL_SPLIT}, 0, 0, FLAGS, "out" },
{ "tsp", "truncated square pyramid", 0, AV_OPT_TYPE_CONST, {.i64=TSPYRAMID}, 0, 0, FLAGS, "out" },
{ "interp", "set interpolation method", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=BILINEAR}, 0, NB_INTERP_METHODS-1, FLAGS, "interp" },
{ "near", "nearest neighbour", 0, AV_OPT_TYPE_CONST, {.i64=NEAREST}, 0, 0, FLAGS, "interp" },
{ "nearest", "nearest neighbour", 0, AV_OPT_TYPE_CONST, {.i64=NEAREST}, 0, 0, FLAGS, "interp" },
@ -3227,6 +3228,64 @@ static int barrelsplit_to_xyz(const V360Context *s,
return 1;
}
/**
* Calculate 3D coordinates on sphere for corresponding frame position in tspyramid format.
*
* @param s filter private context
* @param i horizontal position on frame [0, width)
* @param j vertical position on frame [0, height)
* @param width frame width
* @param height frame height
* @param vec coordinates on sphere
*/
static int tspyramid_to_xyz(const V360Context *s,
int i, int j, int width, int height,
float *vec)
{
const float x = (i + 0.5f) / width;
const float y = (j + 0.5f) / height;
if (x < 0.5f) {
vec[0] = x * 4.f - 1.f;
vec[1] = -(y * 2.f - 1.f);
vec[2] = -1.f;
} else if (x >= 0.6875f && x < 0.8125f &&
y >= 0.375f && y < 0.625f) {
vec[0] = -(x - 0.6875f) * 16.f + 1.f;
vec[1] = -(y - 0.375f) * 8.f + 1.f;
vec[2] = 1.f;
} else if (0.5f <= x && x < 0.6875f &&
((0.f <= y && y < 0.375f && y >= 2.f * (x - 0.5f)) ||
(0.375f <= y && y < 0.625f) ||
(0.625f <= y && y < 1.f && y <= 2.f * (1.f - x)))) {
vec[0] = 1.f;
vec[1] = -2.f * (y - 2.f * x + 1.f) / (3.f - 4.f * x) + 1.f;
vec[2] = 2.f * (x - 0.5f) / 0.1875f - 1.f;
} else if (0.8125f <= x && x < 1.f &&
((0.f <= y && y < 0.375f && x >= (1.f - y / 2.f)) ||
(0.375f <= y && y < 0.625f) ||
(0.625f <= y && y < 1.f && y <= (2.f * x - 1.f)))) {
vec[0] = -1.f;
vec[1] = -2.f * (y + 2.f * x - 2.f) / (4.f * x - 3.f) + 1.f;
vec[2] = -2.f * (x - 0.8125f) / 0.1875f + 1.f;
} else if (0.f <= y && y < 0.375f &&
((0.5f <= x && x < 0.8125f && y < 2.f * (x - 0.5f)) ||
(0.6875f <= x && x < 0.8125f) ||
(0.8125f <= x && x < 1.f && x < (1.f - y / 2.f)))) {
vec[0] = 2.f * (1.f - x - 0.5f * y) / (0.5f - y) - 1.f;
vec[1] = 1.f;
vec[2] = -2.f * (0.375f - y) / 0.375f + 1.f;
} else {
vec[0] = 2.f * (0.5f - x + 0.5f * y) / (y - 0.5f) - 1.f;
vec[1] = -1.f;
vec[2] = 2.f * (1.f - y) / 0.375f - 1.f;
}
normalize_vector(vec);
return 1;
}
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++) {
@ -3350,7 +3409,7 @@ static void fov_from_dfov(int format, float d_fov, float w, float h, float *h_fo
case FLAT:
default:
{
const float da = tanf(0.5 * FFMIN(d_fov, 359.f) * M_PI / 180.f);
const float da = tanf(0.5f * FFMIN(d_fov, 359.f) * M_PI / 180.f);
const float d = hypotf(w, h);
*h_fov = atan2f(da * w, d) * 360.f / M_PI;
@ -3792,6 +3851,12 @@ static int config_output(AVFilterLink *outlink)
w = lrintf(wf / 4.f * 3.f);
h = lrintf(hf);
break;
case TSPYRAMID:
s->out_transform = tspyramid_to_xyz;
prepare_out = NULL;
w = lrintf(wf);
h = lrintf(hf);
break;
default:
av_log(ctx, AV_LOG_ERROR, "Specified output format is not handled.\n");
return AVERROR_BUG;