diff options
-rw-r--r-- | libvo/video_out.c | 20 | ||||
-rw-r--r-- | libvo/video_out.h | 4 | ||||
-rw-r--r-- | libvo/vo_vdpau.c | 38 | ||||
-rw-r--r-- | mplayer.c | 1 |
4 files changed, 51 insertions, 12 deletions
diff --git a/libvo/video_out.c b/libvo/video_out.c index e796784b1e..82cf0dbbfe 100644 --- a/libvo/video_out.c +++ b/libvo/video_out.c @@ -275,6 +275,11 @@ int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts) } vo->frame_loaded = true; vo->next_pts = pts; + // Guaranteed to support at least DRAW_IMAGE later + if (vo->driver->is_new) { + vo->waiting_mpi = mpi; + return 0; + } if (vo_control(vo, VOCTRL_DRAW_IMAGE, mpi) == VO_NOTIMPL) return -1; return 0; @@ -294,6 +299,7 @@ int vo_get_buffered_frame(struct vo *vo, bool eof) void vo_skip_frame(struct vo *vo) { + vo_control(vo, VOCTRL_SKIPFRAME, NULL); vo->frame_loaded = false; } @@ -310,6 +316,18 @@ int vo_draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h, int return vo->driver->draw_slice(vo, src, stride, w, h, x, y); } +void vo_new_frame_imminent(struct vo *vo) +{ + if (!vo->driver->is_new) + return; + if (vo->driver->buffer_frames) + vo_control(vo, VOCTRL_NEWFRAME, NULL); + else { + vo_control(vo, VOCTRL_DRAW_IMAGE, vo->waiting_mpi); + vo->waiting_mpi = NULL; + } +} + void vo_draw_osd(struct vo *vo, struct osd_state *osd) { if (!vo->config_ok) @@ -466,6 +484,8 @@ int vo_config(struct vo *vo, uint32_t width, uint32_t height, NULL, vo); vo->registered_fd = vo->event_fd; } + vo->frame_loaded = false; + vo->waiting_mpi = NULL; return ret; } diff --git a/libvo/video_out.h b/libvo/video_out.h index bd7b2e8fa5..a710f7de4a 100644 --- a/libvo/video_out.h +++ b/libvo/video_out.h @@ -63,6 +63,8 @@ enum mp_voctrl { VOCTRL_XOVERLAY_SET_COLORKEY, // mp_colorkey_t VOCTRL_XOVERLAY_SET_WIN, + VOCTRL_NEWFRAME, + VOCTRL_SKIPFRAME, VOCTRL_REDRAW_OSD, VOCTRL_ONTOP, @@ -258,6 +260,7 @@ struct vo { int config_count; // Total number of successful config calls bool frame_loaded; // Is there a next frame the VO could flip to? + struct mp_image *waiting_mpi; double next_pts; // pts value of the next frame if any double next_pts2; // optional pts of frame after that @@ -307,6 +310,7 @@ int vo_get_buffered_frame(struct vo *vo, bool eof); void vo_skip_frame(struct vo *vo); int vo_draw_frame(struct vo *vo, uint8_t *src[]); int vo_draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h, int x, int y); +void vo_new_frame_imminent(struct vo *vo); void vo_draw_osd(struct vo *vo, struct osd_state *osd); void vo_flip_page(struct vo *vo, unsigned int pts_us, int duration); void vo_check_events(struct vo *vo); diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index be4540002b..f087f6cf38 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -80,7 +80,7 @@ /* number of video and output surfaces */ #define MAX_OUTPUT_SURFACES 15 #define MAX_VIDEO_SURFACES 50 -#define NUM_BUFFERED_VIDEO 4 +#define NUM_BUFFERED_VIDEO 5 /* number of palette entries */ #define PALETTE_SIZE 256 @@ -295,7 +295,7 @@ static int video_to_output_surface(struct vo *vo) &vc->out_rect_vid); } -static void get_buffered_frame(struct vo *vo, bool eof) +static int next_deint_queue_pos(struct vo *vo, bool eof) { struct vdpctx *vc = vo->priv; @@ -305,15 +305,23 @@ static void get_buffered_frame(struct vo *vo, bool eof) else dqp = vc->deint >= 2 ? dqp - 1 : dqp - 2 | 1; if (dqp < (eof ? 0 : 3)) - return; + return -1; + return dqp; +} + +static void set_next_frame_info(struct vo *vo, bool eof) +{ + struct vdpctx *vc = vo->priv; - dqp = FFMIN(dqp, 4); - vc->deint_queue_pos = dqp; + vo->frame_loaded = false; + int dqp = next_deint_queue_pos(vo, eof); + if (dqp < 0) + return; vo->frame_loaded = true; // Set pts values struct buffered_video_surface *bv = vc->buffered_video; - int idx = vc->deint_queue_pos >> 1; + int idx = dqp >> 1; if (idx == 0) { // no future frame/pts available vo->next_pts = bv[0].pts; vo->next_pts2 = MP_NOPTS_VALUE; @@ -327,7 +335,7 @@ static void get_buffered_frame(struct vo *vo, bool eof) intermediate_pts = (bv[idx].pts + bv[idx - 1].pts) / 2; else intermediate_pts = bv[idx].pts; - if (vc->deint_queue_pos & 1) { // first field + if (dqp & 1) { // first field vo->next_pts = bv[idx].pts; vo->next_pts2 = intermediate_pts; } else { @@ -335,8 +343,6 @@ static void get_buffered_frame(struct vo *vo, bool eof) vo->next_pts2 = bv[idx - 1].pts; } } - - video_to_output_surface(vo); } static void add_new_video_surface(struct vo *vo, VdpVideoSurface surface, @@ -358,8 +364,9 @@ static void add_new_video_surface(struct vo *vo, VdpVideoSurface surface, .pts = pts, }; - vc->deint_queue_pos += 2; - get_buffered_frame(vo, false); + vc->deint_queue_pos = FFMIN(vc->deint_queue_pos + 2, + NUM_BUFFERED_VIDEO * 2 - 3); + set_next_frame_info(vo, false); } static void forget_frames(struct vo *vo) @@ -1858,6 +1865,13 @@ static int control(struct vo *vo, uint32_t request, void *data) r->mt = r->mb = vc->border_y; return VO_TRUE; } + case VOCTRL_NEWFRAME: + vc->deint_queue_pos = next_deint_queue_pos(vo, true); + video_to_output_surface(vo); + return true; + case VOCTRL_SKIPFRAME: + vc->deint_queue_pos = next_deint_queue_pos(vo, true); + return true; case VOCTRL_REDRAW_OSD: video_to_output_surface(vo); draw_eosd(vo); @@ -1892,7 +1906,7 @@ const struct vo_driver video_out_vdpau = { .config = config, .control = control, .draw_image = draw_image, - .get_buffered_frame = get_buffered_frame, + .get_buffered_frame = set_next_frame_info, .draw_slice = draw_slice, .draw_osd = draw_osd, .flip_page_timed = flip_page_timed, @@ -3672,6 +3672,7 @@ static void run_playloop(struct MPContext *mpctx) current_module = "flip_page"; if (!frame_time_remaining && blit_frame) { + vo_new_frame_imminent(mpctx->video_out); struct sh_video *sh_video = mpctx->sh_video; mpctx->video_pts = sh_video->pts; update_subtitles(mpctx, sh_video->pts, mpctx->video_offset, false); |