stream: turn the highlight fields into mp_dvdnav_highlight

The highlight rectangle and palette were passed around as loose fields
in three places. Bundle them into a struct, pass the whole nav state to
the sd_lavc control.
This commit is contained in:
Kacper Michajłow committed 2026-08-26 01:47:41 +02:00
1 parent c7859fe5b6
commit c9422ff88f
5 files changed
+53 -70

No files matched your search

+5 -16
View File
@@ -153,25 +153,13 @@ bool disc_nav_mouse_pos_to_src(struct MPContext *mpctx, int src_w, int src_h,
}
// Push the current menu/highlight state to the dvd_subtitle decoders.
static void push_dvd_overlay(struct MPContext *mpctx,
struct stream_nav_state *nav, bool visible)
static void push_dvd_overlay(struct MPContext *mpctx, struct stream_nav_state *nav)
{
struct mp_dvdnav_hli hli = {
.show = visible,
.change_id = nav->change_id,
};
if (visible) {
hli.x = nav->hl_x;
hli.y = nav->hl_y;
hli.w = nav->hl_w;
hli.h = nav->hl_h;
memcpy(hli.palette, nav->hl_palette, sizeof(hli.palette));
}
for (int n = 0; n < mpctx->num_tracks; n++) {
struct track *t = mpctx->tracks[n];
if (!is_dvd_sub_track(t) || !t->d_sub)
continue;
sub_control(t->d_sub, SD_CTRL_APPLY_DVDNAV, &hli);
sub_control(t->d_sub, SD_CTRL_APPLY_DVDNAV, nav);
}
}
@@ -494,12 +482,13 @@ void disc_nav_update(struct MPContext *mpctx)
sync_disc_track_selection(mpctx, s, &nav);
bool is_bd = strcmp(s->info->name, "bd") == 0 || strcmp(s->info->name, "bdmv/bluray") == 0;
bool visible = nav.menu_active && (is_bd || (nav.hl_w > 0 && nav.hl_h > 0));
bool visible = nav.menu_active &&
(is_bd || (mp_rect_w(nav.hl.rect) > 0 && mp_rect_h(nav.hl.rect) > 0));
if (is_bd) {
push_bd_overlay(mpctx, s, &nav, visible);
} else {
push_dvd_overlay(mpctx, &nav, visible);
push_dvd_overlay(mpctx, &nav);
ensure_menu_sub_selection(mpctx, nav.menu_active);
}
+8 -3
View File
@@ -25,6 +25,7 @@
#include <inttypes.h>
#include <sys/types.h>
#include "common/common.h"
#include "misc/bstr.h"
// Minimum guaranteed buffer and seek-back size. For any reads <= of this size,
@@ -142,6 +143,12 @@ static inline bool stream_nav_action_activates(enum stream_nav_action a)
}
}
// A DVD subpicture button highlight.
struct mp_dvdnav_highlight {
struct mp_rect rect; // button rectangle in SPU/source coords
uint32_t palette[4]; // replacement colors for SPU pixel values 0..3
};
// Snapshot of the stream's menu state.
struct stream_nav_state {
bool nav_active; // interactive disc navigation is enabled
@@ -149,9 +156,7 @@ struct stream_nav_state {
bool has_popup; // disc supports a popup menu (BD only)
bool still_active; // holding an indefinite still frame
int src_w, src_h; // dimensions of the coordinate space mouse uses
// Highlight rectangle of the currently focused button (in src coords).
int hl_x, hl_y, hl_w, hl_h;
uint32_t hl_palette[4]; // BGRA highlight palette (0xAARRGGBB, straight)
struct mp_dvdnav_highlight hl; // focused button highlight (DVD only)
uint32_t change_id; // Bumped whenever any of the above changes
uint32_t discontinuity_id; // Bumped when the stream's source position jumps
+13 -25
View File
@@ -79,8 +79,7 @@ struct priv {
bool in_menu;
int current_button; // mirror of libdvdnav HL_BTNN_REG
int btn_rect[4]; // x, y, w, h in source coords
uint32_t hl_palette[4]; // 0xAARRGGBB for SPU pixel values 0..3
struct mp_dvdnav_highlight hl; // focused button rect + palette
uint32_t nav_change_id;
uint32_t discontinuity_id; // bumped on actions that may jump
bool pending_drain; // emit one EOF at the next jump boundary
@@ -241,8 +240,7 @@ static bool in_menu_domain(dvdnav_t *dvdnav)
static void compute_button_rect(struct priv *priv, pci_t *pci, int btn)
{
priv->btn_rect[0] = priv->btn_rect[1] = 0;
priv->btn_rect[2] = priv->btn_rect[3] = 0;
priv->hl.rect = (struct mp_rect){0};
if (btn <= 0 || btn > pci->hli.hl_gi.btn_ns)
return;
// btni_t is packed and full of bitfields, memcpy to ensure correct alignment.
@@ -250,10 +248,11 @@ static void compute_button_rect(struct priv *priv, pci_t *pci, int btn)
memcpy(&b, &pci->hli.btnit[btn - 1], sizeof(b));
int xs = b.x_start, xe = b.x_end;
int ys = b.y_start, ye = b.y_end;
priv->btn_rect[0] = xs;
priv->btn_rect[1] = ys;
priv->btn_rect[2] = xe > xs ? xe - xs : 0;
priv->btn_rect[3] = ye > ys ? ye - ys : 0;
priv->hl.rect = (struct mp_rect){
.x0 = xs, .y0 = ys,
.x1 = xe > xs ? xe : xs,
.y1 = ye > ys ? ye : ys,
};
}
// Resolve the 4-entry "select-state" highlight palette for the focused button.
@@ -262,7 +261,7 @@ static void compute_button_rect(struct priv *priv, pci_t *pci, int btn)
// alphas.
static void compute_highlight_palette(struct priv *priv, pci_t *pci, int btn)
{
memset(priv->hl_palette, 0, sizeof(priv->hl_palette));
memset(priv->hl.palette, 0, sizeof(priv->hl.palette));
if (!priv->spu_clut_valid || btn <= 0 || btn > pci->hli.hl_gi.btn_ns)
return;
btni_t b;
@@ -289,7 +288,7 @@ static void compute_highlight_palette(struct priv *priv, pci_t *pci, int btn)
int c[3];
mp_map_fixp_color(&cmatrix, 8, y, 8, c);
uint32_t alpha = (a << 4) | a;
priv->hl_palette[i] = (alpha << 24) | (c[0] << 16) | (c[1] << 8) | c[2];
priv->hl.palette[i] = (alpha << 24) | (c[0] << 16) | (c[1] << 8) | c[2];
}
}
@@ -334,11 +333,8 @@ static void refresh_video_resolution(struct priv *priv)
static void update_highlight(struct priv *priv)
{
int prev_btn = priv->current_button;
int prev_x = priv->btn_rect[0], prev_y = priv->btn_rect[1];
int prev_w = priv->btn_rect[2], prev_h = priv->btn_rect[3];
bool prev_menu = priv->in_menu;
uint32_t prev_palette[4];
memcpy(prev_palette, priv->hl_palette, sizeof(prev_palette));
struct mp_dvdnav_highlight prev_hl = priv->hl;
priv->in_menu = in_menu_domain(priv->dvdnav);
pci_t *pci = priv->in_menu ? dvdnav_get_current_nav_pci(priv->dvdnav) : NULL;
@@ -362,9 +358,7 @@ static void update_highlight(struct priv *priv)
if (!highlight_live || btn <= 0 || btn > pci->hli.hl_gi.btn_ns) {
priv->current_button = 0;
priv->btn_rect[0] = priv->btn_rect[1] = 0;
priv->btn_rect[2] = priv->btn_rect[3] = 0;
memset(priv->hl_palette, 0, sizeof(priv->hl_palette));
priv->hl = (struct mp_dvdnav_highlight){0};
} else {
priv->current_button = btn;
compute_button_rect(priv, pci, btn);
@@ -372,9 +366,7 @@ static void update_highlight(struct priv *priv)
}
if (priv->in_menu != prev_menu || priv->current_button != prev_btn ||
priv->btn_rect[0] != prev_x || priv->btn_rect[1] != prev_y ||
priv->btn_rect[2] != prev_w || priv->btn_rect[3] != prev_h ||
memcmp(prev_palette, priv->hl_palette, sizeof(prev_palette)) != 0)
memcmp(&prev_hl, &priv->hl, sizeof(prev_hl)) != 0)
{
priv->nav_change_id++;
}
@@ -909,10 +901,7 @@ static int control(stream_t *stream, int cmd, void *arg)
.still_active = priv->still_active,
.src_w = priv->src_w,
.src_h = priv->src_h,
.hl_x = priv->btn_rect[0],
.hl_y = priv->btn_rect[1],
.hl_w = priv->btn_rect[2],
.hl_h = priv->btn_rect[3],
.hl = priv->hl,
.change_id = priv->nav_change_id,
.discontinuity_id = priv->discontinuity_id,
.active_audio_id = dvd_physical_audio_to_substream(priv, priv->audio_physical),
@@ -921,7 +910,6 @@ static int control(stream_t *stream, int cmd, void *arg)
.angle = cur_angle,
.num_angles = num_angles,
};
memcpy(st->hl_palette, priv->hl_palette, sizeof(st->hl_palette));
return STREAM_OK;
}
}
+2 -8
View File
@@ -5,6 +5,7 @@
#include <stdint.h>
#include "player/core.h"
#include "stream/stream.h"
#include "osd.h"
struct sh_stream;
@@ -21,14 +22,7 @@ enum sd_ctrl {
SD_CTRL_SET_VIDEO_DEF_FPS,
SD_CTRL_RESET_SOFT,
SD_CTRL_UPDATE_OPTS,
SD_CTRL_APPLY_DVDNAV, // struct mp_dvdnav_hli *
};
struct mp_dvdnav_hli {
bool show;
int x, y, w, h; // button rect in SPU/source coords
uint32_t palette[4]; // 0xAARRGGBB, straight alpha
uint32_t change_id; // bumped on any visible change
SD_CTRL_APPLY_DVDNAV, // const struct stream_nav_state *
};
enum sd_text_type {
+25 -18
View File
@@ -72,8 +72,9 @@ struct sd_lavc_priv {
int num_seekpoints;
struct bitmap_packer *packer;
// DVD-nav per-pixel highlight overlay state.
struct mp_dvdnav_hli hli;
// DVD-nav menu/highlight overlay state.
bool menu_active; // in-menu: gates the highlight overlay
struct mp_dvdnav_highlight hl; // focused button rect + palette
uint32_t hli_change_id;
};
@@ -300,21 +301,20 @@ static void read_sub_bitmaps(struct sd *sd, struct sub *sub)
convert_pal(pal, 256, opts->sub_gray);
// DVD navigation highlight
bool hli_active = priv->hli.show &&
priv->hli.w > 0 && priv->hli.h > 0 &&
r->x < priv->hli.x + priv->hli.w &&
r->y < priv->hli.y + priv->hli.h &&
r->x + r->w > priv->hli.x &&
r->y + r->h > priv->hli.y;
struct mp_rect hlr = priv->hl.rect;
bool hli_active = priv->menu_active &&
mp_rect_w(hlr) > 0 && mp_rect_h(hlr) > 0 &&
r->x < hlr.x1 && r->y < hlr.y1 &&
r->x + r->w > hlr.x0 && r->y + r->h > hlr.y0;
uint32_t hli_pal[4] = {0};
if (hli_active) {
memcpy(hli_pal, priv->hli.palette, sizeof(hli_pal));
memcpy(hli_pal, priv->hl.palette, sizeof(hli_pal));
convert_pal(hli_pal, 4, opts->sub_gray);
}
int hli_x0 = priv->hli.x - r->x;
int hli_y0 = priv->hli.y - r->y;
int hli_x1 = hli_x0 + priv->hli.w;
int hli_y1 = hli_y0 + priv->hli.h;
int hli_x0 = hlr.x0 - r->x;
int hli_y0 = hlr.y0 - r->y;
int hli_x1 = hlr.x1 - r->x;
int hli_y1 = hlr.y1 - r->y;
for (int y = -padding; y < b->h + padding; y++) {
uint32_t *out = (uint32_t*)((char*)b->bitmap + y * b->stride);
@@ -760,12 +760,19 @@ static int control(struct sd *sd, enum sd_ctrl cmd, void *arg)
priv->video_params = *(struct mp_image_params *)arg;
return CONTROL_OK;
case SD_CTRL_APPLY_DVDNAV: {
struct mp_dvdnav_hli *hli = arg;
if (priv->hli_change_id == hli->change_id)
return CONTROL_OK;
priv->hli = *hli;
priv->hli_change_id = hli->change_id;
const struct stream_nav_state *nav = arg;
bool menu_closed = priv->menu_active && !nav->menu_active;
bool changed = priv->hli_change_id != nav->change_id;
priv->menu_active = nav->menu_active;
priv->hl = nav->hl;
priv->hli_change_id = nav->change_id;
// Don't let menu subpictures leak into title playback.
if (menu_closed) {
for (int n = 0; n < MAX_QUEUE; n++)
clear_sub(&priv->subs[n]);
}
// Re-render any decoded subtitles, after style update.
if (changed)
rerender_queued_subs(sd);
return CONTROL_OK;
}