Making OSD/subtitle bitmaps refcounted was planend a longer time ago,
e.g. the sub_bitmaps.packed field (which refcounts the subtitle bitmap
data) was added in 2016. But nothing benefited much from it, because
struct sub_bitmaps was usually stack allocated, and there was this weird
callback stuff through osd_draw().
Make it possible to get actually refcounted subtitle bitmaps on the OSD
API level. For this, we just copy all subtitle data other than the
bitmaps with sub_bitmaps_copy(). At first, I had planned some fancy
refcount shit, but when that was a big mess and hard to debug and just
boiled to emulating malloc(), I made it a full allocation+copy. This
affects mostly the parts array. With crazy ASS subtitles, this parts
array can get pretty big (thousands of elements or more), in which case
the extra alloc/copy could become performance relevant. But then again
this is just pure bullshit, and I see no need to care. In practice, this
extra work most likely gets drowned out by libass murdering a single
core (while mpv is waiting for it) anyway. So fuck it.
I just wanted this so draw_bmp.c requires only a single call to render
everything. VOs also can benefit from this, because the weird callback
shit isn't necessary anymore (simpler code), but I haven't done anything
about it yet. In general I'd hope this will work towards simplifying the
OSD layer, which is prerequisite for making actual further improvements.
I haven't tested some cases such as the "overlay-add" command. Maybe it
crashes now? Who knows, who cares.
In addition, it might be worthwhile to reduce the code duplication
between all the things that output subtitle bitmaps (with repacking,
image allocation, etc.), but that's orthogonal.
This is more or less a minimal hack to make _some_ text measurement
functionality available to scripts. Since libass does not support such a
thing, this simply uses the bounding box of the rendered text.
This is far from ideal. Problems include:
- using a bitmap bounding box
- additional memory waste and/or flushing caches
- dependency on window size
- odd small deviations with different window sizes (run osd-test.lua and
resize the window after each timer update; the bounding boxes aren't
adjusted in an overly useful way)
- inability to query the size _after_ actual rendering
But I guess it's a start. Since I'm aware that it's crap, add a threat
to the manpage that this may be changed/removed again. For now, I'm
interested whether anyone will have use for it in its current form, as
it's an often requested feature.
Sometimes the atlas can get so large that it exceeds the maximum allowed
size for an mp_image. Since the atlas will never shrink naturally, this
breaks subtitles entirely until mpv is restarted. Reset the packer so
that subtitles can rendered properly once the atlas fits again.
This is a partial workaround for #6286.
libass had an API to configure this since 2013. mpv always used
ASS_FONTPROVIDER_AUTODETECT, because usually there's little reason to
use anything else. The intention of the now added option is to allow
users to disable use of system fonts.
I didn't consider it worth the trouble to add the coretext and
directwrite enum items from ASS_DefaultFontProvider. The "auto" choice
will have the same effect if they're available. Also, the part of the
code which defines the option does not necessarily have libass available
(it's still optional!), so defining all enum items as choices is icky. I
still added fontconfig, since that may be nice to emulate a nostalgic
2010 feeling of mpv freezing on fontconfig.
The option for OSD is even less useful. (But you get it for free, and
why pass up a chance to add yet another useless option?)
This is not quite what was requested in #6947, but as close as it gets.
Remove them from the big MPOpts struct and move them to their sub
structs. In the places where their fields are used, create a private
copy of the structs, instead of accessing the semi-deprecated global
option struct instance (mpv_global.opts) directly.
This actually makes accessing these options finally thread-safe. They
weren't even if they should have for years. (Including some potential
for undefined behavior when e.g. the OSD font was changed at runtime.)
This is mostly transparent. All options get moved around, but most users
of the options just need to access a different struct (changing sd.opts
to a different type changes a lot of uses, for example).
One thing which has to be considered and could cause potential
regressions is that the new option copies must be explicitly updated.
sub_update_opts() takes care of this for example.
Another thing is that writing to the option structs manually won't work,
because the changes won't be propagated to other copies. Apparently the
only affected case is the implementation of the sub-step command, which
tries to change sub_delay. Handle this one explicitly (osd_changed()
doesn't need to be called anymore, because changing the option triggers
UPDATE_OSD, and updates the OSD as a consequence). The way the option
value is propagated is rather hacky, but for now this will do.
I've decided that MP_TRACE means “noisy spam per frame”, whereas
MP_DBG just means “more verbose debugging messages than MSGL_V”.
Basically, MSGL_DBG shouldn't create spam per frame like it currently
does, and MSGL_V should make sense to the end-user and provide mostly
additional informational output.
MP_DBG is basically what I want to make the new default for --log-file,
so the cut-off point for MP_DBG is if we probably want to know if for
debugging purposes but the user most likely doesn't care about on the
terminal.
Also, the debug callbacks for libass and ffmpeg got bumped in their
verbosity levels slightly, because being external components they're a
bit less relevant to mpv debugging, and a bit too over-eager in what
they consider to be relevant information.
I exclusively used the "try it on my machine and remove messages from
MSGL_* until it does what I want it to" approach of refactoring, so
YMMV.
Somewhat chaostic history: libass/ass_mp.* -> ass_mp.* -> sub/ass_mp.*
As far as I can tell, everyone who ever touched these files has agreed
to the relicensing.
When the format of the subtitle bitmaps changes, such as with taking
screenshots with vo_vaapi (RGBA for the VO vs. Y8 for screenshots), the
cache image obviously needs to be recreated.
Fixes#4325.
To make it easier for the eyes, multi line subtitles should
be left justified (for most languages).
This adds an option to define how subtitles are to be justified
inpendently of how they are aligned.
Also add option to enable --sub-justify to be applied on ASS subtitles.
This affects VOs (or other code which render OSD) which does not support
the LIBASS format, but only RGBA. Instead of having a converter stage in
osd.c, make mp_ass_packer_pack() output directly in RGBA.
In general, this is work towards refcounted subtitle images.
Although we could keep the "converter" design, doing it this way seems
simpler, at least considering the current situation with only 2 OSD
formats. It also prevents copying & packing the data twice, which will
lead to better performance. (Although I guess this case is not important
at all.)
It also fixes --force-rgba-osd-rendering when used with vo_opengl,
vo_vdpau, and vo_direct3d.
Change all producer of libass images to packing the bitmaps into a
single larger bitmap directly when they're output. This is supposed to
help working towards refcounted sub bitmaps.
This will reduce performance for VOs like vo_xv, but not for vo_opengl.
vo_opengl simply will pick up the pre-packed sub bitmaps, and skip
packing them again. vo_xv will copy and pack the sub bitmaps
unnecessarily - but if we want sub bitmap refcounting, they'd have to be
copied anyway.
The packing code cannot be removed yet from vo_opengl, because there are
certain corner cases that still produce unpackad other sub bitmaps.
Actual refcounting will also require more work.
Instead of passing an explicit cache to the function, the res parameter
is used. Also, instead of replacing its contents, sub bitmaps are now
appended to it (all assuming the format doesn't actually change).
This is preparation for the following commits.
Commit 2b07d3eb merged progbar and OSD text renderer into one ASS_Track,
but it confused the styles. Specifically, if both progbar and OSD are
visible, the create_ass_track() call made by the progbar code will reset
the style adjusted by the OSD text code.
Change create_ass_track() not to add any styles. Instead let the caller
manage the styles. They are now referenced by name, and lazily added if
they don't exist yet. This is also much cleaner.
There was a somewhat obscure optimization in the OSD and subtitle
rendering path: if only the position of the sub-images changed, and not
the actual image data, uploading of the image data could be skipped. In
theory, this could speed up things like scrolling subtitles.
But it turns out that even in the rare cases subtitles have such scrolls
or axis-aligned movement, modern libass rarely signals this kind of
change. Possibly this is because of sub-pixel handling and such, which
break this.
As such, it's a worthless optimization and just introduces additional
complexity and subtle bugs (especially in cases libass does the
opposite: incorrectly signaling a position change only, which happened
before). Remove this optimization, and rename bitmap_pos_id to
change_id.
Update options like --sub-text-margin-y at runtime. These are somewhat
of a problem, because ass_set_selective_style_override() (intentionally)
does not override them. This should be fixed in libass (by providing
additional override modes), but for now this will do.
Also change the signature of mp_ass_configure(), so we can get access to
the track.
Additionally, drop the redundant setting of the style Alignment (it's
overwritten by mp_ass_set_style()).
See #1622 (again).
Basically abuse the style override mechanism meant for ASS
(mp_ass_set_style()) to update text subtitle styling at runtime too.
This even has the advantage that the style will be overridden, even if
the text subtitle converted (like sd_lavc_conv.c) dares to add a fixed
style in the styles section.
Probably helps with #1622.
Now --ass-use-margins doesn't apply to normal subtitles anymore. This is
probably the inverse from the mpv behavior users expected so far, and
thus a breaking change, so rename the option, that the user at least has
a chance to lookup the option and decide whether the new behavior is
wanted or not.
The basic idea here is:
- plain text subtitles should have a certain useful defalt behavior,
like actually using margins
- ASS subtitles should never be broken by default
- ASS subtitles should look and behave like plaintext subtitles if
the --ass-style-override=force option is used
This also subtly changes --sub-scale-with-window and adds the --ass-
scale-with-window option. Since this one isn't so important, don't
bother with compatibility.
You can set in which "corner" the OSD and subtitles are shown. I'd
prefer it a bit more general (so you could set the alignment using
a factor), but the libass API does not provide this.
--sub-scale-by-window=no attempts to keep subs always at the same pixel
size.
The implementation is a bit all over the place, because it compensates
already done scaling by an inverse scale factor, but it will probably do
its job.
Fixes#1424. (The semantics and name of --sub-scale-with-window are
kept, and this adds a new option - the name is confusingly similar, but
it's actually analogue to --osd-scale-by-window.)
Now requires newest libass git. Since this feature wasn't part of a
libass release yet, I'm not bothering making the mpv code compatible
with as how it was previously implemented (it will just be disabled
with any older libass).
CC: @mpv-player/stable (because mpv-build uses libass git, and this
breaks the feature)
Search $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS for config files.
This also negates the need to have separate user and global variants of
mp_find_config_file()
Closes#864, #109.
Signed-off-by: wm4 <wm4@nowhere>
While I'm not very fond of "const", it's important for declarations
(it decides whether a symbol is emitted in a read-only or read/write
section). Fix all these cases, so we have writeable global data only
when we really need.
(The old "force" choice of that option is renamed to "force-default".)
This allows overriding native ASS script subtitle styles with the style
provided by the --sub-text-* options (like --sub-text-font etc.). This
is disabled by default, and needs to be explicitly enabled with the
--ass-style-override=force option and input property.
This uses in fact exactly the same options (--sub-text-*) and semantics
as the ones used to configure unstyled text subtitles.
It's recommended to combine this with this in the mpv config file:
ass-force-style="ScaledBorderAndShadow=1" # work around dumb libass behavior
Also, adding a key binding to toggle this behavior should be added,
because overriding can easily break:
L cycle ass-style-override
This would cycle override behavior on Shift+L and allows quickly
disabling/enabling style overrides.
Note: ASS should be considered a vector format rather than a subtitle
format. There is no easy or reliable way to determine whether the style
of a given subtitle event can be changed without destroying visuals or
not. This patch relies on a simple heuristic, which often works and
often breaks.
The --ass-styles option is implemented by calling ass_read_styles().
This function can take a codepage (so libass will use iconv to convert
it). This was implemented before our --subcp option was changed, and
this code was not updated. Now libass fails opening iconv, because
--subcp is not always (and not by default) a valid iconv codepage.
Just always pass NULL, which means the file passed to --ass-styles must
be in UTF-8. The --ass-styles option is a fringe option anyway (and will
destroy your subtitles), so having codepage support for it isn't
important at all.
There's a single mp_msg() in path.c, but all path lookup functions seem
to depend on it, so we get a rat-tail of stuff we have to change. This
is probably a good thing though, because we can have the path lookup
functions also access options, so we could allow overriding the default
config path, or ignore the MPV_HOME environment variable, and such
things.
Also take the chance to consistently add talloc_ctx parameters to the
path lookup functions.
Also, this change causes a big mess on configfiles.c. It's the same
issue: everything suddenly needs a (different) context argument. Make it
less wild by providing a mp_load_auto_profiles() function, which
isolates most of it to configfiles.c.
Since m_option.h and options.h are extremely often included, a lot of
files have to be changed.
Moving path.c/h to options/ is a bit questionable, but since this is
mainly about access to config files (which are also handled in
options/), it's probably ok.
The OSD style settings depend on the PlayRes, simply because all style
values are implicitly scaled by the PlayResY in libass. Also, the OSC
changes the PlayResY in certain situations, so something could go wrong.
But not sure if this actually matters in practice.
This simplifies things, although it is slightly less efficient (probably
uses a bit more memory).
This also happens to fix that the OSC dropped the libass cache on every
frame.
This is pretty much a hack for the OSC. It will allow it to rely on a
somewhat predictable style, instead of having to overwrite all user
OSD settings manually with override tags.