mirror of
https://github.com/mpv-player/mpv
synced 2025-03-11 08:37:59 +00:00
vo_gpu_next: don't crash on negative plane strides
This is an annoying special case only really needed because of the `vflip` filter. mpv handles this by directly adjusting the plane transform. The libplacebo API, unfortunately, does not allow passing the required information for this to work smoothly. Long-term I plan on adding support for plane flipping in libplacebo directly, but for the meantime, we will have to work-around it by moving the flipping to the whole-image `crop` instead. Not an ideal solution but better than crashing. Fixes #9855
This commit is contained in:
parent
4629fe577f
commit
ef83498aef
@ -481,17 +481,36 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src
|
||||
|
||||
enum pl_chroma_location chroma = mp_chroma_to_pl(par->chroma_location);
|
||||
int planes = plane_data_from_imgfmt(data, &frame->repr.bits, mpi->imgfmt);
|
||||
bool img_vflipped = false;
|
||||
for (int n = 0; n < planes; n++) {
|
||||
data[n].width = mp_image_plane_w(mpi, n);
|
||||
data[n].height = mp_image_plane_h(mpi, n);
|
||||
data[n].row_stride = mpi->stride[n];
|
||||
data[n].pixels = mpi->planes[n];
|
||||
bool vflipped = mpi->stride[n] < 0;
|
||||
if (vflipped) {
|
||||
int h = mp_image_plane_h(mpi, n);
|
||||
data[n].pixels = mpi->planes[n] + (h - 1) * mpi->stride[n];
|
||||
data[n].row_stride = -mpi->stride[n];
|
||||
} else {
|
||||
data[n].pixels = mpi->planes[n];
|
||||
data[n].row_stride = mpi->stride[n];
|
||||
}
|
||||
|
||||
// libplacebo can't deal with images that have partially flipped
|
||||
// textures. We could work around this by blitting them to fresh
|
||||
// (unflipped) textures, but it's an unlikely enough case to warrant
|
||||
// just erroring out instead. (Usually, all planes will be flipped or
|
||||
// unflipped simultaneously, e.g. by the `vflip` filter)
|
||||
if (n > 0 && img_vflipped != vflipped) {
|
||||
MP_ERR(vo, "Inconsistently flipped planes!\n");
|
||||
return false;
|
||||
}
|
||||
img_vflipped = vflipped;
|
||||
|
||||
pl_buf buf = get_dr_buf(mpi);
|
||||
if (buf) {
|
||||
data[n].pixels = NULL;
|
||||
data[n].buf = buf;
|
||||
data[n].buf_offset = mpi->planes[n] - buf->data;
|
||||
data[n].buf_offset = (uint8_t *) data[n].pixels - buf->data;
|
||||
data[n].pixels = NULL;
|
||||
} else if (gpu->limits.callbacks) {
|
||||
data[n].callback = talloc_free;
|
||||
data[n].priv = mp_image_new_ref(mpi);
|
||||
@ -504,8 +523,11 @@ static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mpi->fmt.xs[n] || mpi->fmt.ys[n])
|
||||
if (mpi->fmt.xs[n] || mpi->fmt.ys[n]) {
|
||||
pl_chroma_location_offset(chroma, &plane->shift_x, &plane->shift_y);
|
||||
if (vflipped)
|
||||
plane->shift_y = -plane->shift_y;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PL_HAVE_LAV_DOLBY_VISION
|
||||
@ -668,6 +690,13 @@ static void apply_crop(struct pl_frame *frame, struct mp_rect crop,
|
||||
frame->crop.y0 = height - frame->crop.y0;
|
||||
frame->crop.y1 = height - frame->crop.y1;
|
||||
}
|
||||
|
||||
struct mp_image *mpi = frame->user_data;
|
||||
if (mpi && mpi->stride[0] < 0) {
|
||||
// Adjust for vertically flipped planes
|
||||
frame->crop.y0 = height - frame->crop.y0;
|
||||
frame->crop.y1 = height - frame->crop.y1;
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_frame(struct vo *vo, struct vo_frame *frame)
|
||||
|
Loading…
Reference in New Issue
Block a user