summaryrefslogtreecommitdiffstats
path: root/video/out/vo_vdpau.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-04-29 15:19:03 +0200
committerwm4 <wm4@nowhere>2014-05-02 01:08:05 +0200
commit6775487a46e42663cf96f4f34091d700f0c5889c (patch)
tree504289fb5569fda9d980e1bf6459f580e889d646 /video/out/vo_vdpau.c
parentd6dc8642aeb470a183cec351b1155463b278b643 (diff)
downloadmpv-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_vdpau.c')
-rw-r--r--video/out/vo_vdpau.c115
1 files changed, 24 insertions, 91 deletions
diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c
index 9aa081f409..aae98f618d 100644
--- a/video/out/vo_vdpau.c
+++ b/video/out/vo_vdpau.c
@@ -86,11 +86,8 @@ struct vdpctx {
VdpOutputSurface rgb_surfaces[NUM_BUFFERED_VIDEO];
bool rgb_surfaces_used[NUM_BUFFERED_VIDEO];
VdpOutputSurface black_pixel;
- struct mp_image *buffered_video[NUM_BUFFERED_VIDEO];
- int buffer_pos;
- // State for redrawing the screen after seek-reset
- int prev_buffer_pos;
+ struct mp_image *current_image;
int output_surface_width, output_surface_height;
@@ -161,12 +158,9 @@ static int render_video_to_output_surface(struct vo *vo,
struct vdp_functions *vdp = vc->vdp;
VdpTime dummy;
VdpStatus vdp_st;
- int dp = vc->buffer_pos;
+ struct mp_image *mpi = vc->current_image;
- // Redraw frame from before seek reset?
- if (dp < 0)
- dp = vc->prev_buffer_pos;
- if (dp < 0) {
+ if (!mpi) {
// At least clear the screen if there is nothing to render
int flags = VDP_OUTPUT_SURFACE_RENDER_ROTATE_0;
vdp_st = vdp->output_surface_render_output_surface(output_surface,
@@ -176,8 +170,6 @@ static int render_video_to_output_surface(struct vo *vo,
return -1;
}
- struct mp_image *mpi = vc->buffered_video[dp];
-
vdp_st = vdp->presentation_queue_block_until_surface_idle(vc->flip_queue,
output_surface,
&dummy);
@@ -230,73 +222,14 @@ static int video_to_output_surface(struct vo *vo)
&vc->out_rect_vid, &vc->src_rect_vid);
}
-static int next_buffer_pos(struct vo *vo, bool eof)
-{
- struct vdpctx *vc = vo->priv;
-
- int dqp = vc->buffer_pos;
- if (dqp < 0)
- dqp += 1000;
- else
- dqp -= 1;
- if (dqp < (eof ? 0 : 1))
- return -1;
- return dqp;
-}
-
-static void set_next_frame_info(struct vo *vo, bool eof)
-{
- struct vdpctx *vc = vo->priv;
-
- vo->frame_loaded = false;
- int dqp = next_buffer_pos(vo, eof);
- if (dqp < 0)
- return;
- vo->frame_loaded = true;
-
- // Set pts values
- struct mp_image **bv = &vc->buffered_video[0];
- if (dqp == 0) { // no future frame/pts available
- vo->next_pts = bv[0]->pts;
- vo->next_pts2 = MP_NOPTS_VALUE;
- } else {
- vo->next_pts = bv[dqp]->pts;
- vo->next_pts2 = bv[dqp - 1]->pts;
- }
-}
-
-static void add_new_video_surface(struct vo *vo, struct mp_image *mpi)
-{
- struct vdpctx *vc = vo->priv;
- struct mp_image **bv = vc->buffered_video;
-
- mp_image_unrefp(&bv[NUM_BUFFERED_VIDEO - 1]);
-
- for (int i = NUM_BUFFERED_VIDEO - 1; i > 0; i--)
- bv[i] = bv[i - 1];
- bv[0] = mpi;
-
- vc->buffer_pos = FFMIN(vc->buffer_pos + 1, NUM_BUFFERED_VIDEO - 2);
- set_next_frame_info(vo, false);
-}
-
static void forget_frames(struct vo *vo, bool seek_reset)
{
struct vdpctx *vc = vo->priv;
- if (seek_reset) {
- if (vc->buffer_pos >= 0)
- vc->prev_buffer_pos = vc->buffer_pos;
- } else {
- vc->prev_buffer_pos = -1001;
- }
+ if (!seek_reset)
+ mp_image_unrefp(&vc->current_image);
- vc->buffer_pos = -1001;
vc->dropped_frame = false;
- if (vc->prev_buffer_pos < 0) {
- for (int i = 0; i < NUM_BUFFERED_VIDEO; i++)
- mp_image_unrefp(&vc->buffered_video[i]);
- }
}
static void resize(struct vo *vo)
@@ -975,23 +908,29 @@ static struct mp_image *get_rgb_surface(struct vo *vo)
return NULL;
}
-static void draw_image(struct vo *vo, mp_image_t *mpi)
+static void draw_image(struct vo *vo, struct mp_image *mpi)
+{
+ struct vdpctx *vc = vo->priv;
+
+ mp_image_setrefp(&vc->current_image, mpi);
+
+ if (status_ok(vo))
+ video_to_output_surface(vo);
+}
+
+static struct mp_image *filter_image(struct vo *vo, struct mp_image *mpi)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
struct mp_image *reserved_mpi = NULL;
VdpStatus vdp_st;
- // Forget previous frames, as we can display a new one now.
- vc->prev_buffer_pos = -1001;
- mp_image_unrefp(&vc->buffered_video[NUM_BUFFERED_VIDEO - 1]);
-
if (vc->image_format == IMGFMT_VDPAU) {
reserved_mpi = mp_image_new_ref(mpi);
} else if (vc->rgb_mode) {
reserved_mpi = get_rgb_surface(vo);
if (!reserved_mpi)
- return;
+ goto end;
VdpOutputSurface rgb_surface = (uintptr_t)reserved_mpi->planes[0];
if (rgb_surface != VDP_INVALID_HANDLE) {
vdp_st = vdp->output_surface_put_bits_native(rgb_surface,
@@ -1005,7 +944,7 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
reserved_mpi = mp_vdpau_get_video_surface(vc->mpvdp, vc->vdp_chroma_type,
mpi->w, mpi->h);
if (!reserved_mpi)
- return;
+ goto end;
VdpVideoSurface surface = (VdpVideoSurface)(intptr_t)reserved_mpi->planes[3];
if (handle_preemption(vo) >= 0) {
const void *destdata[3] = {mpi->planes[0], mpi->planes[2],
@@ -1020,9 +959,10 @@ static void draw_image(struct vo *vo, mp_image_t *mpi)
}
reserved_mpi->pts = mpi->pts;
- add_new_video_surface(vo, reserved_mpi);
- return;
+end:
+ talloc_free(mpi);
+ return reserved_mpi;
}
// warning: the size and pixel format of surface must match that of the
@@ -1175,6 +1115,8 @@ static int preinit(struct vo *vo)
vc->video_eq.capabilities = MP_CSP_EQ_CAPS_COLORMATRIX;
+ vo->max_video_queue = 2;
+
return 0;
}
@@ -1248,14 +1190,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
}
return true;
}
- case VOCTRL_NEWFRAME:
- vc->buffer_pos = next_buffer_pos(vo, true);
- if (status_ok(vo))
- video_to_output_surface(vo);
- return true;
- case VOCTRL_SKIPFRAME:
- vc->buffer_pos = next_buffer_pos(vo, true);
- return true;
case VOCTRL_REDRAW_FRAME:
if (status_ok(vo))
video_to_output_surface(vo);
@@ -1293,7 +1227,6 @@ static int control(struct vo *vo, uint32_t request, void *data)
#define OPT_BASE_STRUCT struct vdpctx
const struct vo_driver video_out_vdpau = {
- .buffer_frames = true,
.description = "VDPAU with X11",
.name = "vdpau",
.preinit = preinit,
@@ -1301,7 +1234,7 @@ const struct vo_driver video_out_vdpau = {
.reconfig = reconfig,
.control = control,
.draw_image = draw_image,
- .get_buffered_frame = set_next_frame_info,
+ .filter_image = filter_image,
.draw_osd = draw_osd,
.flip_page_timed = flip_page_timed,
.uninit = uninit,