mpv/sub/draw_bmp.c

1036 lines
34 KiB
C
Raw Normal View History

/*
* This file is part of mpv.
*
Relicense some non-MPlayer source files to LGPL 2.1 or later This covers source files which were added in mplayer2 and mpv times only, and where all code is covered by LGPL relicensing agreements. There are probably more files to which this applies, but I'm being conservative here. A file named ao_sdl.c exists in MPlayer too, but the mpv one is a complete rewrite, and was added some time after the original ao_sdl.c was removed. The same applies to vo_sdl.c, for which the SDL2 API is radically different in addition (MPlayer supports SDL 1.2 only). common.c contains only code written by me. But common.h is a strange case: although it originally was named mp_common.h and exists in MPlayer too, by now it contains only definitions written by uau and me. The exceptions are the CONTROL_ defines - thus not changing the license of common.h yet. codec_tags.c contained once large tables generated from MPlayer's codecs.conf, but all of these tables were removed. From demux_playlist.c I'm removing a code fragment from someone who was not asked; this probably could be done later (see commit 15dccc37). misc.c is a bit complicated to reason about (it was split off mplayer.c and thus contains random functions out of this file), but actually all functions have been added post-MPlayer. Except get_relative_time(), which was written by uau, but looks similar to 3 different versions of something similar in each of the Unix/win32/OSX timer source files. I'm not sure what that means in regards to copyright, so I've just moved it into another still-GPL source file for now. screenshot.c once had some minor parts of MPlayer's vf_screenshot.c, but they're all gone.
2016-01-19 17:36:06 +00:00
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
Relicense some non-MPlayer source files to LGPL 2.1 or later This covers source files which were added in mplayer2 and mpv times only, and where all code is covered by LGPL relicensing agreements. There are probably more files to which this applies, but I'm being conservative here. A file named ao_sdl.c exists in MPlayer too, but the mpv one is a complete rewrite, and was added some time after the original ao_sdl.c was removed. The same applies to vo_sdl.c, for which the SDL2 API is radically different in addition (MPlayer supports SDL 1.2 only). common.c contains only code written by me. But common.h is a strange case: although it originally was named mp_common.h and exists in MPlayer too, by now it contains only definitions written by uau and me. The exceptions are the CONTROL_ defines - thus not changing the license of common.h yet. codec_tags.c contained once large tables generated from MPlayer's codecs.conf, but all of these tables were removed. From demux_playlist.c I'm removing a code fragment from someone who was not asked; this probably could be done later (see commit 15dccc37). misc.c is a bit complicated to reason about (it was split off mplayer.c and thus contains random functions out of this file), but actually all functions have been added post-MPlayer. Except get_relative_time(), which was written by uau, but looks similar to 3 different versions of something similar in each of the Unix/win32/OSX timer source files. I'm not sure what that means in regards to copyright, so I've just moved it into another still-GPL source file for now. screenshot.c once had some minor parts of MPlayer's vf_screenshot.c, but they're all gone.
2016-01-19 17:36:06 +00:00
* GNU Lesser General Public License for more details.
*
Relicense some non-MPlayer source files to LGPL 2.1 or later This covers source files which were added in mplayer2 and mpv times only, and where all code is covered by LGPL relicensing agreements. There are probably more files to which this applies, but I'm being conservative here. A file named ao_sdl.c exists in MPlayer too, but the mpv one is a complete rewrite, and was added some time after the original ao_sdl.c was removed. The same applies to vo_sdl.c, for which the SDL2 API is radically different in addition (MPlayer supports SDL 1.2 only). common.c contains only code written by me. But common.h is a strange case: although it originally was named mp_common.h and exists in MPlayer too, by now it contains only definitions written by uau and me. The exceptions are the CONTROL_ defines - thus not changing the license of common.h yet. codec_tags.c contained once large tables generated from MPlayer's codecs.conf, but all of these tables were removed. From demux_playlist.c I'm removing a code fragment from someone who was not asked; this probably could be done later (see commit 15dccc37). misc.c is a bit complicated to reason about (it was split off mplayer.c and thus contains random functions out of this file), but actually all functions have been added post-MPlayer. Except get_relative_time(), which was written by uau, but looks similar to 3 different versions of something similar in each of the Unix/win32/OSX timer source files. I'm not sure what that means in regards to copyright, so I've just moved it into another still-GPL source file for now. screenshot.c once had some minor parts of MPlayer's vf_screenshot.c, but they're all gone.
2016-01-19 17:36:06 +00:00
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <stdbool.h>
#include <assert.h>
#include <math.h>
#include <inttypes.h>
#include "common/common.h"
#include "draw_bmp.h"
#include "img_convert.h"
#include "video/mp_image.h"
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
#include "video/repack.h"
#include "video/sws_utils.h"
#include "video/img_format.h"
#include "video/csputils.h"
const bool mp_draw_sub_formats[SUBBITMAP_COUNT] = {
[SUBBITMAP_LIBASS] = true,
[SUBBITMAP_BGRA] = true,
};
struct part {
int change_id;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
// Sub-bitmaps scaled to final sizes.
int num_imgs;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
struct mp_image **imgs;
};
// Must be a power of 2. Height is 1, but mark_rect() effectively operates on
// multiples of chroma sized macro-pixels. (E.g. 4:2:0 -> every second line is
// the same as the previous one, and x0%2==x1%2==0.)
#define SLICE_W 256u
// Whether to scale in tiles. Faster, but can't use correct chroma position.
// Should be a runtime option. SLICE_W is used as tile width. The tile size
// should probably be small; too small or too big will cause overhead when
// scaling.
#define SCALE_IN_TILES 1
#define TILE_H 4u
struct slice {
uint16_t x0, x1;
};
struct mp_draw_sub_cache
{
struct mpv_global *global;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
// Possibly cached parts. Also implies what's in the video_overlay.
struct part parts[MAX_OSD_PARTS];
int64_t change_id;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
struct mp_image_params params; // target image params
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
int w, h; // like params.w/h, but rounded up to chroma
unsigned align_x, align_y; // alignment for all video pixels
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
struct mp_image *rgba_overlay; // all OSD in RGBA
struct mp_image *video_overlay; // rgba_overlay converted to video colorspace
struct mp_image *alpha_overlay; // alpha plane ref. to video_overlay
struct mp_image *calpha_overlay; // alpha_overlay scaled to chroma plane size
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
unsigned s_w; // number of slices per line
struct slice *slices; // slices[y * s_w + x / SLICE_W]
bool any_osd;
struct mp_sws_context *rgba_to_overlay; // scaler for rgba -> video csp.
struct mp_sws_context *alpha_to_calpha; // scaler for overlay -> calpha
bool scale_in_tiles;
struct mp_sws_context *sub_scale; // scaler for SUBBITMAP_BGRA
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
struct mp_repack *overlay_to_f32; // convert video_overlay to float
struct mp_image *overlay_tmp; // slice in float32
struct mp_repack *calpha_to_f32; // convert video_overlay to float
struct mp_image *calpha_tmp; // slice in float32
struct mp_repack *video_to_f32; // convert video to float
struct mp_repack *video_from_f32; // convert float back to video
struct mp_image *video_tmp; // slice in float32
struct mp_sws_context *premul; // video -> premultiplied video
struct mp_sws_context *unpremul; // reverse
struct mp_image *premul_tmp;
// Function that works on the _f32 data.
void (*blend_line)(void *dst, void *src, void *src_a, int w);
struct mp_image res_overlay; // returned by mp_draw_sub_overlay()
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
};
static void blend_line_f32(void *dst, void *src, void *src_a, int w)
{
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
float *dst_f = dst;
float *src_f = src;
float *src_a_f = src_a;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
for (int x = 0; x < w; x++)
dst_f[x] = src_f[x] + dst_f[x] * (1.0f - src_a_f[x]);
}
static void blend_line_u8(void *dst, void *src, void *src_a, int w)
{
uint8_t *dst_i = dst;
uint8_t *src_i = src;
uint8_t *src_a_i = src_a;
for (int x = 0; x < w; x++)
dst_i[x] = src_i[x] + dst_i[x] * (255u - src_a_i[x]) / 255u;
}
static void blend_slice(struct mp_draw_sub_cache *p)
{
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
struct mp_image *ov = p->overlay_tmp;
struct mp_image *ca = p->calpha_tmp;
struct mp_image *vid = p->video_tmp;
for (int plane = 0; plane < vid->num_planes; plane++) {
int xs = vid->fmt.xs[plane];
int ys = vid->fmt.ys[plane];
int h = (1 << vid->fmt.chroma_ys) - (1 << ys) + 1;
int cw = mp_chroma_div_up(vid->w, xs);
for (int y = 0; y < h; y++) {
p->blend_line(mp_image_pixel_ptr_ny(vid, plane, 0, y),
mp_image_pixel_ptr_ny(ov, plane, 0, y),
xs || ys ? mp_image_pixel_ptr_ny(ca, 0, 0, y)
: mp_image_pixel_ptr_ny(ov, ov->num_planes - 1, 0, y),
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
cw);
}
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
static bool blend_overlay_with_video(struct mp_draw_sub_cache *p,
struct mp_image *dst)
{
if (!repack_config_buffers(p->video_to_f32, 0, p->video_tmp, 0, dst, NULL))
return false;
if (!repack_config_buffers(p->video_from_f32, 0, dst, 0, p->video_tmp, NULL))
return false;
int xs = dst->fmt.chroma_xs;
int ys = dst->fmt.chroma_ys;
for (int y = 0; y < dst->h; y += p->align_y) {
struct slice *line = &p->slices[y * p->s_w];
for (int sx = 0; sx < p->s_w; sx++) {
struct slice *s = &line[sx];
int w = s->x1 - s->x0;
if (w <= 0)
continue;
int x = sx * SLICE_W + s->x0;
assert(MP_IS_ALIGNED(x, p->align_x));
assert(MP_IS_ALIGNED(w, p->align_x));
assert(x + w <= p->w);
repack_line(p->overlay_to_f32, 0, 0, x, y, w);
repack_line(p->video_to_f32, 0, 0, x, y, w);
if (p->calpha_to_f32)
repack_line(p->calpha_to_f32, 0, 0, x >> xs, y >> ys, w >> xs);
blend_slice(p);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
repack_line(p->video_from_f32, x, y, 0, 0, w);
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
return true;
}
static bool convert_overlay_part(struct mp_draw_sub_cache *p,
int x0, int y0, int w, int h)
{
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
struct mp_image src = *p->rgba_overlay;
struct mp_image dst = *p->video_overlay;
mp_image_crop(&src, x0, y0, x0 + w, y0 + h);
mp_image_crop(&dst, x0, y0, x0 + w, y0 + h);
if (mp_sws_scale(p->rgba_to_overlay, &dst, &src) < 0)
return false;
if (p->calpha_overlay) {
src = *p->alpha_overlay;
dst = *p->calpha_overlay;
int xs = p->video_overlay->fmt.chroma_xs;
int ys = p->video_overlay->fmt.chroma_ys;
mp_image_crop(&src, x0, y0, x0 + w, y0 + h);
mp_image_crop(&dst, x0 >> xs, y0 >> ys, (x0 + w) >> xs, (y0 + h) >> ys);
if (mp_sws_scale(p->alpha_to_calpha, &dst, &src) < 0)
return false;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
return true;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
static bool convert_to_video_overlay(struct mp_draw_sub_cache *p)
{
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (!p->video_overlay)
return true;
if (p->scale_in_tiles) {
int t_h = p->rgba_overlay->h / TILE_H;
for (int ty = 0; ty < t_h; ty++) {
for (int sx = 0; sx < p->s_w; sx++) {
struct slice *s = &p->slices[ty * TILE_H * p->s_w + sx];
bool pixels_set = false;
for (int y = 0; y < TILE_H; y++) {
if (s[0].x0 < s[0].x1) {
pixels_set = true;
break;
}
s += p->s_w;
}
if (!pixels_set)
continue;
if (!convert_overlay_part(p, sx * SLICE_W, ty * TILE_H,
SLICE_W, TILE_H))
return false;
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
} else {
if (!convert_overlay_part(p, 0, 0, p->rgba_overlay->w, p->rgba_overlay->h))
return false;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
return true;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
// Mark the given rectangle of pixels as possibly non-transparent.
// The rectangle must have been pre-clipped.
static void mark_rect(struct mp_draw_sub_cache *p, int x0, int y0, int x1, int y1)
{
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
x0 = MP_ALIGN_DOWN(x0, p->align_x);
y0 = MP_ALIGN_DOWN(y0, p->align_y);
x1 = MP_ALIGN_UP(x1, p->align_x);
y1 = MP_ALIGN_UP(y1, p->align_y);
assert(x0 >= 0 && x0 <= x1 && x1 <= p->w);
assert(y0 >= 0 && y0 <= y1 && y1 <= p->h);
const int sx0 = x0 / SLICE_W;
const int sx1 = MPMIN(x1 / SLICE_W, p->s_w - 1);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
for (int y = y0; y < y1; y++) {
struct slice *line = &p->slices[y * p->s_w];
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
struct slice *s0 = &line[sx0];
struct slice *s1 = &line[sx1];
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
s0->x0 = MPMIN(s0->x0, x0 % SLICE_W);
s1->x1 = MPMAX(s1->x1, ((x1 - 1) % SLICE_W) + 1);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (s0 != s1) {
s0->x1 = SLICE_W;
s1->x0 = 0;
for (int x = sx0 + 1; x < sx1; x++) {
struct slice *s = &line[x];
s->x0 = 0;
s->x1 = SLICE_W;
}
}
// Ensure the very last slice does not extend
// beyond the total width.
struct slice *last_s = &line[p->s_w - 1];
last_s->x1 = MPMIN(p->w - ((p->s_w - 1) * SLICE_W), last_s->x1);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->any_osd = true;
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
static void draw_ass_rgba(uint8_t *dst, ptrdiff_t dst_stride,
uint8_t *src, ptrdiff_t src_stride,
int w, int h, uint32_t color)
{
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
const unsigned int r = (color >> 24) & 0xff;
const unsigned int g = (color >> 16) & 0xff;
const unsigned int b = (color >> 8) & 0xff;
const unsigned int a = 0xff - (color & 0xff);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
for (int y = 0; y < h; y++) {
uint32_t *dstrow = (uint32_t *) dst;
for (int x = 0; x < w; x++) {
const unsigned int v = src[x];
unsigned int aa = a * v;
uint32_t dstpix = dstrow[x];
unsigned int dstb = dstpix & 0xFF;
unsigned int dstg = (dstpix >> 8) & 0xFF;
unsigned int dstr = (dstpix >> 16) & 0xFF;
unsigned int dsta = (dstpix >> 24) & 0xFF;
dstb = (v * b * a + dstb * (255 * 255 - aa)) / (255 * 255);
dstg = (v * g * a + dstg * (255 * 255 - aa)) / (255 * 255);
dstr = (v * r * a + dstr * (255 * 255 - aa)) / (255 * 255);
dsta = (aa * 255 + dsta * (255 * 255 - aa)) / (255 * 255);
dstrow[x] = dstb | (dstg << 8) | (dstr << 16) | (dsta << 24);
}
dst += dst_stride;
src += src_stride;
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
static void render_ass(struct mp_draw_sub_cache *p, struct sub_bitmaps *sb)
{
assert(sb->format == SUBBITMAP_LIBASS);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
for (int i = 0; i < sb->num_parts; i++) {
struct sub_bitmap *s = &sb->parts[i];
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
draw_ass_rgba(mp_image_pixel_ptr(p->rgba_overlay, 0, s->x, s->y),
p->rgba_overlay->stride[0], s->bitmap, s->stride,
s->w, s->h, s->libass.color);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
mark_rect(p, s->x, s->y, s->x + s->w, s->y + s->h);
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
static void draw_rgba(uint8_t *dst, ptrdiff_t dst_stride,
uint8_t *src, ptrdiff_t src_stride, int w, int h)
{
for (int y = 0; y < h; y++) {
uint32_t *srcrow = (uint32_t *)src;
uint32_t *dstrow = (uint32_t *)dst;
for (int x = 0; x < w; x++) {
uint32_t srcpix = srcrow[x];
uint32_t dstpix = dstrow[x];
unsigned int srcb = srcpix & 0xFF;
unsigned int srcg = (srcpix >> 8) & 0xFF;
unsigned int srcr = (srcpix >> 16) & 0xFF;
unsigned int srca = (srcpix >> 24) & 0xFF;
unsigned int dstb = dstpix & 0xFF;
unsigned int dstg = (dstpix >> 8) & 0xFF;
unsigned int dstr = (dstpix >> 16) & 0xFF;
unsigned int dsta = (dstpix >> 24) & 0xFF;
dstb = srcb + dstb * (255 * 255 - srca) / (255 * 255);
dstg = srcg + dstg * (255 * 255 - srca) / (255 * 255);
dstr = srcr + dstr * (255 * 255 - srca) / (255 * 255);
dsta = srca + dsta * (255 * 255 - srca) / (255 * 255);
dstrow[x] = dstb | (dstg << 8) | (dstr << 16) | (dsta << 24);
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
dst += dst_stride;
src += src_stride;
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
static bool render_rgba(struct mp_draw_sub_cache *p, struct part *part,
struct sub_bitmaps *sb)
{
assert(sb->format == SUBBITMAP_BGRA);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (part->change_id != sb->change_id) {
for (int n = 0; n < part->num_imgs; n++)
talloc_free(part->imgs[n]);
part->num_imgs = sb->num_parts;
MP_TARRAY_GROW(p, part->imgs, part->num_imgs);
for (int n = 0; n < part->num_imgs; n++)
part->imgs[n] = NULL;
part->change_id = sb->change_id;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
for (int i = 0; i < sb->num_parts; i++) {
struct sub_bitmap *s = &sb->parts[i];
// Clipping is rare but necessary.
int sx0 = s->x;
int sy0 = s->y;
int sx1 = s->x + s->dw;
int sy1 = s->y + s->dh;
int x0 = MPCLAMP(sx0, 0, p->w);
int y0 = MPCLAMP(sy0, 0, p->h);
int x1 = MPCLAMP(sx1, 0, p->w);
int y1 = MPCLAMP(sy1, 0, p->h);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
int dw = x1 - x0;
int dh = y1 - y0;
if (dw <= 0 || dh <= 0)
continue;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
// We clip the source instead of the scaled image, because that might
// avoid excessive memory usage when applying a ridiculous scale factor,
// even if that stretches it to up to 1 pixel due to integer rounding.
int sx = 0;
int sy = 0;
int sw = s->w;
int sh = s->h;
if (x0 != sx0 || y0 != sy0 || x1 != sx1 || y1 != sy1) {
double fx = s->dw / (double)s->w;
double fy = s->dh / (double)s->h;
sx = MPCLAMP((x0 - sx0) / fx, 0, s->w);
sy = MPCLAMP((y0 - sy0) / fy, 0, s->h);
sw = MPCLAMP(dw / fx, 1, s->w);
sh = MPCLAMP(dh / fy, 1, s->h);
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
assert(sx >= 0 && sw > 0 && sx + sw <= s->w);
assert(sy >= 0 && sh > 0 && sy + sh <= s->h);
ptrdiff_t s_stride = s->stride;
void *s_ptr = (char *)s->bitmap + s_stride * sy + sx * 4;
if (dw != sw || dh != sh) {
struct mp_image *scaled = part->imgs[i];
if (!scaled) {
struct mp_image src_img = {0};
mp_image_setfmt(&src_img, IMGFMT_BGRA);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
mp_image_set_size(&src_img, sw, sh);
src_img.planes[0] = s_ptr;
src_img.stride[0] = s_stride;
src_img.params.alpha = MP_ALPHA_PREMUL;
scaled = mp_image_alloc(IMGFMT_BGRA, dw, dh);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (!scaled)
return false;
part->imgs[i] = talloc_steal(p, scaled);
mp_image_copy_attributes(scaled, &src_img);
if (mp_sws_scale(p->sub_scale, scaled, &src_img) < 0)
return false;
}
assert(scaled->w == dw);
assert(scaled->h == dh);
s_stride = scaled->stride[0];
s_ptr = scaled->planes[0];
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
draw_rgba(mp_image_pixel_ptr(p->rgba_overlay, 0, x0, y0),
p->rgba_overlay->stride[0], s_ptr, s_stride, dw, dh);
mark_rect(p, x0, y0, x1, y1);
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
return true;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
static bool render_sb(struct mp_draw_sub_cache *p, struct sub_bitmaps *sb)
{
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
struct part *part = &p->parts[sb->render_index];
switch (sb->format) {
case SUBBITMAP_LIBASS:
render_ass(p, sb);
return true;
case SUBBITMAP_BGRA:
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
return render_rgba(p, part, sb);
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
return false;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
static void clear_rgba_overlay(struct mp_draw_sub_cache *p)
{
assert(p->rgba_overlay->imgfmt == IMGFMT_BGRA);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
for (int y = 0; y < p->rgba_overlay->h; y++) {
uint32_t *px = mp_image_pixel_ptr(p->rgba_overlay, 0, 0, y);
struct slice *line = &p->slices[y * p->s_w];
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
for (int sx = 0; sx < p->s_w; sx++) {
struct slice *s = &line[sx];
// Ensure this final slice doesn't extend beyond the width of p->s_w
if (s->x1 == SLICE_W && sx == p->s_w - 1 && y == p->rgba_overlay->h - 1)
s->x1 = MPMIN(p->w - ((p->s_w - 1) * SLICE_W), s->x1);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (s->x0 <= s->x1) {
memset(px + s->x0, 0, (s->x1 - s->x0) * 4);
*s = (struct slice){SLICE_W, 0};
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
px += SLICE_W;
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->any_osd = false;
}
static struct mp_sws_context *alloc_scaler(struct mp_draw_sub_cache *p)
{
struct mp_sws_context *s = mp_sws_alloc(p);
mp_sws_enable_cmdline_opts(s, p->global);
return s;
}
static void init_general(struct mp_draw_sub_cache *p)
{
p->sub_scale = alloc_scaler(p);
p->s_w = MP_ALIGN_UP(p->rgba_overlay->w, SLICE_W) / SLICE_W;
p->slices = talloc_zero_array(p, struct slice, p->s_w * p->rgba_overlay->h);
mp_image_clear(p->rgba_overlay, 0, 0, p->w, p->h);
clear_rgba_overlay(p);
}
static bool reinit_to_video(struct mp_draw_sub_cache *p)
{
struct mp_image_params *params = &p->params;
mp_image_params_guess_csp(params);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
bool need_premul = params->alpha != MP_ALPHA_PREMUL &&
(mp_imgfmt_get_desc(params->imgfmt).flags & MP_IMGFLAG_ALPHA);
// Intermediate format for video_overlay. Requirements:
// - same subsampling as video
// - uses video colorspace
// - has alpha
// - repacker support (to the format used in p->blend_line)
// - probably 8 bit per component rather than something wasteful or strange
struct mp_regular_imgfmt vfdesc = {0};
int rflags = REPACK_CREATE_EXPAND_8BIT;
bool use_shortcut = false;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->video_to_f32 = mp_repack_create_planar(params->imgfmt, false, rflags);
talloc_steal(p, p->video_to_f32);
if (!p->video_to_f32)
return false;
mp_get_regular_imgfmt(&vfdesc, mp_repack_get_format_dst(p->video_to_f32));
assert(vfdesc.num_planes); // must have succeeded
if (params->color.space == MP_CSP_RGB && vfdesc.num_planes >= 3) {
use_shortcut = true;
if (vfdesc.component_type == MP_COMPONENT_TYPE_UINT &&
vfdesc.component_size == 1 && vfdesc.component_pad == 0)
p->blend_line = blend_line_u8;
}
// If no special blender is available, blend in float.
if (!p->blend_line) {
TA_FREEP(&p->video_to_f32);
rflags |= REPACK_CREATE_PLANAR_F32;
p->video_to_f32 = mp_repack_create_planar(params->imgfmt, false, rflags);
talloc_steal(p, p->video_to_f32);
if (!p->video_to_f32)
return false;
mp_get_regular_imgfmt(&vfdesc, mp_repack_get_format_dst(p->video_to_f32));
assert(vfdesc.component_type == MP_COMPONENT_TYPE_FLOAT);
p->blend_line = blend_line_f32;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->scale_in_tiles = SCALE_IN_TILES;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
int vid_f32_fmt = mp_repack_get_format_dst(p->video_to_f32);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->video_from_f32 = mp_repack_create_planar(params->imgfmt, true, rflags);
talloc_steal(p, p->video_from_f32);
if (!p->video_from_f32)
return false;
2012-12-25 14:23:16 +00:00
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
assert(mp_repack_get_format_dst(p->video_to_f32) ==
mp_repack_get_format_src(p->video_from_f32));
int overlay_fmt = 0;
if (use_shortcut) {
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
// No point in doing anything fancy.
overlay_fmt = IMGFMT_BGRA;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->scale_in_tiles = false;
} else {
struct mp_regular_imgfmt odesc = vfdesc;
// Just use 8 bit as well (should be fine, may use less memory).
odesc.component_type = MP_COMPONENT_TYPE_UINT;
odesc.component_size = 1;
odesc.component_pad = 0;
// Ensure there's alpha.
if (odesc.planes[odesc.num_planes - 1].components[0] != 4) {
if (odesc.num_planes >= 4)
return false; // wat
odesc.planes[odesc.num_planes++] =
(struct mp_regular_imgfmt_plane){1, {4}};
}
overlay_fmt = mp_find_regular_imgfmt(&odesc);
p->scale_in_tiles = odesc.chroma_xs || odesc.chroma_ys;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (!overlay_fmt)
return false;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->overlay_to_f32 = mp_repack_create_planar(overlay_fmt, false, rflags);
talloc_steal(p, p->overlay_to_f32);
if (!p->overlay_to_f32)
return false;
int render_fmt = mp_repack_get_format_dst(p->overlay_to_f32);
struct mp_regular_imgfmt ofdesc = {0};
mp_get_regular_imgfmt(&ofdesc, render_fmt);
if (ofdesc.planes[ofdesc.num_planes - 1].components[0] != 4)
return false;
// The formats must be the same, minus possible lack of alpha in vfdesc.
if (ofdesc.num_planes != vfdesc.num_planes &&
ofdesc.num_planes - 1 != vfdesc.num_planes)
return false;
for (int n = 0; n < vfdesc.num_planes; n++) {
if (vfdesc.planes[n].components[0] != ofdesc.planes[n].components[0])
return false;
}
2012-12-25 14:23:16 +00:00
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->align_x = mp_repack_get_align_x(p->video_to_f32);
p->align_y = mp_repack_get_align_y(p->video_to_f32);
2012-12-25 14:23:16 +00:00
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
assert(p->align_x >= mp_repack_get_align_x(p->overlay_to_f32));
assert(p->align_y >= mp_repack_get_align_y(p->overlay_to_f32));
if (p->align_x > SLICE_W || p->align_y > TILE_H)
return false;
p->w = MP_ALIGN_UP(params->w, p->align_x);
int slice_h = p->align_y;
p->h = MP_ALIGN_UP(params->h, slice_h);
// Size of the overlay. If scaling in tiles, round up to tiles, so we don't
// need to reinit the scale for right/bottom tiles.
int w = p->w;
int h = p->h;
if (p->scale_in_tiles) {
w = MP_ALIGN_UP(w, SLICE_W);
h = MP_ALIGN_UP(h, TILE_H);
}
p->rgba_overlay = talloc_steal(p, mp_image_alloc(IMGFMT_BGRA, w, h));
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->overlay_tmp = talloc_steal(p, mp_image_alloc(render_fmt, SLICE_W, slice_h));
p->video_tmp = talloc_steal(p, mp_image_alloc(vid_f32_fmt, SLICE_W, slice_h));
if (!p->rgba_overlay || !p->overlay_tmp || !p->video_tmp)
return false;
mp_image_params_guess_csp(&p->rgba_overlay->params);
p->rgba_overlay->params.alpha = MP_ALPHA_PREMUL;
p->overlay_tmp->params.color = params->color;
p->video_tmp->params.color = params->color;
if (p->rgba_overlay->imgfmt == overlay_fmt) {
if (!repack_config_buffers(p->overlay_to_f32, 0, p->overlay_tmp,
0, p->rgba_overlay, NULL))
return false;
} else {
// Generally non-RGB.
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->video_overlay = talloc_steal(p, mp_image_alloc(overlay_fmt, w, h));
if (!p->video_overlay)
return false;
p->video_overlay->params.color = params->color;
p->video_overlay->params.chroma_location = params->chroma_location;
p->video_overlay->params.alpha = MP_ALPHA_PREMUL;
if (p->scale_in_tiles)
p->video_overlay->params.chroma_location = MP_CHROMA_CENTER;
p->rgba_to_overlay = alloc_scaler(p);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->rgba_to_overlay->allow_zimg = true;
if (!mp_sws_supports_formats(p->rgba_to_overlay,
p->video_overlay->imgfmt, p->rgba_overlay->imgfmt))
return false;
if (!repack_config_buffers(p->overlay_to_f32, 0, p->overlay_tmp,
0, p->video_overlay, NULL))
return false;
// Setup a scaled alpha plane if chroma-subsampling is present.
int xs = p->video_overlay->fmt.chroma_xs;
int ys = p->video_overlay->fmt.chroma_ys;
if (xs || ys) {
// Require float so format selection becomes simpler (maybe).
assert(rflags & REPACK_CREATE_PLANAR_F32);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
// For extracting the alpha plane, construct a gray format that is
// compatible with the alpha one.
struct mp_regular_imgfmt odesc = {0};
mp_get_regular_imgfmt(&odesc, overlay_fmt);
assert(odesc.component_size);
int aplane = odesc.num_planes - 1;
assert(odesc.planes[aplane].num_components == 1);
assert(odesc.planes[aplane].components[0] == 4);
struct mp_regular_imgfmt cadesc = odesc;
cadesc.num_planes = 1;
cadesc.planes[0] = (struct mp_regular_imgfmt_plane){1, {1}};
cadesc.chroma_xs = cadesc.chroma_ys = 0;
int calpha_fmt = mp_find_regular_imgfmt(&cadesc);
if (!calpha_fmt)
return false;
// Unscaled alpha plane from p->video_overlay.
p->alpha_overlay = talloc_zero(p, struct mp_image);
mp_image_setfmt(p->alpha_overlay, calpha_fmt);
mp_image_set_size(p->alpha_overlay, w, h);
p->alpha_overlay->planes[0] = p->video_overlay->planes[aplane];
p->alpha_overlay->stride[0] = p->video_overlay->stride[aplane];
// Full range gray always has the same range as alpha.
p->alpha_overlay->params.color.levels = MP_CSP_LEVELS_PC;
mp_image_params_guess_csp(&p->alpha_overlay->params);
p->calpha_overlay =
talloc_steal(p, mp_image_alloc(calpha_fmt, w >> xs, h >> ys));
if (!p->calpha_overlay)
return false;
p->calpha_overlay->params.color = p->alpha_overlay->params.color;
p->calpha_to_f32 = mp_repack_create_planar(calpha_fmt, false, rflags);
talloc_steal(p, p->calpha_to_f32);
if (!p->calpha_to_f32)
return false;
int af32_fmt = mp_repack_get_format_dst(p->calpha_to_f32);
p->calpha_tmp = talloc_steal(p, mp_image_alloc(af32_fmt, SLICE_W, 1));
if (!p->calpha_tmp)
return false;
if (!repack_config_buffers(p->calpha_to_f32, 0, p->calpha_tmp,
0, p->calpha_overlay, NULL))
return false;
p->alpha_to_calpha = alloc_scaler(p);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (!mp_sws_supports_formats(p->alpha_to_calpha,
calpha_fmt, calpha_fmt))
return false;
}
2012-12-25 14:23:16 +00:00
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (need_premul) {
p->premul = alloc_scaler(p);
p->unpremul = alloc_scaler(p);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
p->premul_tmp = mp_image_alloc(params->imgfmt, params->w, params->h);
talloc_steal(p, p->premul_tmp);
if (!p->premul_tmp)
return false;
mp_image_set_params(p->premul_tmp, params);
p->premul_tmp->params.alpha = MP_ALPHA_PREMUL;
// Only zimg supports this.
p->premul->force_scaler = MP_SWS_ZIMG;
p->unpremul->force_scaler = MP_SWS_ZIMG;
}
init_general(p);
return true;
}
static bool reinit_to_overlay(struct mp_draw_sub_cache *p)
{
p->align_x = 1;
p->align_y = 1;
p->w = p->params.w;
p->h = p->params.h;
p->rgba_overlay = talloc_steal(p, mp_image_alloc(IMGFMT_BGRA, p->w, p->h));
if (!p->rgba_overlay)
return false;
mp_image_params_guess_csp(&p->rgba_overlay->params);
p->rgba_overlay->params.alpha = MP_ALPHA_PREMUL;
// Some non-sense with the intention to somewhat isolate the returned image.
mp_image_setfmt(&p->res_overlay, p->rgba_overlay->imgfmt);
mp_image_set_size(&p->res_overlay, p->rgba_overlay->w, p->rgba_overlay->h);
mp_image_copy_attributes(&p->res_overlay, p->rgba_overlay);
p->res_overlay.planes[0] = p->rgba_overlay->planes[0];
p->res_overlay.stride[0] = p->rgba_overlay->stride[0];
init_general(p);
// Mark all dirty (for full reinit of user state).
for (int y = 0; y < p->rgba_overlay->h; y++) {
for (int sx = 0; sx < p->s_w; sx++)
p->slices[y * p->s_w + sx] = (struct slice){0, SLICE_W};
}
return true;
}
static bool check_reinit(struct mp_draw_sub_cache *p,
struct mp_image_params *params, bool to_video)
{
if (!mp_image_params_equal(&p->params, params) || !p->rgba_overlay) {
talloc_free_children(p);
*p = (struct mp_draw_sub_cache){.global = p->global, .params = *params};
if (!(to_video ? reinit_to_video(p) : reinit_to_overlay(p))) {
talloc_free_children(p);
*p = (struct mp_draw_sub_cache){.global = p->global};
return false;
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
return true;
2012-12-25 14:23:16 +00:00
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
char *mp_draw_sub_get_dbg_info(struct mp_draw_sub_cache *p)
{
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
assert(p);
return talloc_asprintf(NULL,
"align=%d:%d ov=%-7s, ov_f=%s, v_f=%s, a=%s, ca=%s, ca_f=%s",
p->align_x, p->align_y,
mp_imgfmt_to_name(p->video_overlay ? p->video_overlay->imgfmt : 0),
mp_imgfmt_to_name(p->overlay_tmp->imgfmt),
mp_imgfmt_to_name(p->video_tmp->imgfmt),
mp_imgfmt_to_name(p->alpha_overlay ? p->alpha_overlay->imgfmt : 0),
mp_imgfmt_to_name(p->calpha_overlay ? p->calpha_overlay->imgfmt : 0),
mp_imgfmt_to_name(p->calpha_tmp ? p->calpha_tmp->imgfmt : 0));
}
struct mp_draw_sub_cache *mp_draw_sub_alloc(void *ta_parent, struct mpv_global *g)
{
struct mp_draw_sub_cache *c = talloc_zero(ta_parent, struct mp_draw_sub_cache);
c->global = g;
return c;
}
// For tests.
struct mp_draw_sub_cache *mp_draw_sub_alloc_test(struct mp_image *dst)
{
struct mp_draw_sub_cache *c = talloc_zero(NULL, struct mp_draw_sub_cache);
reinit_to_video(c);
return c;
}
bool mp_draw_sub_bitmaps(struct mp_draw_sub_cache *p, struct mp_image *dst,
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
struct sub_bitmap_list *sbs_list)
{
bool ok = false;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
// dst must at least be as large as the bounding box, or you may get memory
// corruption.
assert(dst->w >= sbs_list->w);
assert(dst->h >= sbs_list->h);
if (!check_reinit(p, &dst->params, true))
return false;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (p->change_id != sbs_list->change_id) {
p->change_id = sbs_list->change_id;
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
clear_rgba_overlay(p);
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
for (int n = 0; n < sbs_list->num_items; n++) {
if (!render_sb(p, sbs_list->items[n]))
goto done;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (!convert_to_video_overlay(p))
goto done;
}
if (p->any_osd) {
struct mp_image *target = dst;
if (p->premul_tmp) {
if (mp_sws_scale(p->premul, p->premul_tmp, dst) < 0)
goto done;
target = p->premul_tmp;
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
if (!blend_overlay_with_video(p, target))
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
goto done;
if (target != dst) {
if (mp_sws_scale(p->unpremul, dst, p->premul_tmp) < 0)
goto done;
}
}
draw_bmp: rewrite draw_bmp.c is the software blender for subtitles and OSD. It's used by encoding mode (burning subtitles), and some VOs, like vo_drm, vo_x11, vo_xv, and possibly more. This changes the algorithm from upsampling the video to 4:4:4 and then blending to downsampling the OSD and then blending directly to video. This has far-reaching consequences for its internals, and results in an effective rewrite. Since I wanted to avoid un-premultiplying, all blending is done with premultiplied alpha. That's actually the sane thing to do. The old code just didn't do it, because it's very weird in YUV fixed point. Essentially, you'd have to compensate for the chroma centering constant by subtracting src_alpha/255*128. This seemed so hairy (especially with correct rounding and high bit depths involved) that I went for using float. I think it turned out mostly OK, although it's more complex and less maintainable than before. reinit() is certainly a bit too long. While it should be possible to optimize the RGB path more (for example by blending directly instead of doing the stupid float conversion), this is probably slower. vo_xv users probably lose in this, because it takes the slowest path (due to subsampling requirements and using YUV). Why this rewrite? Nobody knows. I simply forgot the reason. But you'll have it anyway. Whether or not this would have required a full rewrite, at least it supports target alpha now (you can for example hard sub transparent PNGs, if you ever wanted to use mpv for this). Remove the check in vf_sub. The new draw_bmp.c is not as reliant on libswscale anymore (mostly uses repack.c now), and osd.c shows an error message on missing support instead now. Formats with chroma subsampling of 4 are not supported, because FFmpeg doesn't provide pixfmt definitions for alpha variants. We could provide those ourselves (relatively trivial), but why bother.
2020-05-09 16:01:07 +00:00
ok = true;
done:
return ok;
}
// Bounding boxes for mp_draw_sub_overlay() API. For simplicity, each rectangle
// covers a fixed tile on the screen, starts out empty, but is not extended
// beyond the tile. In the simplest case, there's only 1 rect/tile for everything.
struct rc_grid {
unsigned w, h; // size in grid tiles
unsigned r_w, r_h; // size of a grid tile in pixels
struct mp_rect *rcs; // rcs[x * w + y]
};
static void init_rc_grid(struct rc_grid *gr, struct mp_draw_sub_cache *p,
struct mp_rect *rcs, int max_rcs)
{
*gr = (struct rc_grid){ .w = max_rcs ? 1 : 0, .h = max_rcs ? 1 : 0,
.rcs = rcs, .r_w = p->s_w * SLICE_W, .r_h = p->h, };
// Dumb iteration to figure out max. size because I'm stupid.
bool more = true;
while (more) {
more = false;
if (gr->r_h >= 128) {
if (gr->w * gr->h * 2 > max_rcs)
break;
gr->h *= 2;
gr->r_h = (p->h + gr->h - 1) / gr->h;
more = true;
}
if (gr->r_w >= SLICE_W * 2) {
if (gr->w * gr->h * 2 > max_rcs)
break;
gr->w *= 2;
gr->r_w = (p->s_w + gr->w - 1) / gr->w * SLICE_W;
more = true;
}
}
assert(gr->r_h * gr->h >= p->h);
assert(!(gr->r_w & (SLICE_W - 1)));
assert(gr->r_w * gr->w >= p->w);
// Init with empty (degenerate) rectangles.
for (int y = 0; y < gr->h; y++) {
for (int x = 0; x < gr->w; x++) {
struct mp_rect *rc = &gr->rcs[y * gr->w + x];
rc->x1 = x * gr->r_w;
rc->y1 = y * gr->r_h;
rc->x0 = rc->x1 + gr->r_w;
rc->y0 = rc->y1 + gr->r_h;
}
}
}
// Extend given grid with contents of p->slices.
static void mark_rcs(struct mp_draw_sub_cache *p, struct rc_grid *gr)
{
for (int y = 0; y < p->h; y++) {
struct slice *line = &p->slices[y * p->s_w];
struct mp_rect *rcs = &gr->rcs[y / gr->r_h * gr->w];
for (int sx = 0; sx < p->s_w; sx++) {
struct slice *s = &line[sx];
if (s->x0 < s->x1) {
unsigned xpos = sx * SLICE_W;
struct mp_rect *rc = &rcs[xpos / gr->r_w];
rc->y0 = MPMIN(rc->y0, y);
rc->y1 = MPMAX(rc->y1, y + 1);
rc->x0 = MPMIN(rc->x0, xpos + s->x0);
// Ensure this does not extend beyond the total width
rc->x1 = MPCLAMP(xpos + s->x1, rc->x1, p->w);
}
}
}
}
// Remove empty RCs, and return rc count.
static int return_rcs(struct rc_grid *gr)
{
int num = 0, cnt = gr->w * gr->h;
for (int n = 0; n < cnt; n++) {
struct mp_rect *rc = &gr->rcs[n];
if (rc->x0 < rc->x1 && rc->y0 < rc->y1)
gr->rcs[num++] = *rc;
}
return num;
}
struct mp_image *mp_draw_sub_overlay(struct mp_draw_sub_cache *p,
struct sub_bitmap_list *sbs_list,
struct mp_rect *act_rcs,
int max_act_rcs,
int *num_act_rcs,
struct mp_rect *mod_rcs,
int max_mod_rcs,
int *num_mod_rcs)
{
*num_act_rcs = 0;
*num_mod_rcs = 0;
struct mp_image_params params = {.w = sbs_list->w, .h = sbs_list->h};
if (!check_reinit(p, &params, false))
return NULL;
struct rc_grid gr_act, gr_mod;
init_rc_grid(&gr_act, p, act_rcs, max_act_rcs);
init_rc_grid(&gr_mod, p, mod_rcs, max_mod_rcs);
if (p->change_id != sbs_list->change_id) {
p->change_id = sbs_list->change_id;
mark_rcs(p, &gr_mod);
clear_rgba_overlay(p);
for (int n = 0; n < sbs_list->num_items; n++) {
if (!render_sb(p, sbs_list->items[n])) {
p->change_id = 0;
return NULL;
}
}
mark_rcs(p, &gr_mod);
}
mark_rcs(p, &gr_act);
*num_act_rcs = return_rcs(&gr_act);
*num_mod_rcs = return_rcs(&gr_mod);
return &p->res_overlay;
video: make OSD/subtitle bitmaps refcounted (sort of) 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.
2020-04-26 21:34:32 +00:00
}
// vim: ts=4 sw=4 et tw=80