vo: replace VOCTRL_HDR_METADATA with direct VO params read

Currently VOCTRL are completely unusable for frequent data query. Since
the HDR parameter addition to video-params, the parameters can change
each frame. In which case observe on those parameter would be triggered
constantly. The problem is that quering those parameters involves VOCTRL
which in turn involves whole render cycle of delay.

Instead update VO params on each draw_frame. This requires changes to VO
reconfiguration condition, but in practice it should only be triggered
when image size or data layout changes. In other cases it will be
handled internal by VO driver.

I'm not quite happy with this solution, but don't see better one without
changing observe/notify logic significantly. There is no good way
currently to handle VOCTRL that are constantly queried.

This adds unfortunate synchronization of player command with VO thread,
but there is not way around that and if too frequent queries of this
param becomes a problem we can thing of other solutions.

Changes the way to get data from VO driver added by a98c5328dc

Fixes: 84de84b
Fixes: #12825
This commit is contained in:
Kacper Michajłow 2023-11-07 00:52:56 +01:00 committed by Dudemanguy
parent a96d26e63a
commit 477a0f8318
5 changed files with 36 additions and 28 deletions

View File

@ -2372,17 +2372,16 @@ static struct mp_image_params get_video_out_params(struct MPContext *mpctx)
static int mp_property_vo_imgparams(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
struct vo *vo = mpctx->video_out;
if (!vo)
return M_PROPERTY_UNAVAILABLE;
int valid = m_property_read_sub_validate(ctx, prop, action, arg);
if (valid != M_PROPERTY_VALID)
return valid;
struct mp_image_params p = get_video_out_params(ctx);
MPContext *mpctx = ctx;
if (mpctx->video_out)
vo_control(mpctx->video_out, VOCTRL_HDR_METADATA, &p.color.hdr);
return property_imgparams(p, action, arg);
return property_imgparams(vo_get_current_params(vo), action, arg);
}
static int mp_property_dec_imgparams(void *ctx, struct m_property *prop,

View File

@ -1034,6 +1034,19 @@ static void apply_video_crop(struct MPContext *mpctx, struct vo *vo)
}
}
static bool video_reconfig_needed(const struct mp_image_params *p1,
const struct mp_image_params *p2)
{
return p1->imgfmt != p2->imgfmt ||
p1->hw_subfmt != p2->hw_subfmt ||
p1->w != p2->w || p1->h != p2->h ||
p1->p_w != p2->p_w || p1->p_h != p2->p_h ||
p1->force_window != p2->force_window ||
p1->rotate != p2->rotate ||
p1->stereo3d != p2->stereo3d ||
!mp_rect_equals(&p1->crop, &p2->crop);
}
void write_video(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
@ -1156,7 +1169,7 @@ void write_video(struct MPContext *mpctx)
// Filter output is different from VO input?
struct mp_image_params *p = &mpctx->next_frames[0]->params;
if (!vo->params || !mp_image_params_equal(p, vo->params)) {
if (!vo->params || video_reconfig_needed(p, vo->params)) {
// Changing config deletes the current frame; wait until it's finished.
if (vo_still_displaying(vo))
return;

View File

@ -1422,3 +1422,13 @@ int lookup_keymap_table(const struct mp_keymap *map, int key)
map++;
return map->to;
}
struct mp_image_params vo_get_current_params(struct vo *vo)
{
struct mp_image_params p = {0};
mp_mutex_lock(&vo->in->lock);
if (vo->params)
p = *vo->params;
mp_mutex_unlock(&vo->in->lock);
return p;
}

View File

@ -122,8 +122,6 @@ enum mp_voctrl {
/* private to vo_gpu and vo_gpu_next */
VOCTRL_EXTERNAL_RESIZE,
VOCTRL_HDR_METADATA, // struct pl_hdr_metadata*
};
// Helper to expose what kind of content is currently playing to the VO.
@ -536,4 +534,6 @@ void vo_get_src_dst_rects(struct vo *vo, struct mp_rect *out_src,
struct vo_frame *vo_frame_ref(struct vo_frame *frame);
struct mp_image_params vo_get_current_params(struct vo *vo);
#endif /* MPLAYER_VIDEO_OUT_H */

View File

@ -153,8 +153,6 @@ struct priv {
bool target_hint;
float corner_rounding;
struct pl_hdr_metadata last_hdr_metadata;
};
static void update_render_options(struct vo *vo);
@ -1033,19 +1031,11 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame)
goto done;
}
const struct pl_frame *cur_frame = NULL;
for (int i = 0; i < mix.num_frames; i++) {
if (mix.timestamps[i] > 0.0f)
break;
cur_frame = mix.frames[i];
}
if (cur_frame) {
p->last_hdr_metadata = cur_frame->color.hdr;
const struct pl_frame *cur_frame = pl_frame_mix_nearest(&mix);
if (cur_frame && vo->params) {
vo->params->color.hdr = cur_frame->color.hdr;
// Augment metadata with peak detection max_pq_y / avg_pq_y
pl_renderer_get_hdr_metadata(p->rr, &p->last_hdr_metadata);
} else {
p->last_hdr_metadata = (struct pl_hdr_metadata){0};
pl_renderer_get_hdr_metadata(p->rr, &vo->params->color.hdr);
}
p->is_interpolated = mix.num_frames > 1;
@ -1430,10 +1420,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
return true;
}
case VOCTRL_HDR_METADATA:
*(struct pl_hdr_metadata *) data = p->last_hdr_metadata;
return true;
case VOCTRL_SCREENSHOT:
video_screenshot(vo, data);
return true;