summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/video.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-10-01 16:07:51 +0200
committerwm4 <wm4@nowhere>2016-10-01 16:07:51 +0200
commit82231fd74d173fb47845dd086d360bceb3e5fc17 (patch)
tree8ed97d95f54c5d7c62e6d2f745ce9dfbe290ad0b /video/out/opengl/video.c
parent052584c9e2b87a69ef2359d88989a694910ac506 (diff)
downloadmpv-82231fd74d173fb47845dd086d360bceb3e5fc17.tar.bz2
mpv-82231fd74d173fb47845dd086d360bceb3e5fc17.tar.xz
vo_opengl: attempt to fix chroma offset under rotation and flipping
Other than being overly convoluted, this seems to make sense to me. Except that to get the "rot" transform I have to set flip=true, which makes no sense at all to me.
Diffstat (limited to 'video/out/opengl/video.c')
-rw-r--r--video/out/opengl/video.c63
1 files changed, 48 insertions, 15 deletions
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c
index 7d7641a1ea..c3b3660c78 100644
--- a/video/out/opengl/video.c
+++ b/video/out/opengl/video.c
@@ -728,11 +728,12 @@ static int pass_bind(struct gl_video *p, struct img_tex tex)
}
// Rotation by 90° and flipping.
-static void get_plane_source_transform(struct gl_video *p, struct texplane *t,
- struct gl_transform *out_tr)
+// w/h is used for recentering.
+static void get_transform(float w, float h, int rotate, bool flip,
+ struct gl_transform *out_tr)
{
struct gl_transform tr = identity_trans;
- int a = p->image_params.rotate % 90 ? 0 : p->image_params.rotate / 90;
+ int a = rotate % 90 ? 0 : rotate / 90;
int sin90[4] = {0, 1, 0, -1}; // just to avoid rounding issues etc.
int cos90[4] = {1, 0, -1, 0};
struct gl_transform rot = {{{cos90[a], sin90[a]}, {-sin90[a], cos90[a]}}};
@@ -741,17 +742,24 @@ static void get_plane_source_transform(struct gl_video *p, struct texplane *t,
// basically, recenter to keep the whole image in view
float b[2] = {1, 1};
gl_transform_vec(rot, &b[0], &b[1]);
- tr.t[0] += b[0] < 0 ? t->w : 0;
- tr.t[1] += b[1] < 0 ? t->h : 0;
+ tr.t[0] += b[0] < 0 ? w : 0;
+ tr.t[1] += b[1] < 0 ? h : 0;
- if (t->flipped) {
- struct gl_transform flip = {{{1, 0}, {0, -1}}, {0, t->h}};
- gl_transform_trans(flip, &tr);
+ if (flip) {
+ struct gl_transform fliptr = {{{1, 0}, {0, -1}}, {0, h}};
+ gl_transform_trans(fliptr, &tr);
}
*out_tr = tr;
}
+// Return the chroma plane upscaled to luma size, but with additional padding
+// for image sizes not aligned to subsampling.
+static int chroma_upsize(int size, int shift)
+{
+ return mp_chroma_div_up(size, shift) << shift;
+}
+
// Places a video_image's image textures + associated metadata into tex[]. The
// number of textures is equal to p->plane_count. Any necessary plane offsets
// are stored in off. (e.g. chroma position)
@@ -760,13 +768,13 @@ static void pass_get_img_tex(struct gl_video *p, struct video_image *vimg,
{
assert(vimg->mpi);
+ int w = p->image_params.w;
+ int h = p->image_params.h;
+
// Determine the chroma offset
float ls_w = 1.0 / (1 << p->image_desc.chroma_xs);
float ls_h = 1.0 / (1 << p->image_desc.chroma_ys);
- if (p->image_params.rotate % 180 == 90)
- MPSWAP(float, ls_w, ls_h);
-
struct gl_transform chroma = {{{ls_w, 0.0}, {0.0, ls_h}}};
if (p->image_params.chroma_location != MP_CHROMA_CENTER) {
@@ -781,8 +789,6 @@ static void pass_get_img_tex(struct gl_video *p, struct video_image *vimg,
chroma.t[1] = ls_h < 1 ? ls_h * -cy / 2 : 0;
}
- // FIXME: account for rotation in the chroma offset
-
// The existing code assumes we just have a single tex multiplier for
// all of the planes. This may change in the future
float tex_mul = 1.0 / mp_get_csp_mul(p->image_params.color.space,
@@ -819,11 +825,38 @@ static void pass_get_img_tex(struct gl_video *p, struct video_image *vimg,
.components = p->image_desc.components[n],
};
snprintf(tex[n].swizzle, sizeof(tex[n].swizzle), "%s", t->swizzle);
- get_plane_source_transform(p, t, &tex[n].transform);
+ get_transform(t->w, t->h, p->image_params.rotate, t->flipped,
+ &tex[n].transform);
if (p->image_params.rotate % 180 == 90)
MPSWAP(int, tex[n].w, tex[n].h);
- off[n] = type == PLANE_CHROMA ? chroma : identity_trans;
+ off[n] = identity_trans;
+
+ if (type == PLANE_CHROMA) {
+ struct gl_transform rot;
+ get_transform(0, 0, p->image_params.rotate, true, &rot);
+
+ struct gl_transform tr = chroma;
+ gl_transform_vec(rot, &tr.t[0], &tr.t[1]);
+
+ float dx = (chroma_upsize(w, p->image_desc.xs[n]) - w) * ls_w;
+ float dy = (chroma_upsize(h, p->image_desc.ys[n]) - h) * ls_h;
+
+ // Adjust the chroma offset if the real chroma size is fractional
+ // due image sizes not aligned to chroma subsampling.
+ struct gl_transform rot2;
+ get_transform(0, 0, p->image_params.rotate, t->flipped, &rot2);
+ if (rot2.m[0][0] < 0)
+ tr.t[0] += dx;
+ if (rot2.m[1][0] < 0)
+ tr.t[0] += dy;
+ if (rot2.m[0][1] < 0)
+ tr.t[1] += dx;
+ if (rot2.m[1][1] < 0)
+ tr.t[1] += dy;
+
+ off[n] = tr;
+ }
}
}