diff options
-rw-r--r-- | command.c | 8 | ||||
-rw-r--r-- | libmpcodecs/ad_ffmpeg.c | 2 | ||||
-rw-r--r-- | libmpcodecs/dec_video.c | 8 | ||||
-rw-r--r-- | libmpcodecs/dec_video.h | 1 | ||||
-rw-r--r-- | libmpcodecs/vf.h | 1 | ||||
-rw-r--r-- | libmpcodecs/vf_ass.c | 2 | ||||
-rw-r--r-- | libmpcodecs/vf_expand.c | 6 | ||||
-rw-r--r-- | libmpcodecs/vf_vo.c | 7 | ||||
-rw-r--r-- | libmpcodecs/vfcap.h | 2 | ||||
-rw-r--r-- | libvo/video_out.c | 40 | ||||
-rw-r--r-- | libvo/video_out.h | 9 | ||||
-rw-r--r-- | libvo/vo_gl.c | 33 | ||||
-rw-r--r-- | libvo/vo_vdpau.c | 79 | ||||
-rw-r--r-- | libvo/vo_xv.c | 77 | ||||
-rw-r--r-- | mplayer.c | 40 | ||||
-rw-r--r-- | sub/sub.h | 1 |
16 files changed, 160 insertions, 156 deletions
@@ -287,19 +287,21 @@ static int mp_property_playback_speed(m_option_t *prop, int action, void *arg, MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; + double orig_speed = opts->playback_speed; switch (action) { case M_PROPERTY_SET: if (!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop, *(float *) arg); opts->playback_speed = *(float *) arg; - reinit_audio_chain(mpctx); - return M_PROPERTY_OK; + goto set; case M_PROPERTY_STEP_UP: case M_PROPERTY_STEP_DOWN: opts->playback_speed += (arg ? *(float *) arg : 0.1) * (action == M_PROPERTY_STEP_DOWN ? -1 : 1); + set: M_PROPERTY_CLAMP(prop, opts->playback_speed); + // Adjust time until next frame flip for nosound mode + mpctx->time_frame *= orig_speed / opts->playback_speed; reinit_audio_chain(mpctx); return M_PROPERTY_OK; } diff --git a/libmpcodecs/ad_ffmpeg.c b/libmpcodecs/ad_ffmpeg.c index ae7f36b791..762c80282d 100644 --- a/libmpcodecs/ad_ffmpeg.c +++ b/libmpcodecs/ad_ffmpeg.c @@ -214,7 +214,7 @@ static void uninit(sh_audio_t *sh) AVCodecContext *lavc_context = ctx->avctx; if (lavc_context) { - if (avcodec_close(lavc_context) < 0) + if (lavc_context->codec && avcodec_close(lavc_context) < 0) mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not close codec.\n"); av_freep(&lavc_context->extradata); av_freep(&lavc_context); diff --git a/libmpcodecs/dec_video.c b/libmpcodecs/dec_video.c index cd3083faa4..14cf029fbe 100644 --- a/libmpcodecs/dec_video.c +++ b/libmpcodecs/dec_video.c @@ -195,14 +195,6 @@ int set_rectangle(sh_video_t *sh_video, int param, int value) return 0; } -int redraw_osd(struct sh_video *sh_video, struct osd_state *osd) -{ - struct vf_instance *vf = sh_video->vfilter; - if (vf->control(vf, VFCTRL_REDRAW_OSD, osd) == true) - return 0; - return -1; -} - void resync_video_stream(sh_video_t *sh_video) { const struct vd_functions *vd = sh_video->vd_driver; diff --git a/libmpcodecs/dec_video.h b/libmpcodecs/dec_video.h index f7210e02c3..ab4b55bef7 100644 --- a/libmpcodecs/dec_video.h +++ b/libmpcodecs/dec_video.h @@ -44,7 +44,6 @@ struct mp_csp_details; void get_detected_video_colorspace(struct sh_video *sh, struct mp_csp_details *csp); void set_video_colorspace(struct sh_video *sh); int set_rectangle(sh_video_t *sh_video, int param, int value); -int redraw_osd(struct sh_video *sh_video, struct osd_state *osd); void resync_video_stream(sh_video_t *sh_video); void video_reset_aspect(struct sh_video *sh_video); int get_current_video_decoder_lag(sh_video_t *sh_video); diff --git a/libmpcodecs/vf.h b/libmpcodecs/vf.h index 0dac19c9f6..d97e363778 100644 --- a/libmpcodecs/vf.h +++ b/libmpcodecs/vf.h @@ -112,7 +112,6 @@ struct vf_ctrl_screenshot { /* Hack to make the OSD state object available to vf_expand and vf_ass which * access OSD/subtitle state outside of normal OSD draw time. */ #define VFCTRL_SET_OSD_OBJ 20 -#define VFCTRL_REDRAW_OSD 21 // Change user-visible OSD immediately #define VFCTRL_SET_YUV_COLORSPACE 22 // arg is struct mp_csp_details* #define VFCTRL_GET_YUV_COLORSPACE 23 // arg is struct mp_csp_details* diff --git a/libmpcodecs/vf_ass.c b/libmpcodecs/vf_ass.c index c5613ce992..a062149364 100644 --- a/libmpcodecs/vf_ass.c +++ b/libmpcodecs/vf_ass.c @@ -463,7 +463,7 @@ static int vf_open(vf_instance_t *vf, char *args) vf->control = control; vf->get_image = get_image; vf->put_image = put_image; - vf->default_caps = VFCAP_EOSD; + vf->default_caps = VFCAP_EOSD | VFCAP_EOSD_FILTER; return 1; } diff --git a/libmpcodecs/vf_expand.c b/libmpcodecs/vf_expand.c index 95580b9f26..a640108e0e 100644 --- a/libmpcodecs/vf_expand.c +++ b/libmpcodecs/vf_expand.c @@ -452,10 +452,6 @@ static int control(struct vf_instance *vf, int request, void* data){ case VFCTRL_DRAW_OSD: if(vf->priv->osd_enabled) return CONTROL_TRUE; break; - case VFCTRL_REDRAW_OSD: - if (vf->priv->osd_enabled) - return false; - break; } #endif return vf_next_control(vf,request,data); @@ -481,6 +477,8 @@ static int vf_open(vf_instance_t *vf, char *args){ vf->priv->osd_enabled, vf->priv->aspect, vf->priv->round); + if (vf->priv->osd_enabled) + vf->default_caps = VFCAP_OSD_FILTER; return 1; } diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c index 499184d37f..d673c7bcd4 100644 --- a/libmpcodecs/vf_vo.c +++ b/libmpcodecs/vf_vo.c @@ -117,8 +117,6 @@ static int control(struct vf_instance *vf, int request, void* data) if(!video_out->config_ok) return CONTROL_FALSE; // vo not configured? vo_draw_osd(video_out, data); return CONTROL_TRUE; - case VFCTRL_REDRAW_OSD: - return vo_control(video_out, VOCTRL_REDRAW_OSD, data) == true; case VFCTRL_SET_EQUALIZER: { vf_equalizer_t *eq=data; @@ -153,7 +151,6 @@ static int control(struct vf_instance *vf, int request, void* data) { struct osd_state *osd = data; mp_eosd_images_t images = {NULL, 2}; - double pts = video_out->next_pts; ASS_Renderer *renderer; double scale; if (osd->vsfilter_aspect && vf->opts->ass_vsfilter_aspect_compat) { @@ -168,7 +165,7 @@ static int control(struct vf_instance *vf, int request, void* data) if (osd->ass_track_changed) vf->priv->prev_visibility = false; osd->ass_track_changed = false; - if (sub_visibility && osd->ass_track && (pts != MP_NOPTS_VALUE)) { + if (sub_visibility && osd->ass_track && (osd->pts != MP_NOPTS_VALUE)) { struct mp_eosd_res res = {0}; if (vo_control(video_out, VOCTRL_GET_EOSD_RES, &res) == VO_TRUE) { ass_set_frame_size(renderer, res.w, res.h); @@ -181,7 +178,7 @@ static int control(struct vf_instance *vf, int request, void* data) mp_ass_reload_options(vf->priv->renderer_vsfilter, vf->opts); } images.imgs = ass_render_frame(renderer, osd->ass_track, - (pts+sub_delay) * 1000 + .5, + (osd->pts+sub_delay) * 1000 + .5, &images.changed); if (!vf->priv->prev_visibility || osd->ass_force_reload) images.changed = 2; diff --git a/libmpcodecs/vfcap.h b/libmpcodecs/vfcap.h index 611d642869..c9b943177d 100644 --- a/libmpcodecs/vfcap.h +++ b/libmpcodecs/vfcap.h @@ -52,5 +52,7 @@ #define VFCAP_EOSD_UNSCALED 0x4000 // used by libvo and vf_vo, indicates the VO does not support draw_slice for this format #define VOCAP_NOSLICES 0x8000 +#define VFCAP_OSD_FILTER 0x10000 // OSD is drawn in filter chain +#define VFCAP_EOSD_FILTER 0x20000 // EOSD is drawn in filter chain #endif /* MPLAYER_VFCAP_H */ diff --git a/libvo/video_out.c b/libvo/video_out.c index 2333afcb80..205d618878 100644 --- a/libvo/video_out.c +++ b/libvo/video_out.c @@ -275,11 +275,27 @@ 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; } +int vo_redraw_frame(struct vo *vo) +{ + if (!vo->config_ok) + return -1; + if (vo_control(vo, VOCTRL_REDRAW_FRAME, NULL) == true) { + vo->redrawing = true; + return 0; + } + return -1; +} + int vo_get_buffered_frame(struct vo *vo, bool eof) { if (!vo->config_ok) @@ -294,6 +310,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 +327,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) @@ -321,8 +350,12 @@ void vo_flip_page(struct vo *vo, unsigned int pts_us, int duration) { if (!vo->config_ok) return; - vo->frame_loaded = false; - vo->next_pts = MP_NOPTS_VALUE; + if (!vo->redrawing) { + vo->frame_loaded = false; + vo->next_pts = MP_NOPTS_VALUE; + } + vo->want_redraw = false; + vo->redrawing = false; if (vo->driver->flip_page_timed) vo->driver->flip_page_timed(vo, pts_us, duration); else @@ -466,6 +499,9 @@ 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; + vo->redrawing = false; return ret; } diff --git a/libvo/video_out.h b/libvo/video_out.h index e5d2f78c8a..06c606f4d2 100644 --- a/libvo/video_out.h +++ b/libvo/video_out.h @@ -63,7 +63,9 @@ enum mp_voctrl { VOCTRL_XOVERLAY_SET_COLORKEY, // mp_colorkey_t VOCTRL_XOVERLAY_SET_WIN, - VOCTRL_REDRAW_OSD, + VOCTRL_NEWFRAME, + VOCTRL_SKIPFRAME, + VOCTRL_REDRAW_FRAME, VOCTRL_ONTOP, VOCTRL_ROOTWIN, @@ -258,8 +260,11 @@ 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 + bool want_redraw; // visible frame wrong (window resize), needs refresh + bool redrawing; // between redrawing frame and flipping it double flip_queue_offset; // queue flip events at most this much in advance @@ -303,10 +308,12 @@ void list_video_out(void); int vo_control(struct vo *vo, uint32_t request, void *data); int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts); +int vo_redraw_frame(struct vo *vo); 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_gl.c b/libvo/vo_gl.c index dbaef279d8..e68465f009 100644 --- a/libvo/vo_gl.c +++ b/libvo/vo_gl.c @@ -127,8 +127,6 @@ struct gl_priv { int mipmap_gen; int stereo_mode; - int int_pause; - struct mp_csp_equalizer video_eq; int texture_width; @@ -140,8 +138,6 @@ struct gl_priv { unsigned int slice_height; }; -static void redraw(struct vo *vo); - static void resize(struct vo *vo, int x, int y) { struct gl_priv *p = vo->priv; @@ -185,7 +181,7 @@ static void resize(struct vo *vo, int x, int y) vo_osd_changed(OSDTYPE_OSD); } gl->Clear(GL_COLOR_BUFFER_BIT); - redraw(vo); + vo->want_redraw = true; } static void texSize(struct vo *vo, int w, int h, int *texw, int *texh) @@ -699,8 +695,8 @@ static void check_events(struct vo *vo) } if (e & VO_EVENT_RESIZE) resize(vo, vo->dwidth, vo->dheight); - if (e & VO_EVENT_EXPOSE && p->int_pause) - redraw(vo); + if (e & VO_EVENT_EXPOSE) + vo->want_redraw = true; } /** @@ -900,15 +896,6 @@ static void flip_page(struct vo *vo) } } -static void redraw(struct vo *vo) -{ - if (vo_doublebuffering) { - do_render(vo); - do_render_osd(vo, RENDER_OSD | RENDER_EOSD); - } - flip_page(vo); -} - static int draw_slice(struct vo *vo, uint8_t *src[], int stride[], int w, int h, int x, int y) { @@ -1423,10 +1410,6 @@ static int control(struct vo *vo, uint32_t request, void *data) struct gl_priv *p = vo->priv; switch (request) { - case VOCTRL_PAUSE: - case VOCTRL_RESUME: - p->int_pause = (request == VOCTRL_PAUSE); - return VO_TRUE; case VOCTRL_QUERY_FORMAT: return query_format(vo, *(uint32_t *)data); case VOCTRL_GET_IMAGE: @@ -1487,6 +1470,7 @@ static int control(struct vo *vo, uint32_t request, void *data) if (mp_csp_equalizer_set(&p->video_eq, args->name, args->value) < 0) return VO_NOTIMPL; update_yuvconv(vo); + vo->want_redraw = true; return VO_TRUE; } break; @@ -1495,6 +1479,7 @@ static int control(struct vo *vo, uint32_t request, void *data) if (vo->config_count && supports_csp) { p->colorspace = *(struct mp_csp_details *)data; update_yuvconv(vo); + vo->want_redraw = true; } return VO_TRUE; } @@ -1506,14 +1491,10 @@ static int control(struct vo *vo, uint32_t request, void *data) break; p->glctx->update_xinerama_info(vo); return VO_TRUE; - case VOCTRL_REDRAW_OSD: + case VOCTRL_REDRAW_FRAME: if (vo_doublebuffering) do_render(vo); - draw_osd(vo, data); - if (vo_doublebuffering) - do_render_osd(vo, 2); - flip_page(vo); - return VO_TRUE; + return true; case VOCTRL_SCREENSHOT: { struct voctrl_screenshot_args *args = data; if (args->full_window) diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index d58607e135..42200d8f5d 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 @@ -195,9 +195,6 @@ struct vdpctx { // Video equalizer struct mp_csp_equalizer video_eq; - int num_shown_frames; - bool paused; - // These tell what's been initialized and uninit() should free/uninitialize bool mode_switched; }; @@ -295,7 +292,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 +302,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; +} - dqp = FFMIN(dqp, 4); - vc->deint_queue_pos = dqp; +static void set_next_frame_info(struct vo *vo, bool eof) +{ + struct vdpctx *vc = vo->priv; + + 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 +332,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 +340,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 +361,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) @@ -410,7 +414,6 @@ static void resize(struct vo *vo) int min_output_width = FFMAX(vo->dwidth, vc->vid_width); int min_output_height = FFMAX(vo->dheight, vc->vid_height); - bool had_frames = vc->num_shown_frames; if (vc->output_surface_width < min_output_width || vc->output_surface_height < min_output_height) { if (vc->output_surface_width < min_output_width) { @@ -439,11 +442,8 @@ static void resize(struct vo *vo) mp_msg(MSGT_VO, MSGL_DBG2, "vdpau out create: %u\n", vc->output_surfaces[i]); } - vc->num_shown_frames = 0; } - if (vc->paused && had_frames) - if (video_to_output_surface(vo) >= 0) - flip_page_timed(vo, 0, -1); + vo->want_redraw = true; } static void preemption_callback(VdpDevice device, void *context) @@ -825,7 +825,6 @@ static void mark_vdpau_objects_uninitialized(struct vo *vo) }; vc->output_surface_width = vc->output_surface_height = -1; vc->eosd_render_count = 0; - vc->num_shown_frames = 0; } static int handle_preemption(struct vo *vo) @@ -937,9 +936,6 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, static void check_events(struct vo *vo) { - struct vdpctx *vc = vo->priv; - struct vdp_functions *vdp = vc->vdp; - if (handle_preemption(vo) < 0) return; @@ -947,19 +943,8 @@ static void check_events(struct vo *vo) if (e & VO_EVENT_RESIZE) resize(vo); - else if (e & VO_EVENT_EXPOSE && vc->paused) { - /* did we already draw a buffer */ - if (vc->num_shown_frames) { - /* redraw the last visible buffer */ - VdpStatus vdp_st; - int last_surface = WRAP_ADD(vc->surface_num, -1, - vc->num_output_surfaces); - vdp_st = vdp->presentation_queue_display(vc->flip_queue, - vc->output_surfaces[last_surface], - vo->dwidth, vo->dheight, 0); - CHECK_ST_WARNING("Error when calling " - "vdp_presentation_queue_display"); - } + else if (e & VO_EVENT_EXPOSE) { + vo->want_redraw = true; } } @@ -1400,7 +1385,6 @@ static void flip_page_timed(struct vo *vo, unsigned int pts_us, int duration) vc->last_ideal_time = ideal_pts; vc->dropped_frame = false; vc->surface_num = WRAP_ADD(vc->surface_num, 1, vc->num_output_surfaces); - vc->num_shown_frames = FFMIN(vc->num_shown_frames + 1, 1000); } static int draw_slice(struct vo *vo, uint8_t *image[], int stride[], int w, @@ -1796,13 +1780,12 @@ static int control(struct vo *vo, uint32_t request, void *data) feature_enables); CHECK_ST_WARNING("Error changing deinterlacing settings"); } + vo->want_redraw = true; return VO_TRUE; case VOCTRL_PAUSE: if (vc->dropped_frame) flip_page_timed(vo, 0, -1); - return (vc->paused = true); - case VOCTRL_RESUME: - return (vc->paused = false); + return true; case VOCTRL_QUERY_FORMAT: return query_format(*(uint32_t *)data); case VOCTRL_GET_IMAGE: @@ -1823,6 +1806,7 @@ static int control(struct vo *vo, uint32_t request, void *data) checked_resize(vo); return VO_TRUE; case VOCTRL_SET_EQUALIZER: { + vo->want_redraw = true; struct voctrl_set_equalizer_args *args = data; return set_equalizer(vo, args->name, args->value); } @@ -1834,6 +1818,7 @@ static int control(struct vo *vo, uint32_t request, void *data) vc->colorspace = *(struct mp_csp_details *)data; if (status_ok(vo)) update_csc_matrix(vo); + vo->want_redraw = true; return true; case VOCTRL_GET_YUV_COLORSPACE: *(struct mp_csp_details *)data = vc->colorspace; @@ -1858,11 +1843,15 @@ static int control(struct vo *vo, uint32_t request, void *data) r->mt = r->mb = vc->border_y; return VO_TRUE; } - case VOCTRL_REDRAW_OSD: + 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_FRAME: video_to_output_surface(vo); - draw_eosd(vo); - draw_osd(vo, data); - flip_page_timed(vo, 0, -1); return true; case VOCTRL_RESET: forget_frames(vo); @@ -1892,7 +1881,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, diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c index deda443594..4180ac0fd0 100644 --- a/libvo/vo_xv.c +++ b/libvo/vo_xv.c @@ -89,10 +89,8 @@ struct xvctx { int current_ip_buf; int num_buffers; int total_buffers; - int have_visible_image_copy; - int have_next_image_copy; - int unchanged_visible_image; - int unchanged_next_image; + bool have_image_copy; + bool unchanged_image; int visible_buf; XvImage *xvimage[NUM_BUFFERS + 1]; uint32_t image_width; @@ -227,8 +225,7 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, } ctx->visible_buf = -1; - ctx->have_visible_image_copy = false; - ctx->have_next_image_copy = false; + ctx->have_image_copy = false; /* check image formats */ ctx->xv_format = 0; @@ -420,18 +417,11 @@ static void copy_backup_image(struct vo *vo, int dest, int src) static void check_events(struct vo *vo) { - struct xvctx *ctx = vo->priv; int e = vo_x11_check_events(vo); - if (e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) + if (e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) { resize(vo); - - if ((e & VO_EVENT_EXPOSE || e & VO_EVENT_RESIZE) && ctx->is_paused) { - /* did we already draw a buffer */ - if (ctx->visible_buf != -1) { - /* redraw the last visible buffer */ - put_xvimage(vo, ctx->xvimage[ctx->visible_buf]); - } + vo->want_redraw = true; } } @@ -446,26 +436,21 @@ static void draw_osd(struct vo *vo, struct osd_state *osd) vo->panscan_x), ctx->image_height, ctx->draw_alpha_fnc, vo); if (ctx->osd_objects_drawn) - ctx->unchanged_next_image = false; + ctx->unchanged_image = false; } -static int redraw_osd(struct vo *vo, struct osd_state *osd) +static int redraw_frame(struct vo *vo) { struct xvctx *ctx = vo->priv; - if (ctx->have_visible_image_copy) + if (ctx->have_image_copy) copy_backup_image(vo, ctx->visible_buf, ctx->num_buffers); - else if (ctx->unchanged_visible_image) { + else if (ctx->unchanged_image) { copy_backup_image(vo, ctx->num_buffers, ctx->visible_buf); - ctx->have_visible_image_copy = true; - } - else + ctx->have_image_copy = true; + } else return false; - int temp = ctx->current_buf; ctx->current_buf = ctx->visible_buf; - draw_osd(vo, osd); - ctx->current_buf = temp; - put_xvimage(vo, ctx->xvimage[ctx->visible_buf]); return true; } @@ -477,11 +462,6 @@ static void flip_page(struct vo *vo) /* remember the currently visible buffer */ ctx->visible_buf = ctx->current_buf; - ctx->have_visible_image_copy = ctx->have_next_image_copy; - ctx->have_next_image_copy = false; - ctx->unchanged_visible_image = ctx->unchanged_next_image; - ctx->unchanged_next_image = false; - if (ctx->num_buffers > 1) { ctx->current_buf = vo_directrendering ? 0 : ((ctx->current_buf + 1) % ctx->num_buffers); @@ -524,11 +504,12 @@ static int draw_slice(struct vo *vo, uint8_t *image[], int stride[], int w, return 0; } -static mp_image_t *get_screenshot(struct vo *vo) { +static mp_image_t *get_screenshot(struct vo *vo) +{ struct xvctx *ctx = vo->priv; // try to get an image without OSD - if (ctx->have_visible_image_copy) + if (ctx->have_image_copy) copy_backup_image(vo, ctx->visible_buf, ctx->num_buffers); XvImage *xv_image = ctx->xvimage[ctx->visible_buf]; @@ -570,7 +551,7 @@ static uint32_t draw_image(struct vo *vo, mp_image_t *mpi) { struct xvctx *ctx = vo->priv; - ctx->have_next_image_copy = false; + ctx->have_image_copy = false; if (mpi->flags & MP_IMGFLAG_DIRECT) // direct rendering: @@ -590,9 +571,9 @@ static uint32_t draw_image(struct vo *vo, mp_image_t *mpi) if (ctx->is_paused) { copy_backup_image(vo, ctx->num_buffers, ctx->current_buf); - ctx->have_next_image_copy = true; + ctx->have_image_copy = true; } - ctx->unchanged_next_image = true; + ctx->unchanged_image = true; return true; } @@ -844,20 +825,20 @@ static int control(struct vo *vo, uint32_t request, void *data) case VOCTRL_SET_PANSCAN: resize(vo); return VO_TRUE; - case VOCTRL_SET_EQUALIZER: - { - struct voctrl_set_equalizer_args *args = data; - return vo_xv_set_eq(vo, x11->xv_port, args->name, args->value); - } - case VOCTRL_GET_EQUALIZER: - { - struct voctrl_get_equalizer_args *args = data; - return vo_xv_get_eq(vo, x11->xv_port, args->name, args->valueptr); - } + case VOCTRL_SET_EQUALIZER: { + vo->want_redraw = true; + struct voctrl_set_equalizer_args *args = data; + return vo_xv_set_eq(vo, x11->xv_port, args->name, args->value); + } + case VOCTRL_GET_EQUALIZER: { + struct voctrl_get_equalizer_args *args = data; + return vo_xv_get_eq(vo, x11->xv_port, args->name, args->valueptr); + } case VOCTRL_SET_YUV_COLORSPACE:; struct mp_csp_details* given_cspc = data; int is_709 = given_cspc->format == MP_CSP_BT_709; vo_xv_set_eq(vo, x11->xv_port, "bt_709", is_709 * 200 - 100); + vo->want_redraw = true; return true; case VOCTRL_GET_YUV_COLORSPACE:; struct mp_csp_details* cspc = data; @@ -872,8 +853,8 @@ static int control(struct vo *vo, uint32_t request, void *data) case VOCTRL_UPDATE_SCREENINFO: update_xinerama_info(vo); return VO_TRUE; - case VOCTRL_REDRAW_OSD: - return redraw_osd(vo, data); + case VOCTRL_REDRAW_FRAME: + return redraw_frame(vo); case VOCTRL_SCREENSHOT: { struct voctrl_screenshot_args *args = data; args->out_image = get_screenshot(vo); @@ -2928,8 +2928,7 @@ static double update_video(struct MPContext *mpctx) while (1) { current_module = "filter_video"; - if (!mpctx->hrseek_active - && vo_get_buffered_frame(video_out, false) >= 0) + if (vo_get_buffered_frame(video_out, false) >= 0) break; // XXX Time used in this call is not counted in any performance // timer now @@ -3035,6 +3034,22 @@ void unpause_player(struct MPContext *mpctx) (void)get_relative_time(mpctx); // ignore time that passed during pause } +static int redraw_osd(struct MPContext *mpctx) +{ + struct sh_video *sh_video = mpctx->sh_video; + struct vf_instance *vf = sh_video->vfilter; + if (sh_video->output_flags & VFCAP_OSD_FILTER) + return -1; + if (vo_redraw_frame(mpctx->video_out) < 0) + return -1; + mpctx->osd->pts = mpctx->video_pts; + if (!(sh_video->output_flags & VFCAP_EOSD_FILTER)) + vf->control(vf, VFCTRL_DRAW_EOSD, mpctx->osd); + vf->control(vf, VFCTRL_DRAW_OSD, mpctx->osd); + vo_flip_page(mpctx->video_out, 0, -1); + return 0; +} + void add_step_frame(struct MPContext *mpctx) { mpctx->step_frames++; @@ -3071,11 +3086,10 @@ static void pause_loop(struct MPContext *mpctx) } if (mpctx->sh_video && mpctx->video_out) vo_check_events(mpctx->video_out); - usec_sleep(20000); update_osd_msg(mpctx); int hack = vo_osd_changed(0); vo_osd_changed(hack); - if (hack) + if (hack || mpctx->sh_video && mpctx->video_out->want_redraw) break; #ifdef CONFIG_STREAM_CACHE if (!opts->quiet && stream_cache_size > 0) { @@ -3612,7 +3626,7 @@ static void run_playloop(struct MPContext *mpctx) vo_fps = mpctx->sh_video->fps; bool blit_frame = mpctx->video_out->frame_loaded; - if (!blit_frame || mpctx->hrseek_active) { + if (!blit_frame) { double frame_time = update_video(mpctx); blit_frame = mpctx->video_out->frame_loaded; mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "*** ftime=%5.3f ***\n", frame_time); @@ -3672,12 +3686,14 @@ static void run_playloop(struct MPContext *mpctx) current_module = "flip_page"; if (!frame_time_remaining && blit_frame) { + vo_new_frame_imminent(mpctx->video_out); |