From e5311586ab7641e0e1936473594bd9fbaa67bb2d Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 24 Nov 2013 12:58:06 +0100 Subject: Rename sub.c/.h to osd.c/.h This was way too misleading. osd.c merely calls the subtitle renderers, instead of actually dealing with subtitles. --- sub/ass_mp.c | 2 +- sub/dec_sub.c | 1 - sub/dec_sub.h | 2 +- sub/draw_bmp.c | 5 +- sub/draw_bmp.h | 2 +- sub/find_subfiles.c | 1 - sub/img_convert.c | 2 +- sub/osd.c | 325 ++++++++++++++++++++++++++++++++++++++++++++++++++++ sub/osd.h | 245 +++++++++++++++++++++++++++++++++++++++ sub/osd_dummy.c | 2 +- sub/osd_libass.c | 2 +- sub/sd_ass.c | 1 - sub/sd_lavc.c | 1 - sub/sd_spu.c | 1 - sub/spudec.c | 2 +- sub/sub.c | 325 ---------------------------------------------------- sub/sub.h | 245 --------------------------------------- 17 files changed, 579 insertions(+), 585 deletions(-) create mode 100644 sub/osd.c create mode 100644 sub/osd.h delete mode 100644 sub/sub.c delete mode 100644 sub/sub.h (limited to 'sub') diff --git a/sub/ass_mp.c b/sub/ass_mp.c index ac36e2d954..33cd1559fc 100644 --- a/sub/ass_mp.c +++ b/sub/ass_mp.c @@ -33,7 +33,7 @@ #include "mpvcore/mp_msg.h" #include "mpvcore/path.h" #include "ass_mp.h" -#include "sub/sub.h" +#include "osd.h" #include "stream/stream.h" #include "mpvcore/options.h" diff --git a/sub/dec_sub.c b/sub/dec_sub.c index cb76acc248..425db1b3e8 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -25,7 +25,6 @@ #include "config.h" #include "demux/demux.h" #include "sd.h" -#include "sub.h" #include "dec_sub.h" #include "mpvcore/options.h" #include "mpvcore/mp_msg.h" diff --git a/sub/dec_sub.h b/sub/dec_sub.h index 9ff2b366bd..4fa62d7b97 100644 --- a/sub/dec_sub.h +++ b/sub/dec_sub.h @@ -4,7 +4,7 @@ #include #include -#include "sub/sub.h" +#include "osd.h" struct sh_stream; struct ass_track; diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c index 3dc46fb827..2b91befe50 100644 --- a/sub/draw_bmp.c +++ b/sub/draw_bmp.c @@ -26,9 +26,8 @@ #include #include "mpvcore/mp_common.h" -#include "sub/draw_bmp.h" -#include "sub/sub.h" -#include "sub/img_convert.h" +#include "draw_bmp.h" +#include "img_convert.h" #include "video/mp_image.h" #include "video/sws_utils.h" #include "video/img_format.h" diff --git a/sub/draw_bmp.h b/sub/draw_bmp.h index 489e91f666..9ccd764d5d 100644 --- a/sub/draw_bmp.h +++ b/sub/draw_bmp.h @@ -1,7 +1,7 @@ #ifndef MPLAYER_DRAW_BMP_H #define MPLAYER_DRAW_BMP_H -#include "sub/sub.h" +#include "osd.h" struct mp_image; struct sub_bitmaps; diff --git a/sub/find_subfiles.c b/sub/find_subfiles.c index a5b1bdeb22..fc55484c52 100644 --- a/sub/find_subfiles.c +++ b/sub/find_subfiles.c @@ -11,7 +11,6 @@ #include "mpvcore/path.h" #include "mpvcore/mp_common.h" #include "sub/find_subfiles.h" -#include "sub/sub.h" static const char *sub_exts[] = {"utf", "utf8", "utf-8", "idx", "sub", "srt", "smi", "rt", "txt", "ssa", "aqt", "jss", diff --git a/sub/img_convert.c b/sub/img_convert.c index 3ebe993c17..ce72f2c6d3 100644 --- a/sub/img_convert.c +++ b/sub/img_convert.c @@ -24,7 +24,7 @@ #include "talloc.h" #include "img_convert.h" -#include "sub.h" +#include "osd.h" #include "video/img_format.h" #include "video/mp_image.h" #include "video/sws_utils.h" diff --git a/sub/osd.c b/sub/osd.c new file mode 100644 index 0000000000..4c1b2ff322 --- /dev/null +++ b/sub/osd.c @@ -0,0 +1,325 @@ +/* + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include +#include +#include + +#include + +#include "mpvcore/mp_common.h" + +#include "stream/stream.h" + +#include "osdep/timer.h" + +#include "talloc.h" +#include "mpvcore/options.h" +#include "mpvcore/mp_msg.h" +#include "osd.h" +#include "dec_sub.h" +#include "img_convert.h" +#include "draw_bmp.h" +#include "video/mp_image.h" +#include "video/mp_image_pool.h" + +static const struct osd_style_opts osd_style_opts_def = { + .font = "sans-serif", + .font_size = 45, + .color = {255, 255, 255, 255}, + .border_color = {0, 0, 0, 255}, + .shadow_color = {240, 240, 240, 128}, + .border_size = 2.5, + .shadow_offset = 0, + .margin_x = 25, + .margin_y = 10, +}; + +#define OPT_BASE_STRUCT struct osd_style_opts +const struct m_sub_options osd_style_conf = { + .opts = (m_option_t[]) { + OPT_STRING("font", font, 0), + OPT_FLOATRANGE("font-size", font_size, 0, 1, 9000), + OPT_COLOR("color", color, 0), + OPT_COLOR("border-color", border_color, 0), + OPT_COLOR("shadow-color", shadow_color, 0), + OPT_COLOR("back-color", back_color, 0), + OPT_FLOATRANGE("border-size", border_size, 0, 0, 10), + OPT_FLOATRANGE("shadow-offset", shadow_offset, 0, 0, 10), + OPT_FLOATRANGE("spacing", spacing, 0, -10, 10), + OPT_INTRANGE("margin-x", margin_x, 0, 0, 300), + OPT_INTRANGE("margin-y", margin_y, 0, 0, 600), + OPT_FLOATRANGE("blur", blur, 0, 0, 20), + {0} + }, + .size = sizeof(struct osd_style_opts), + .defaults = &osd_style_opts_def, +}; + +static bool osd_res_equals(struct mp_osd_res a, struct mp_osd_res b) +{ + return a.w == b.w && a.h == b.h && a.ml == b.ml && a.mt == b.mt + && a.mr == b.mr && a.mb == b.mb + && a.display_par == b.display_par + && a.video_par == b.video_par; +} + +struct osd_state *osd_create(struct MPOpts *opts, struct ass_library *asslib) +{ + struct osd_state *osd = talloc_zero(NULL, struct osd_state); + *osd = (struct osd_state) { + .opts = opts, + .ass_library = asslib, + .osd_text = talloc_strdup(osd, ""), + .sub_text = talloc_strdup(osd, ""), + .progbar_type = -1, + }; + + for (int n = 0; n < MAX_OSD_PARTS; n++) { + struct osd_object *obj = talloc_struct(osd, struct osd_object, { + .type = n, + }); + for (int i = 0; i < OSD_CONV_CACHE_MAX; i++) + obj->cache[i] = talloc_steal(obj, osd_conv_cache_new()); + osd->objs[n] = obj; + } + + osd->objs[OSDTYPE_SUB]->is_sub = true; // dec_sub.c + osd->objs[OSDTYPE_SUBTEXT]->is_sub = true; // osd_libass.c + + osd_init_backend(osd); + return osd; +} + +void osd_free(struct osd_state *osd) +{ + if (!osd) + return; + osd_destroy_backend(osd); + talloc_free(osd); +} + +static bool set_text(void *talloc_ctx, char **var, const char *text) +{ + if (!text) + text = ""; + if (strcmp(*var, text) == 0) + return true; + talloc_free(*var); + *var = talloc_strdup(talloc_ctx, text); + return false; +} + +void osd_set_text(struct osd_state *osd, const char *text) +{ + if (!set_text(osd, &osd->osd_text, text)) + osd_changed(osd, OSDTYPE_OSD); +} + +void osd_set_sub(struct osd_state *osd, const char *text) +{ + if (!set_text(osd, &osd->sub_text, text)) + osd_changed(osd, OSDTYPE_SUBTEXT); +} + +static void render_object(struct osd_state *osd, struct osd_object *obj, + struct mp_osd_res res, double video_pts, + const bool sub_formats[SUBBITMAP_COUNT], + struct sub_bitmaps *out_imgs) +{ + struct MPOpts *opts = osd->opts; + + bool formats[SUBBITMAP_COUNT]; + memcpy(formats, sub_formats, sizeof(formats)); + if (opts->force_rgba_osd) + formats[SUBBITMAP_LIBASS] = false; + + *out_imgs = (struct sub_bitmaps) {0}; + + if (!osd_res_equals(res, obj->vo_res)) + obj->force_redraw = true; + obj->vo_res = res; + + if (obj->type == OSDTYPE_SUB) { + if (osd->render_bitmap_subs && osd->dec_sub) { + double sub_pts = video_pts; + if (sub_pts != MP_NOPTS_VALUE) + sub_pts -= osd->video_offset - opts->sub_delay; + sub_get_bitmaps(osd->dec_sub, obj->vo_res, sub_pts, out_imgs); + } + } else if (obj->type == OSDTYPE_EXTERNAL2) { + if (osd->external2.format) { + *out_imgs = osd->external2; + osd->external2.bitmap_id = osd->external2.bitmap_pos_id = 0; + } + } else { + osd_object_get_bitmaps(osd, obj, out_imgs); + } + + if (obj->force_redraw) { + out_imgs->bitmap_id++; + out_imgs->bitmap_pos_id++; + } + + obj->force_redraw = false; + obj->vo_bitmap_id += out_imgs->bitmap_id; + obj->vo_bitmap_pos_id += out_imgs->bitmap_pos_id; + + if (out_imgs->num_parts == 0) + return; + + if (obj->cached.bitmap_id == obj->vo_bitmap_id + && obj->cached.bitmap_pos_id == obj->vo_bitmap_pos_id + && formats[obj->cached.format]) + { + *out_imgs = obj->cached; + return; + } + + out_imgs->render_index = obj->type; + out_imgs->bitmap_id = obj->vo_bitmap_id; + out_imgs->bitmap_pos_id = obj->vo_bitmap_pos_id; + + if (formats[out_imgs->format]) + return; + + bool cached = false; // do we have a copy of all the image data? + + if (out_imgs->format == SUBBITMAP_INDEXED && opts->sub_gray) + cached |= osd_conv_idx_to_gray(obj->cache[0], out_imgs); + + if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_INDEXED) + cached |= osd_conv_idx_to_rgba(obj->cache[1], out_imgs); + + if (out_imgs->format == SUBBITMAP_RGBA && opts->sub_gauss != 0.0f) + cached |= osd_conv_blur_rgba(obj->cache[2], out_imgs, opts->sub_gauss); + + // Do this conversion last to not trigger gauss blurring for ASS + if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_LIBASS) + cached |= osd_conv_ass_to_rgba(obj->cache[3], out_imgs); + + if (cached) + obj->cached = *out_imgs; +} + +// draw_flags is a bit field of OSD_DRAW_* constants +void osd_draw(struct osd_state *osd, struct mp_osd_res res, + double video_pts, int draw_flags, + const bool formats[SUBBITMAP_COUNT], + void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx) +{ + if (draw_flags & OSD_DRAW_SUB_FILTER) + draw_flags |= OSD_DRAW_SUB_ONLY; + + if (!(draw_flags & OSD_DRAW_SUB_ONLY)) + osd->last_vo_res = res; + + for (int n = 0; n < MAX_OSD_PARTS; n++) { + struct osd_object *obj = osd->objs[n]; + + // Object is drawn into the video frame itself; don't draw twice + if (osd->render_subs_in_filter && obj->is_sub && + !(draw_flags & OSD_DRAW_SUB_FILTER)) + continue; + if ((draw_flags & OSD_DRAW_SUB_ONLY) && !obj->is_sub) + continue; + + struct sub_bitmaps imgs; + render_object(osd, obj, res, video_pts, formats, &imgs); + if (imgs.num_parts > 0) { + if (formats[imgs.format]) { + cb(cb_ctx, &imgs); + } else { + mp_msg(MSGT_OSD, MSGL_ERR, + "Can't render OSD part %d (format %d).\n", + obj->type, imgs.format); + } + } + } +} + +struct draw_on_image_closure { + struct osd_state *osd; + struct mp_image *dest; + struct mp_image_pool *pool; + bool changed; +}; + +static void draw_on_image(void *ctx, struct sub_bitmaps *imgs) +{ + struct draw_on_image_closure *closure = ctx; + struct osd_state *osd = closure->osd; + if (closure->pool) { + mp_image_pool_make_writeable(closure->pool, closure->dest); + } else { + mp_image_make_writeable(closure->dest); + } + mp_draw_sub_bitmaps(&osd->draw_cache, closure->dest, imgs); + talloc_steal(osd, osd->draw_cache); + closure->changed = true; +} + +// Calls mp_image_make_writeable() on the dest image if something is drawn. +// Returns whether anything was drawn. +bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res, + double video_pts, int draw_flags, struct mp_image *dest) +{ + struct draw_on_image_closure closure = {osd, dest}; + osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats, + &draw_on_image, &closure); + return closure.changed; +} + +// Like osd_draw_on_image(), but if dest needs to be copied to make it +// writeable, allocate images from the given pool. (This is a minor +// optimization to reduce "real" image sized memory allocations.) +void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res, + double video_pts, int draw_flags, + struct mp_image_pool *pool, struct mp_image *dest) +{ + struct draw_on_image_closure closure = {osd, dest, pool}; + osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats, + &draw_on_image, &closure); +} + +void osd_changed(struct osd_state *osd, int new_value) +{ + for (int n = 0; n < MAX_OSD_PARTS; n++) { + if (osd->objs[n]->type == new_value) + osd->objs[n]->force_redraw = true; + } + osd->want_redraw = true; +} + +void osd_changed_all(struct osd_state *osd) +{ + for (int n = 0; n < MAX_OSD_PARTS; n++) + osd_changed(osd, n); +} + +// Scale factor to translate OSD coordinates to what the obj uses internally. +// osd_coordinates * (sh, sh) = obj_coordinates +void osd_object_get_scale_factor(struct osd_state *osd, struct osd_object *obj, + double *sw, double *sh) +{ + int nw, nh; + osd_object_get_resolution(osd, obj, &nw, &nh); + *sw = nw / (double)obj->vo_res.w; + *sh = nh / (double)obj->vo_res.h; +} diff --git a/sub/osd.h b/sub/osd.h new file mode 100644 index 0000000000..64e10193ea --- /dev/null +++ b/sub/osd.h @@ -0,0 +1,245 @@ +/* + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPLAYER_SUB_H +#define MPLAYER_SUB_H + +#include +#include +#include + +#include "mpvcore/m_option.h" + +// NOTE: VOs must support at least SUBBITMAP_RGBA. +enum sub_bitmap_format { + SUBBITMAP_EMPTY = 0,// no bitmaps; always has num_parts==0 + SUBBITMAP_LIBASS, // A8, with a per-surface blend color (libass.color) + SUBBITMAP_RGBA, // B8G8R8A8 (MSB=A, LSB=B), scaled, premultiplied alpha + SUBBITMAP_INDEXED, // scaled, bitmap points to osd_bmp_indexed + + SUBBITMAP_COUNT +}; + +// For SUBBITMAP_INDEXED +struct osd_bmp_indexed { + uint8_t *bitmap; + // Each entry is like a pixel in SUBBITMAP_RGBA format, but using straight + // alpha. + uint32_t palette[256]; +}; + +struct sub_bitmap { + void *bitmap; + int stride; + // Note: not clipped, going outside the screen area is allowed + // (except for SUBBITMAP_LIBASS, which is always clipped) + int w, h; + int x, y; + int dw, dh; + + union { + struct { + uint32_t color; + } libass; + }; +}; + +struct sub_bitmaps { + // For VO cache state (limited by MAX_OSD_PARTS) + int render_index; + + enum sub_bitmap_format format; + + // If false, dw==w && dh==h. + // SUBBITMAP_LIBASS is never scaled. + bool scaled; + + struct sub_bitmap *parts; + int num_parts; + + // Incremented on each change + int bitmap_id, bitmap_pos_id; +}; + +struct mp_osd_res { + int w, h; // screen dimensions, including black borders + int mt, mb, ml, mr; // borders (top, bottom, left, right) + double display_par; + double video_par; // PAR of the original video (for some sub decoders) +}; + +enum mp_osdtype { + OSDTYPE_SUB, + OSDTYPE_SUBTEXT, + + OSDTYPE_PROGBAR, + OSDTYPE_OSD, + + OSDTYPE_EXTERNAL, + OSDTYPE_EXTERNAL2, + + MAX_OSD_PARTS +}; + +#define OSD_CONV_CACHE_MAX 4 + +struct osd_object { + int type; // OSDTYPE_* + bool is_sub; + + bool force_redraw; + + // caches for OSD conversion (internal to render_object()) + struct osd_conv_cache *cache[OSD_CONV_CACHE_MAX]; + struct sub_bitmaps cached; + + // VO cache state + int vo_bitmap_id; + int vo_bitmap_pos_id; + struct mp_osd_res vo_res; + + // Internally used by osd_libass.c + struct ass_track *osd_track; + struct sub_bitmap *parts_cache; +}; + +struct osd_state { + struct osd_object *objs[MAX_OSD_PARTS]; + + struct ass_library *ass_library; + struct ass_renderer *ass_renderer; + double video_offset; + double vo_pts; + + bool render_subs_in_filter; + bool render_bitmap_subs; + + struct mp_osd_res last_vo_res; + + bool want_redraw; + + // OSDTYPE_OSD + char *osd_text; + // OSDTYPE_SUBTEXT + char *sub_text; + // OSDTYPE_PROGBAR + int progbar_type; // <0: disabled, 1-255: symbol, else: no symbol + float progbar_value; // range 0.0-1.0 + float *progbar_stops; // used for chapter indicators (0.0-1.0 each) + int progbar_num_stops; + // OSDTYPE_EXTERNAL + char *external; + int external_res_x, external_res_y; + // OSDTYPE_EXTERNAL2 + struct sub_bitmaps external2; + // OSDTYPE_SUB + struct dec_sub *dec_sub; + + struct MPOpts *opts; + + // Internal to sub.c + struct mp_draw_sub_cache *draw_cache; + + // Internally used by osd_libass.c + struct ass_renderer *osd_render; + struct ass_library *osd_ass_library; +}; + +// Start of OSD symbols in osd_font.pfb +#define OSD_CODEPOINTS 0xE000 + +// OSD symbols. osd_font.pfb has them starting from codepoint OSD_CODEPOINTS. +// Symbols with a value >= 32 are normal unicode codepoints. +enum mp_osd_font_codepoints { + OSD_PLAY = 0x01, + OSD_PAUSE = 0x02, + OSD_STOP = 0x03, + OSD_REW = 0x04, + OSD_FFW = 0x05, + OSD_CLOCK = 0x06, + OSD_CONTRAST = 0x07, + OSD_SATURATION = 0x08, + OSD_VOLUME = 0x09, + OSD_BRIGHTNESS = 0x0A, + OSD_HUE = 0x0B, + OSD_BALANCE = 0x0C, + OSD_PANSCAN = 0x50, + + OSD_PB_START = 0x10, + OSD_PB_0 = 0x11, + OSD_PB_END = 0x12, + OSD_PB_1 = 0x13, +}; + +struct osd_style_opts { + char *font; + float font_size; + struct m_color color; + struct m_color border_color; + struct m_color shadow_color; + struct m_color back_color; + float border_size; + float shadow_offset; + float spacing; + int margin_x; + int margin_y; + float blur; +}; + +extern const struct m_sub_options osd_style_conf; + +struct osd_state *osd_create(struct MPOpts *opts, struct ass_library *asslib); +void osd_set_text(struct osd_state *osd, const char *text); +void osd_set_sub(struct osd_state *osd, const char *text); +void osd_changed(struct osd_state *osd, int new_value); +void osd_changed_all(struct osd_state *osd); +void osd_free(struct osd_state *osd); + +enum mp_osd_draw_flags { + OSD_DRAW_SUB_FILTER = (1 << 0), + OSD_DRAW_SUB_ONLY = (1 << 1), +}; + +void osd_draw(struct osd_state *osd, struct mp_osd_res res, + double video_pts, int draw_flags, + const bool formats[SUBBITMAP_COUNT], + void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx); + +struct mp_image; +bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res, + double video_pts, int draw_flags, struct mp_image *dest); + +struct mp_image_pool; +void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res, + double video_pts, int draw_flags, + struct mp_image_pool *pool, struct mp_image *dest); + +void osd_object_get_scale_factor(struct osd_state *osd, struct osd_object *obj, + double *sw, double *sh); + +// defined in osd_libass.c and osd_dummy.c + +void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj, + struct sub_bitmaps *out_imgs); +void osd_object_get_resolution(struct osd_state *osd, struct osd_object *obj, + int *out_w, int *out_h); +void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function); +void osd_init_backend(struct osd_state *osd); +void osd_destroy_backend(struct osd_state *osd); + +#endif /* MPLAYER_SUB_H */ diff --git a/sub/osd_dummy.c b/sub/osd_dummy.c index a330c63982..cc2ba37377 100644 --- a/sub/osd_dummy.c +++ b/sub/osd_dummy.c @@ -4,7 +4,7 @@ #include "config.h" #include "talloc.h" -#include "sub.h" +#include "osd.h" void osd_init_backend(struct osd_state *osd) { diff --git a/sub/osd_libass.c b/sub/osd_libass.c index 29db58f464..0564fbb4d3 100644 --- a/sub/osd_libass.c +++ b/sub/osd_libass.c @@ -27,7 +27,7 @@ #include "talloc.h" #include "mpvcore/mp_common.h" #include "mpvcore/mp_msg.h" -#include "sub.h" +#include "osd.h" static const char osd_font_pfb[] = #include "sub/osd_font.h" diff --git a/sub/sd_ass.c b/sub/sd_ass.c index fd545cdbda..631c81a083 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -30,7 +30,6 @@ #include "mpvcore/mp_msg.h" #include "video/csputils.h" #include "video/mp_image.h" -#include "sub.h" #include "dec_sub.h" #include "ass_mp.h" #include "sd.h" diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index 683436eb2a..9741b0de70 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -28,7 +28,6 @@ #include "video/mp_image.h" #include "sd.h" #include "dec_sub.h" -#include "sub.h" struct sd_lavc_priv { AVCodecContext *avctx; diff --git a/sub/sd_spu.c b/sub/sd_spu.c index 0061ec81e3..15ea351159 100644 --- a/sub/sd_spu.c +++ b/sub/sd_spu.c @@ -22,7 +22,6 @@ #include "mpvcore/options.h" #include "video/mp_image.h" #include "sd.h" -#include "sub.h" #include "spudec.h" struct sd_spu_priv { diff --git a/sub/spudec.c b/sub/spudec.c index 5d58b3664c..5a2c094be9 100644 --- a/sub/spudec.c +++ b/sub/spudec.c @@ -43,7 +43,7 @@ #include "mpvcore/mp_msg.h" #include "spudec.h" -#include "sub.h" +#include "osd.h" #include "mpvcore/mp_common.h" #include "video/csputils.h" diff --git a/sub/sub.c b/sub/sub.c deleted file mode 100644 index 9be61bd1d3..0000000000 --- a/sub/sub.c +++ /dev/null @@ -1,325 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include -#include -#include -#include - -#include - -#include "mpvcore/mp_common.h" - -#include "stream/stream.h" - -#include "osdep/timer.h" - -#include "talloc.h" -#include "mpvcore/options.h" -#include "mpvcore/mp_msg.h" -#include "sub.h" -#include "dec_sub.h" -#include "img_convert.h" -#include "draw_bmp.h" -#include "video/mp_image.h" -#include "video/mp_image_pool.h" - -static const struct osd_style_opts osd_style_opts_def = { - .font = "sans-serif", - .font_size = 45, - .color = {255, 255, 255, 255}, - .border_color = {0, 0, 0, 255}, - .shadow_color = {240, 240, 240, 128}, - .border_size = 2.5, - .shadow_offset = 0, - .margin_x = 25, - .margin_y = 10, -}; - -#define OPT_BASE_STRUCT struct osd_style_opts -const struct m_sub_options osd_style_conf = { - .opts = (m_option_t[]) { - OPT_STRING("font", font, 0), - OPT_FLOATRANGE("font-size", font_size, 0, 1, 9000), - OPT_COLOR("color", color, 0), - OPT_COLOR("border-color", border_color, 0), - OPT_COLOR("shadow-color", shadow_color, 0), - OPT_COLOR("back-color", back_color, 0), - OPT_FLOATRANGE("border-size", border_size, 0, 0, 10), - OPT_FLOATRANGE("shadow-offset", shadow_offset, 0, 0, 10), - OPT_FLOATRANGE("spacing", spacing, 0, -10, 10), - OPT_INTRANGE("margin-x", margin_x, 0, 0, 300), - OPT_INTRANGE("margin-y", margin_y, 0, 0, 600), - OPT_FLOATRANGE("blur", blur, 0, 0, 20), - {0} - }, - .size = sizeof(struct osd_style_opts), - .defaults = &osd_style_opts_def, -}; - -static bool osd_res_equals(struct mp_osd_res a, struct mp_osd_res b) -{ - return a.w == b.w && a.h == b.h && a.ml == b.ml && a.mt == b.mt - && a.mr == b.mr && a.mb == b.mb - && a.display_par == b.display_par - && a.video_par == b.video_par; -} - -struct osd_state *osd_create(struct MPOpts *opts, struct ass_library *asslib) -{ - struct osd_state *osd = talloc_zero(NULL, struct osd_state); - *osd = (struct osd_state) { - .opts = opts, - .ass_library = asslib, - .osd_text = talloc_strdup(osd, ""), - .sub_text = talloc_strdup(osd, ""), - .progbar_type = -1, - }; - - for (int n = 0; n < MAX_OSD_PARTS; n++) { - struct osd_object *obj = talloc_struct(osd, struct osd_object, { - .type = n, - }); - for (int i = 0; i < OSD_CONV_CACHE_MAX; i++) - obj->cache[i] = talloc_steal(obj, osd_conv_cache_new()); - osd->objs[n] = obj; - } - - osd->objs[OSDTYPE_SUB]->is_sub = true; // dec_sub.c - osd->objs[OSDTYPE_SUBTEXT]->is_sub = true; // osd_libass.c - - osd_init_backend(osd); - return osd; -} - -void osd_free(struct osd_state *osd) -{ - if (!osd) - return; - osd_destroy_backend(osd); - talloc_free(osd); -} - -static bool set_text(void *talloc_ctx, char **var, const char *text) -{ - if (!text) - text = ""; - if (strcmp(*var, text) == 0) - return true; - talloc_free(*var); - *var = talloc_strdup(talloc_ctx, text); - return false; -} - -void osd_set_text(struct osd_state *osd, const char *text) -{ - if (!set_text(osd, &osd->osd_text, text)) - osd_changed(osd, OSDTYPE_OSD); -} - -void osd_set_sub(struct osd_state *osd, const char *text) -{ - if (!set_text(osd, &osd->sub_text, text)) - osd_changed(osd, OSDTYPE_SUBTEXT); -} - -static void render_object(struct osd_state *osd, struct osd_object *obj, - struct mp_osd_res res, double video_pts, - const bool sub_formats[SUBBITMAP_COUNT], - struct sub_bitmaps *out_imgs) -{ - struct MPOpts *opts = osd->opts; - - bool formats[SUBBITMAP_COUNT]; - memcpy(formats, sub_formats, sizeof(formats)); - if (opts->force_rgba_osd) - formats[SUBBITMAP_LIBASS] = false; - - *out_imgs = (struct sub_bitmaps) {0}; - - if (!osd_res_equals(res, obj->vo_res)) - obj->force_redraw = true; - obj->vo_res = res; - - if (obj->type == OSDTYPE_SUB) { - if (osd->render_bitmap_subs && osd->dec_sub) { - double sub_pts = video_pts; - if (sub_pts != MP_NOPTS_VALUE) - sub_pts -= osd->video_offset - opts->sub_delay; - sub_get_bitmaps(osd->dec_sub, obj->vo_res, sub_pts, out_imgs); - } - } else if (obj->type == OSDTYPE_EXTERNAL2) { - if (osd->external2.format) { - *out_imgs = osd->external2; - osd->external2.bitmap_id = osd->external2.bitmap_pos_id = 0; - } - } else { - osd_object_get_bitmaps(osd, obj, out_imgs); - } - - if (obj->force_redraw) { - out_imgs->bitmap_id++; - out_imgs->bitmap_pos_id++; - } - - obj->force_redraw = false; - obj->vo_bitmap_id += out_imgs->bitmap_id; - obj->vo_bitmap_pos_id += out_imgs->bitmap_pos_id; - - if (out_imgs->num_parts == 0) - return; - - if (obj->cached.bitmap_id == obj->vo_bitmap_id - && obj->cached.bitmap_pos_id == obj->vo_bitmap_pos_id - && formats[obj->cached.format]) - { - *out_imgs = obj->cached; - return; - } - - out_imgs->render_index = obj->type; - out_imgs->bitmap_id = obj->vo_bitmap_id; - out_imgs->bitmap_pos_id = obj->vo_bitmap_pos_id; - - if (formats[out_imgs->format]) - return; - - bool cached = false; // do we have a copy of all the image data? - - if (out_imgs->format == SUBBITMAP_INDEXED && opts->sub_gray) - cached |= osd_conv_idx_to_gray(obj->cache[0], out_imgs); - - if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_INDEXED) - cached |= osd_conv_idx_to_rgba(obj->cache[1], out_imgs); - - if (out_imgs->format == SUBBITMAP_RGBA && opts->sub_gauss != 0.0f) - cached |= osd_conv_blur_rgba(obj->cache[2], out_imgs, opts->sub_gauss); - - // Do this conversion last to not trigger gauss blurring for ASS - if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_LIBASS) - cached |= osd_conv_ass_to_rgba(obj->cache[3], out_imgs); - - if (cached) - obj->cached = *out_imgs; -} - -// draw_flags is a bit field of OSD_DRAW_* constants -void osd_draw(struct osd_state *osd, struct mp_osd_res res, - double video_pts, int draw_flags, - const bool formats[SUBBITMAP_COUNT], - void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx) -{ - if (draw_flags & OSD_DRAW_SUB_FILTER) - draw_flags |= OSD_DRAW_SUB_ONLY; - - if (!(draw_flags & OSD_DRAW_SUB_ONLY)) - osd->last_vo_res = res; - - for (int n = 0; n < MAX_OSD_PARTS; n++) { - struct osd_object *obj = osd->objs[n]; - - // Object is drawn into the video frame itself; don't draw twice - if (osd->render_subs_in_filter && obj->is_sub && - !(draw_flags & OSD_DRAW_SUB_FILTER)) - continue; - if ((draw_flags & OSD_DRAW_SUB_ONLY) && !obj->is_sub) - continue; - - struct sub_bitmaps imgs; - render_object(osd, obj, res, video_pts, formats, &imgs); - if (imgs.num_parts > 0) { - if (formats[imgs.format]) { - cb(cb_ctx, &imgs); - } else { - mp_msg(MSGT_OSD, MSGL_ERR, - "Can't render OSD part %d (format %d).\n", - obj->type, imgs.format); - } - } - } -} - -struct draw_on_image_closure { - struct osd_state *osd; - struct mp_image *dest; - struct mp_image_pool *pool; - bool changed; -}; - -static void draw_on_image(void *ctx, struct sub_bitmaps *imgs) -{ - struct draw_on_image_closure *closure = ctx; - struct osd_state *osd = closure->osd; - if (closure->pool) { - mp_image_pool_make_writeable(closure->pool, closure->dest); - } else { - mp_image_make_writeable(closure->dest); - } - mp_draw_sub_bitmaps(&osd->draw_cache, closure->dest, imgs); - talloc_steal(osd, osd->draw_cache); - closure->changed = true; -} - -// Calls mp_image_make_writeable() on the dest image if something is drawn. -// Returns whether anything was drawn. -bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res, - double video_pts, int draw_flags, struct mp_image *dest) -{ - struct draw_on_image_closure closure = {osd, dest}; - osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats, - &draw_on_image, &closure); - return closure.changed; -} - -// Like osd_draw_on_image(), but if dest needs to be copied to make it -// writeable, allocate images from the given pool. (This is a minor -// optimization to reduce "real" image sized memory allocations.) -void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res, - double video_pts, int draw_flags, - struct mp_image_pool *pool, struct mp_image *dest) -{ - struct draw_on_image_closure closure = {osd, dest, pool}; - osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats, - &draw_on_image, &closure); -} - -void osd_changed(struct osd_state *osd, int new_value) -{ - for (int n = 0; n < MAX_OSD_PARTS; n++) { - if (osd->objs[n]->type == new_value) - osd->objs[n]->force_redraw = true; - } - osd->want_redraw = true; -} - -void osd_changed_all(struct osd_state *osd) -{ - for (int n = 0; n < MAX_OSD_PARTS; n++) - osd_changed(osd, n); -} - -// Scale factor to translate OSD coordinates to what the obj uses internally. -// osd_coordinates * (sh, sh) = obj_coordinates -void osd_object_get_scale_factor(struct osd_state *osd, struct osd_object *obj, - double *sw, double *sh) -{ - int nw, nh; - osd_object_get_resolution(osd, obj, &nw, &nh); - *sw = nw / (double)obj->vo_res.w; - *sh = nh / (double)obj->vo_res.h; -} diff --git a/sub/sub.h b/sub/sub.h deleted file mode 100644 index 64e10193ea..0000000000 --- a/sub/sub.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * This file is part of MPlayer. - * - * MPlayer is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * MPlayer is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with MPlayer; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPLAYER_SUB_H -#define MPLAYER_SUB_H - -#include -#include -#include - -#include "mpvcore/m_option.h" - -// NOTE: VOs must support at least SUBBITMAP_RGBA. -enum sub_bitmap_format { - SUBBITMAP_EMPTY = 0,// no bitmaps; always has num_parts==0 - SUBBITMAP_LIBASS, // A8, with a per-surface blend color (libass.color) - SUBBITMAP_RGBA, // B8G8R8A8 (MSB=A, LSB=B), scaled, premultiplied alpha - SUBBITMAP_INDEXED, // scaled, bitmap points to osd_bmp_indexed - - SUBBITMAP_COUNT -}; - -// For SUBBITMAP_INDEXED -struct osd_bmp_indexed { - uint8_t *bitmap; - // Each entry is like a pixel in SUBBITMAP_RGBA format, but using straight - // alpha. - uint32_t palette[256]; -}; - -struct sub_bitmap { - void *bitmap; - int stride; - // Note: not clipped, going outside the screen area is allowed - // (except for SUBBITMAP_LIBASS, which is always clipped) - int w, h; - int x, y; - int dw, dh; - - union { - struct { - uint32_t color; - } libass; - }; -}; - -struct sub_bitmaps { - // For VO cache state (limited by MAX_OSD_PARTS) - int render_index; - - enum sub_bitmap_format format; - - // If false, dw==w && dh==h. - // SUBBITMAP_LIBASS is never scaled. - bool scaled; - - struct sub_bitmap *parts; - int num_parts; - - // Incremented on each change - int bitmap_id, bitmap_pos_id; -}; - -struct mp_osd_res { - int w, h; // screen dimensions, including black borders - int mt, mb, ml, mr; // borders (top, bottom, left, right) - double display_par; - double video_par; // PAR of the original video (for some sub decoders) -}; - -enum mp_osdtype { - OSDTYPE_SUB, - OSDTYPE_SUBTEXT, - - OSDTYPE_PROGBAR, - OSDTYPE_OSD, - - OSDTYPE_EXTERNAL, - OSDTYPE_EXTERNAL2, - - MAX_OSD_PARTS -}; - -#define OSD_CONV_CACHE_MAX 4 - -struct osd_object { - int type; // OSDTYPE_* - bool is_sub; - - bool force_redraw; - - // caches for OSD conversion (internal to render_object()) - struct osd_conv_cache *cache[OSD_CONV_CACHE_MAX]; - struct sub_bitmaps cached; - - // VO cache state - int vo_bitmap_id; - int vo_bitmap_pos_id; - struct mp_osd_res vo_res; - - // Internally used by osd_libass.c - struct ass_track *osd_track; - struct sub_bitmap *parts_cache; -}; - -struct osd_state { - struct osd_object *objs[MAX_OSD_PARTS]; - - struct ass_library *ass_library; - struct ass_renderer *ass_renderer; - double video_offset; - double vo_pts; - - bool render_subs_in_filter; - bool render_bitmap_subs; - - struct mp_osd_res last_vo_res; - - bool want_redraw; - - // OSDTYPE_OSD - char *osd_text; - // OSDTYPE_SUBTEXT - char *sub_text; - // OSDTYPE_PROGBAR - int progbar_type; // <0: disabled, 1-255: symbol, else: no symbol - float progbar_value; // range 0.0-1.0 - float *progbar_stops; // used for chapter indicators (0.0-1.0 each) - int progbar_num_stops; - // OSDTYPE_EXTERNAL - char *external; - int external_res_x, external_res_y; - // OSDTYPE_EXTERNAL2 - struct sub_bitmaps external2; - // OSDTYPE_SUB - struct dec_sub *dec_sub; - - struct MPOpts *opts; - - // Internal to sub.c - struct mp_draw_sub_cache *draw_cache; - - // Internally used by osd_libass.c - struct ass_renderer *osd_render; - struct ass_library *osd_ass_library; -}; - -// Start of OSD symbols in osd_font.pfb -#define OSD_CODEPOINTS 0xE000 - -// OSD symbols. osd_font.pfb has them starting from codepoint OSD_CODEPOINTS. -// Symbols with a value >= 32 are normal unicode codepoints. -enum mp_osd_font_codepoints { - OSD_PLAY = 0x01, - OSD_PAUSE = 0x02, - OSD_STOP = 0x03, - OSD_REW = 0x04, - OSD_FFW = 0x05, - OSD_CLOCK = 0x06, - OSD_CONTRAST = 0x07, - OSD_SATURATION = 0x08, - OSD_VOLUME = 0x09, - OSD_BRIGHTNESS = 0x0A, - OSD_HUE = 0x0B, - OSD_BALANCE = 0x0C, - OSD_PANSCAN = 0x50, - - OSD_PB_START = 0x10, - OSD_PB_0 = 0x11, - OSD_PB_END = 0x12, - OSD_PB_1 = 0x13, -}; - -struct osd_style_opts { - char *font; - float font_size; - struct m_color color; - struct m_color border_color; - struct m_color shadow_color; - struct m_color back_color; - float border_size; - float shadow_offset; - float spacing; - int margin_x; - int margin_y; - float blur; -}; - -extern const struct m_sub_options osd_style_conf; - -struct osd_state *osd_create(struct MPOpts *opts, struct ass_library *asslib); -void osd_set_text(struct osd_state *osd, const char *text); -void osd_set_sub(struct osd_state *osd, const char *text); -void osd_changed(struct osd_state *osd, int new_value); -void osd_changed_all(struct osd_state *osd); -void osd_free(struct osd_state *osd); - -enum mp_osd_draw_flags { - OSD_DRAW_SUB_FILTER = (1 << 0), - OSD_DRAW_SUB_ONLY = (1 << 1), -}; - -void osd_draw(struct osd_state *osd, struct mp_osd_res res, - double video_pts, int draw_flags, - const bool formats[SUBBITMAP_COUNT], - void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx); - -struct mp_image; -bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res, - double video_pts, int draw_flags, struct mp_image *dest); - -struct mp_image_pool; -void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res, - double video_pts, int draw_flags, - struct mp_image_pool *pool, struct mp_image *dest); - -void osd_object_get_scale_factor(struct osd_state *osd, struct osd_object *obj, - double *sw, double *sh); - -// defined in osd_libass.c and osd_dummy.c - -void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj, - struct sub_bitmaps *out_imgs); -void osd_object_get_resolution(struct osd_state *osd, struct osd_object *obj, - int *out_w, int *out_h); -void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function); -void osd_init_backend(struct osd_state *osd); -void osd_destroy_backend(struct osd_state *osd); - -#endif /* MPLAYER_SUB_H */ -- cgit v1.2.3