avfilter/vf_v360: add ball projection format
This commit is contained in:
		
							parent
							
								
									b766a13dba
								
							
						
					
					
						commit
						b632ad81c5
					
				@ -18060,6 +18060,9 @@ If diagonal field of view is set it overrides horizontal and vertical field of v
 | 
			
		||||
@item mercator
 | 
			
		||||
Mercator format.
 | 
			
		||||
 | 
			
		||||
@item ball
 | 
			
		||||
Ball format, gives significant distortion toward the back.
 | 
			
		||||
 | 
			
		||||
@end table
 | 
			
		||||
 | 
			
		||||
@item interp
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,7 @@ enum Projections {
 | 
			
		||||
    CUBEMAP_1_6,
 | 
			
		||||
    STEREOGRAPHIC,
 | 
			
		||||
    MERCATOR,
 | 
			
		||||
    BALL,
 | 
			
		||||
    NB_PROJECTIONS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -66,6 +66,7 @@ static const AVOption v360_options[] = {
 | 
			
		||||
    {      "c1x6", "cubemap 1x6",                                0, AV_OPT_TYPE_CONST,  {.i64=CUBEMAP_1_6},     0,                   0, FLAGS, "in" },
 | 
			
		||||
    {        "sg", "stereographic",                              0, AV_OPT_TYPE_CONST,  {.i64=STEREOGRAPHIC},   0,                   0, FLAGS, "in" },
 | 
			
		||||
    {  "mercator", "mercator",                                   0, AV_OPT_TYPE_CONST,  {.i64=MERCATOR},        0,                   0, FLAGS, "in" },
 | 
			
		||||
    {      "ball", "ball",                                       0, AV_OPT_TYPE_CONST,  {.i64=BALL},            0,                   0, FLAGS, "in" },
 | 
			
		||||
    {    "output", "set output projection",            OFFSET(out), AV_OPT_TYPE_INT,    {.i64=CUBEMAP_3_2},     0,    NB_PROJECTIONS-1, FLAGS, "out" },
 | 
			
		||||
    {         "e", "equirectangular",                            0, AV_OPT_TYPE_CONST,  {.i64=EQUIRECTANGULAR}, 0,                   0, FLAGS, "out" },
 | 
			
		||||
    {  "equirect", "equirectangular",                            0, AV_OPT_TYPE_CONST,  {.i64=EQUIRECTANGULAR}, 0,                   0, FLAGS, "out" },
 | 
			
		||||
@ -81,6 +82,7 @@ static const AVOption v360_options[] = {
 | 
			
		||||
    {      "c1x6", "cubemap 1x6",                                0, AV_OPT_TYPE_CONST,  {.i64=CUBEMAP_1_6},     0,                   0, FLAGS, "out" },
 | 
			
		||||
    {        "sg", "stereographic",                              0, AV_OPT_TYPE_CONST,  {.i64=STEREOGRAPHIC},   0,                   0, FLAGS, "out" },
 | 
			
		||||
    {  "mercator", "mercator",                                   0, AV_OPT_TYPE_CONST,  {.i64=MERCATOR},        0,                   0, FLAGS, "out" },
 | 
			
		||||
    {      "ball", "ball",                                       0, AV_OPT_TYPE_CONST,  {.i64=BALL},            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" },
 | 
			
		||||
@ -1582,6 +1584,80 @@ static void mercator_to_xyz(const V360Context *s,
 | 
			
		||||
    vec[2] = -cos_theta * cos_phi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculate frame position in ball format for corresponding 3D coordinates on sphere.
 | 
			
		||||
 *
 | 
			
		||||
 * @param s filter context
 | 
			
		||||
 * @param vec coordinates on sphere
 | 
			
		||||
 * @param width frame width
 | 
			
		||||
 * @param height frame height
 | 
			
		||||
 * @param us horizontal coordinates for interpolation window
 | 
			
		||||
 * @param vs vertical coordinates for interpolation window
 | 
			
		||||
 * @param du horizontal relative coordinate
 | 
			
		||||
 * @param dv vertical relative coordinate
 | 
			
		||||
 */
 | 
			
		||||
static void xyz_to_ball(const V360Context *s,
 | 
			
		||||
                        const float *vec, int width, int height,
 | 
			
		||||
                        uint16_t us[4][4], uint16_t vs[4][4], float *du, float *dv)
 | 
			
		||||
{
 | 
			
		||||
    const float l = hypotf(vec[0], vec[1]);
 | 
			
		||||
    const float r = sinf(acosf(-vec[2]) * 0.5f);
 | 
			
		||||
    float uf, vf;
 | 
			
		||||
    int ui, vi;
 | 
			
		||||
 | 
			
		||||
    uf = (1.f - r * vec[0] / l) * width  / 2.f;
 | 
			
		||||
    vf = (1.f + r * vec[1] / l) * height / 2.f;
 | 
			
		||||
    ui = floorf(uf);
 | 
			
		||||
    vi = floorf(vf);
 | 
			
		||||
 | 
			
		||||
    *du = uf - ui;
 | 
			
		||||
    *dv = vf - vi;
 | 
			
		||||
 | 
			
		||||
    for (int i = -1; i < 3; i++) {
 | 
			
		||||
        for (int j = -1; j < 3; j++) {
 | 
			
		||||
            us[i + 1][j + 1] = mod(ui + j, width);
 | 
			
		||||
            vs[i + 1][j + 1] = av_clip(vi + i, 0, height - 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculate 3D coordinates on sphere for corresponding frame position in ball format.
 | 
			
		||||
 *
 | 
			
		||||
 * @param s filter 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 void ball_to_xyz(const V360Context *s,
 | 
			
		||||
                        int i, int j, int width, int height,
 | 
			
		||||
                        float *vec)
 | 
			
		||||
{
 | 
			
		||||
    const float x = (2.f * i) / width  - 1.f;
 | 
			
		||||
    const float y = (2.f * j) / height - 1.f;
 | 
			
		||||
    const float l = hypotf(x, y);
 | 
			
		||||
 | 
			
		||||
    if (l <= 1.f) {
 | 
			
		||||
        const float phi   = atan2f(x, y);
 | 
			
		||||
        const float theta = 2.f * asinf(l);
 | 
			
		||||
 | 
			
		||||
        const float sin_phi   = sinf(phi);
 | 
			
		||||
        const float cos_phi   = cosf(phi);
 | 
			
		||||
        const float sin_theta = sinf(theta);
 | 
			
		||||
        const float cos_theta = cosf(theta);
 | 
			
		||||
 | 
			
		||||
        vec[0] =  sin_theta * sin_phi;
 | 
			
		||||
        vec[1] = -sin_theta * cos_phi;
 | 
			
		||||
        vec[2] = -cos_theta;
 | 
			
		||||
    } else {
 | 
			
		||||
        vec[0] =  0.f;
 | 
			
		||||
        vec[1] = -1.f;
 | 
			
		||||
        vec[2] =  0.f;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Prepare data for processing equi-angular cubemap input format.
 | 
			
		||||
 *
 | 
			
		||||
@ -2429,6 +2505,12 @@ static int config_output(AVFilterLink *outlink)
 | 
			
		||||
        wf = w;
 | 
			
		||||
        hf = h;
 | 
			
		||||
        break;
 | 
			
		||||
    case BALL:
 | 
			
		||||
        s->in_transform = xyz_to_ball;
 | 
			
		||||
        err = 0;
 | 
			
		||||
        wf = w;
 | 
			
		||||
        hf = h / 2.f;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        av_log(ctx, AV_LOG_ERROR, "Specified input format is not handled.\n");
 | 
			
		||||
        return AVERROR_BUG;
 | 
			
		||||
@ -2499,6 +2581,12 @@ static int config_output(AVFilterLink *outlink)
 | 
			
		||||
        w = roundf(wf);
 | 
			
		||||
        h = roundf(hf);
 | 
			
		||||
        break;
 | 
			
		||||
    case BALL:
 | 
			
		||||
        s->out_transform = ball_to_xyz;
 | 
			
		||||
        prepare_out = NULL;
 | 
			
		||||
        w = roundf(wf);
 | 
			
		||||
        h = roundf(hf * 2.f);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        av_log(ctx, AV_LOG_ERROR, "Specified output format is not handled.\n");
 | 
			
		||||
        return AVERROR_BUG;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user