mirror of https://github.com/mpv-player/mpv
player: make screenshot each-frame mode more accurate
Due to asynchronicity, we generally can't guarantee that a video frame matches up with other events such as playback time change exactly (since decoding, presentation, and property update all happen at different times). This is a complaint in the referenced bug report, where screenshot filenames in each-frame screenshot did not use the correct timestamp, and instead was lagging behind by 1 frame. But in this case, synchronicity was already pretty much forced with wait calls. The only problem was that the playback time was updated at a later time, which results in the observed 1 frame lag. Fix this by moving the place where the screenshot is triggered in this mode. Normal screenshots may still have the old problem. There is no effort made to guarantee the timestamps absolutely line up, same as with the OSD. (If you want a guarantee, you need to use a video filter, such as libavfilter's drawtext. These will obviously use the proper timestamp, instead of going through the somewhat asynchronous property etc. system in the player frontend.) Fixes: #7433
This commit is contained in:
parent
3d17e19c2c
commit
a3bd8c3b5f
|
@ -49,6 +49,7 @@
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
#include "screenshot.h"
|
||||||
|
|
||||||
// Wait until mp_wakeup_core() is called, since the last time
|
// Wait until mp_wakeup_core() is called, since the last time
|
||||||
// mp_wait_events() was called.
|
// mp_wait_events() was called.
|
||||||
|
@ -1226,6 +1227,8 @@ void run_playloop(struct MPContext *mpctx)
|
||||||
if (mpctx->video_status == STATUS_EOF)
|
if (mpctx->video_status == STATUS_EOF)
|
||||||
update_subtitles(mpctx, mpctx->playback_pts);
|
update_subtitles(mpctx, mpctx->playback_pts);
|
||||||
|
|
||||||
|
handle_each_frame_screenshot(mpctx);
|
||||||
|
|
||||||
handle_eof(mpctx);
|
handle_eof(mpctx);
|
||||||
|
|
||||||
handle_loop_file(mpctx);
|
handle_loop_file(mpctx);
|
||||||
|
|
|
@ -53,6 +53,7 @@ typedef struct screenshot_ctx {
|
||||||
struct mp_cmd *each_frame;
|
struct mp_cmd *each_frame;
|
||||||
|
|
||||||
int frameno;
|
int frameno;
|
||||||
|
uint64_t last_frame_count;
|
||||||
} screenshot_ctx;
|
} screenshot_ctx;
|
||||||
|
|
||||||
void screenshot_init(struct MPContext *mpctx)
|
void screenshot_init(struct MPContext *mpctx)
|
||||||
|
@ -529,13 +530,17 @@ static void screenshot_fin(struct mp_cmd_ctx *cmd)
|
||||||
mp_wakeup_core(mpctx);
|
mp_wakeup_core(mpctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screenshot_flip(struct MPContext *mpctx)
|
void handle_each_frame_screenshot(struct MPContext *mpctx)
|
||||||
{
|
{
|
||||||
screenshot_ctx *ctx = mpctx->screenshot_ctx;
|
screenshot_ctx *ctx = mpctx->screenshot_ctx;
|
||||||
|
|
||||||
if (!ctx->each_frame)
|
if (!ctx->each_frame)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (ctx->last_frame_count == mpctx->shown_vframes)
|
||||||
|
return;
|
||||||
|
ctx->last_frame_count = mpctx->shown_vframes;
|
||||||
|
|
||||||
struct mp_waiter wait = MP_WAITER_INITIALIZER;
|
struct mp_waiter wait = MP_WAITER_INITIALIZER;
|
||||||
void *a[] = {mpctx, &wait};
|
void *a[] = {mpctx, &wait};
|
||||||
run_command(mpctx, mp_cmd_clone(ctx->each_frame), NULL, screenshot_fin, a);
|
run_command(mpctx, mp_cmd_clone(ctx->each_frame), NULL, screenshot_fin, a);
|
||||||
|
|
|
@ -28,8 +28,8 @@ struct mpv_global;
|
||||||
// One time initialization at program start.
|
// One time initialization at program start.
|
||||||
void screenshot_init(struct MPContext *mpctx);
|
void screenshot_init(struct MPContext *mpctx);
|
||||||
|
|
||||||
// Called by the playback core code when a new frame is displayed.
|
// Called by the playback core on each iteration.
|
||||||
void screenshot_flip(struct MPContext *mpctx);
|
void handle_each_frame_screenshot(struct MPContext *mpctx);
|
||||||
|
|
||||||
/* Return the image converted to the given format. If the pixel aspect ratio is
|
/* Return the image converted to the given format. If the pixel aspect ratio is
|
||||||
* not 1:1, the image is scaled as well. Returns NULL on failure.
|
* not 1:1, the image is scaled as well. Returns NULL on failure.
|
||||||
|
|
|
@ -1224,8 +1224,6 @@ void write_video(struct MPContext *mpctx)
|
||||||
|
|
||||||
vo_c->underrun_signaled = false;
|
vo_c->underrun_signaled = false;
|
||||||
|
|
||||||
screenshot_flip(mpctx);
|
|
||||||
|
|
||||||
mp_wakeup_core(mpctx);
|
mp_wakeup_core(mpctx);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue