mirror of
https://github.com/mpv-player/mpv
synced 2024-12-17 20:34:58 +00:00
1e73da47da
If, for some reason, the subtitle renderer attempts to render a subtitle before SD_CTRL_SET_VIDEO_PARAMS was called, it passed a value calculated from invalid values. This can happen with --vf=sub and --start. The crash happens if 1. there was a subtitle packet that falls into the timestamp of the rendered video frame, 2. the playloop hasn't informed the subtitle decoder about the video resolution yet (normally unneeded, because that is used for weird corner cases only, so this code is a bit fuzzy), and 3. something actually requests a frame to be drawn from the subtitle renderer, like with vf_sub. The actual crash was due to passing NaN as pixel aspect to libass, which then created glyphs with ridiculous sizes, involving a few integer overflows and unchecked mallocs. The sd_lavc.c and sd_spu.c cases probably don't crash, but I'm not sure, and it's better fix them anyway. Not bothering with sd_spu.c, this crap is for compatibility and will be removed soon. Note that this would have been no problem, had the code checked whether SD_CTRL_SET_VIDEO_PARAMS was actually called. This commit adds such a check (although it basically checks after using the parameters). Regression since49caa0a7
and633fde4a
.
102 lines
2.5 KiB
C
102 lines
2.5 KiB
C
/*
|
|
* This file is part of mpv.
|
|
*
|
|
* mpv is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* mpv is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
|
|
#include "talloc.h"
|
|
#include "options/options.h"
|
|
#include "video/mp_image.h"
|
|
#include "sd.h"
|
|
#include "spudec.h"
|
|
|
|
struct sd_spu_priv {
|
|
void *spudec;
|
|
};
|
|
|
|
static bool is_dvd_sub(const char *t)
|
|
{
|
|
return t && (strcmp(t, "dvd_subtitle") == 0 ||
|
|
strcmp(t, "dvd_subtitle_mpg") == 0);
|
|
}
|
|
|
|
static bool supports_format(const char *format)
|
|
{
|
|
return is_dvd_sub(format);
|
|
}
|
|
|
|
static int init(struct sd *sd)
|
|
{
|
|
void *spudec = spudec_new_scaled(sd->log, sd->sub_video_w, sd->sub_video_h,
|
|
sd->extradata, sd->extradata_len);
|
|
if (!spudec)
|
|
return -1;
|
|
struct sd_spu_priv *priv = talloc_zero(NULL, struct sd_spu_priv);
|
|
priv->spudec = spudec;
|
|
sd->priv = priv;
|
|
return 0;
|
|
}
|
|
|
|
static void decode(struct sd *sd, struct demux_packet *packet)
|
|
{
|
|
struct sd_spu_priv *priv = sd->priv;
|
|
|
|
if (packet->pts < 0 || packet->len == 0)
|
|
return;
|
|
|
|
spudec_assemble(priv->spudec, packet->buffer, packet->len,
|
|
packet->pts * 90000);
|
|
}
|
|
|
|
static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
|
|
struct sub_bitmaps *res)
|
|
{
|
|
struct MPOpts *opts = sd->opts;
|
|
struct sd_spu_priv *priv = sd->priv;
|
|
|
|
spudec_set_forced_subs_only(priv->spudec, opts->forced_subs_only);
|
|
spudec_heartbeat(priv->spudec, pts * 90000);
|
|
|
|
if (spudec_visible(priv->spudec))
|
|
spudec_get_indexed(priv->spudec, &d, 1, 1, res);
|
|
}
|
|
|
|
static void reset(struct sd *sd)
|
|
{
|
|
struct sd_spu_priv *priv = sd->priv;
|
|
|
|
spudec_reset(priv->spudec);
|
|
}
|
|
|
|
static void uninit(struct sd *sd)
|
|
{
|
|
struct sd_spu_priv *priv = sd->priv;
|
|
|
|
spudec_free(priv->spudec);
|
|
talloc_free(priv);
|
|
}
|
|
|
|
const struct sd_functions sd_spu = {
|
|
.name = "spu",
|
|
.supports_format = supports_format,
|
|
.init = init,
|
|
.decode = decode,
|
|
.get_bitmaps = get_bitmaps,
|
|
.reset = reset,
|
|
.uninit = uninit,
|
|
};
|