diff options
author | wm4 <wm4@nowhere> | 2014-04-29 15:19:03 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-05-02 01:08:05 +0200 |
commit | 6775487a46e42663cf96f4f34091d700f0c5889c (patch) | |
tree | 504289fb5569fda9d980e1bf6459f580e889d646 /video/out/vo.c | |
parent | d6dc8642aeb470a183cec351b1155463b278b643 (diff) | |
download | mpv-6775487a46e42663cf96f4f34091d700f0c5889c.tar.bz2 mpv-6775487a46e42663cf96f4f34091d700f0c5889c.tar.xz |
video: move video frame queue from vo_vdpau.c to vo.c
Remove the special casing of vo_vdpau vs. other VOs. Replace the
complicated interaction between vo.c and vo_vdpau.c with a simple queue
in vo.c. VOs other than vdpau are handled by setting the length of the
queue to 1 (this is essentially what waiting_mpi was).
Note that vo_vdpau.c seems to have buffered only 1 or 2 frames into the
future, while the remaining 3 or 4 frames were past frames. So the new
code buffers 2 frames (vo_vdpau.c requests this queue length by setting
vo->max_video_queue to 2). It should probably be investigated why
vo_vdpau.c kept so many past frames.
The field vo->redrawing is removed. I'm not really sure what that would
be needed for; it seems pointless.
Future directions include making the interface between playloop and VO
simpler, as well as making rendering a frame a single operation, as
opposed to the weird 3-step sequence of rendering, drawing OSD, and
flipping.
Diffstat (limited to 'video/out/vo.c')
-rw-r--r-- | video/out/vo.c | 95 |
1 files changed, 57 insertions, 38 deletions
diff --git a/video/out/vo.c b/video/out/vo.c index 8556b6470c..6c0cb44c14 100644 --- a/video/out/vo.c +++ b/video/out/vo.c @@ -112,6 +112,8 @@ const struct vo_driver *video_out_drivers[] = NULL }; +static void forget_frames(struct vo *vo); + static bool get_desc(struct m_obj_desc *dst, int index) { if (index >= MP_ARRAY_SIZE(video_out_drivers) - 1) @@ -171,6 +173,7 @@ static struct vo *vo_create(struct mpv_global *global, .input_ctx = input_ctx, .event_fd = -1, .monitor_par = 1, + .max_video_queue = 1, .next_pts = MP_NOPTS_VALUE, .next_pts2 = MP_NOPTS_VALUE, }; @@ -228,7 +231,7 @@ void vo_destroy(struct vo *vo) { if (vo->event_fd != -1) mp_input_rm_key_fd(vo->input_ctx, vo->event_fd); - mp_image_unrefp(&vo->waiting_mpi); + forget_frames(vo); vo->driver->uninit(vo); talloc_free(vo); } @@ -345,9 +348,7 @@ int vo_reconfig(struct vo *vo, struct mp_image_params *params, int flags) talloc_free(vo->params); vo->params = NULL; } - vo->frame_loaded = false; - vo->waiting_mpi = NULL; - vo->redrawing = false; + forget_frames(vo); vo->hasframe = false; return ret; } @@ -357,19 +358,45 @@ int vo_control(struct vo *vo, uint32_t request, void *data) return vo->driver->control(vo, request, data); } +static void update_video_queue_state(struct vo *vo, bool eof) +{ + int num = vo->num_video_queue; + // Normally, buffer 1 image ahead, except if the queue is limited to less + // than 2 entries, or if EOF is reached and there aren't enough images left. + int min = 2; + if (vo->max_video_queue < 2 || (vo->num_video_queue < 2 && eof)) + min = 1; + vo->frame_loaded = num >= min; + if (!vo->frame_loaded) + num = -1; + vo->next_pts = num > 0 ? vo->video_queue[0]->pts : MP_NOPTS_VALUE; + vo->next_pts2 = num > 1 ? vo->video_queue[1]->pts : MP_NOPTS_VALUE; +} + +static void forget_frames(struct vo *vo) +{ + for (int n = 0; n < vo->num_video_queue; n++) + talloc_free(vo->video_queue[n]); + vo->num_video_queue = 0; + update_video_queue_state(vo, false); +} + void vo_queue_image(struct vo *vo, struct mp_image *mpi) { + assert(mpi); if (!vo->config_ok) return; - if (vo->driver->buffer_frames) { - vo->driver->draw_image(vo, mpi); + mpi = mp_image_new_ref(mpi); + if (vo->driver->filter_image) + mpi = vo->driver->filter_image(vo, mpi); + if (!mpi) { + MP_ERR(vo, "Could not upload image.\n"); return; } - vo->frame_loaded = true; - vo->next_pts = mpi->pts; - vo->next_pts2 = MP_NOPTS_VALUE; - assert(!vo->waiting_mpi); - vo->waiting_mpi = mp_image_new_ref(mpi); + assert(vo->max_video_queue <= VO_MAX_QUEUE); + assert(vo->num_video_queue < vo->max_video_queue); + vo->video_queue[vo->num_video_queue++] = mpi; + update_video_queue_state(vo, false); } int vo_redraw_frame(struct vo *vo) @@ -378,7 +405,6 @@ int vo_redraw_frame(struct vo *vo) return -1; if (vo_control(vo, VOCTRL_REDRAW_FRAME, NULL) == true) { vo->want_redraw = false; - vo->redrawing = true; return 0; } return -1; @@ -395,32 +421,33 @@ int vo_get_buffered_frame(struct vo *vo, bool eof) { if (!vo->config_ok) return -1; - if (vo->frame_loaded) - return 0; - if (!vo->driver->buffer_frames) - return -1; - vo->driver->get_buffered_frame(vo, eof); + update_video_queue_state(vo, eof); return vo->frame_loaded ? 0 : -1; } +// Remove vo->video_queue[0] +static void shift_queue(struct vo *vo) +{ + if (!vo->num_video_queue) + return; + talloc_free(vo->video_queue[0]); + vo->num_video_queue--; + for (int n = 0; n < vo->num_video_queue; n++) + vo->video_queue[n] = vo->video_queue[n + 1]; +} + void vo_skip_frame(struct vo *vo) { - vo_control(vo, VOCTRL_SKIPFRAME, NULL); + shift_queue(vo); vo->frame_loaded = false; - mp_image_unrefp(&vo->waiting_mpi); } void vo_new_frame_imminent(struct vo *vo) { - if (vo->driver->buffer_frames) - vo_control(vo, VOCTRL_NEWFRAME, NULL); - else { - assert(vo->frame_loaded); - assert(vo->waiting_mpi); - assert(vo->waiting_mpi->pts == vo->next_pts); - vo->driver->draw_image(vo, vo->waiting_mpi); - mp_image_unrefp(&vo->waiting_mpi); - } + assert(vo->frame_loaded); + assert(vo->num_video_queue > 0); + vo->driver->draw_image(vo, vo->video_queue[0]); + shift_queue(vo); } void vo_draw_osd(struct vo *vo, struct osd_state *osd) @@ -433,18 +460,13 @@ void vo_flip_page(struct vo *vo, int64_t pts_us, int duration) { if (!vo->config_ok) return; - if (!vo->redrawing) { - vo->frame_loaded = false; - vo->next_pts = MP_NOPTS_VALUE; - vo->next_pts2 = 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 vo->driver->flip_page(vo); vo->hasframe = true; + update_video_queue_state(vo, false); } void vo_check_events(struct vo *vo) @@ -457,11 +479,8 @@ void vo_check_events(struct vo *vo) void vo_seek_reset(struct vo *vo) { vo_control(vo, VOCTRL_RESET, NULL); - vo->frame_loaded = false; - vo->next_pts = MP_NOPTS_VALUE; - vo->next_pts2 = MP_NOPTS_VALUE; + forget_frames(vo); vo->hasframe = false; - mp_image_unrefp(&vo->waiting_mpi); } // Calculate the appropriate source and destination rectangle to |