summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
Diffstat (limited to 'video/out')
-rw-r--r--video/out/vo.c29
-rw-r--r--video/out/vo.h4
-rw-r--r--video/out/vo_lavc.c10
-rw-r--r--video/out/vo_vdpau.c61
4 files changed, 59 insertions, 45 deletions
diff --git a/video/out/vo.c b/video/out/vo.c
index 18e000e3ab..9a75ccb789 100644
--- a/video/out/vo.c
+++ b/video/out/vo.c
@@ -38,6 +38,7 @@
#include "core/mp_fifo.h"
#include "core/m_config.h"
#include "core/mp_msg.h"
+#include "video/mp_image.h"
#include "video/vfcap.h"
#include "sub/sub.h"
@@ -159,28 +160,20 @@ int vo_control(struct vo *vo, uint32_t request, void *data)
return vo->driver->control(vo, request, data);
}
-static void draw_image_pts(struct vo *vo, struct mp_image *mpi, double pts)
-{
- if (vo->driver->draw_image_pts) {
- vo->driver->draw_image_pts(vo, mpi, pts);
- } else {
- vo->driver->draw_image(vo, mpi);
- }
-}
-
// Return -1 if driver appears not to support a draw_image interface,
// 0 otherwise (whether the driver actually drew something or not).
-int vo_draw_image(struct vo *vo, struct mp_image *mpi, double pts)
+int vo_draw_image(struct vo *vo, struct mp_image *mpi)
{
if (!vo->config_ok)
return 0;
if (vo->driver->buffer_frames) {
- draw_image_pts(vo, mpi, pts);
+ vo->driver->draw_image(vo, mpi);
return 0;
}
vo->frame_loaded = true;
- vo->next_pts = pts;
- vo->waiting_mpi = mpi;
+ vo->next_pts = mpi->pts;
+ assert(!vo->waiting_mpi);
+ vo->waiting_mpi = mp_image_new_ref(mpi);
return 0;
}
@@ -211,6 +204,7 @@ void vo_skip_frame(struct vo *vo)
{
vo_control(vo, VOCTRL_SKIPFRAME, NULL);
vo->frame_loaded = false;
+ mp_image_unrefp(&vo->waiting_mpi);
}
void vo_new_frame_imminent(struct vo *vo)
@@ -218,8 +212,11 @@ void vo_new_frame_imminent(struct vo *vo)
if (vo->driver->buffer_frames)
vo_control(vo, VOCTRL_NEWFRAME, NULL);
else {
- draw_image_pts(vo, vo->waiting_mpi, vo->next_pts);
- vo->waiting_mpi = NULL;
+ 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);
}
}
@@ -262,6 +259,7 @@ void vo_seek_reset(struct vo *vo)
vo_control(vo, VOCTRL_RESET, NULL);
vo->frame_loaded = false;
vo->hasframe = false;
+ mp_image_unrefp(&vo->waiting_mpi);
}
void vo_destroy(struct vo *vo)
@@ -269,6 +267,7 @@ void vo_destroy(struct vo *vo)
if (vo->registered_fd != -1)
mp_input_rm_key_fd(vo->input_ctx, vo->registered_fd);
vo->driver->uninit(vo);
+ talloc_free(vo->waiting_mpi);
talloc_free(vo);
}
diff --git a/video/out/vo.h b/video/out/vo.h
index 7b929f985d..e883293326 100644
--- a/video/out/vo.h
+++ b/video/out/vo.h
@@ -53,7 +53,7 @@ enum mp_voctrl {
/* for vdpau hardware decoding */
VOCTRL_HWDEC_DECODER_RENDER, // pointer to hw state
- VOCTRL_HWDEC_GET_SURFACE, // struct mp_image
+ VOCTRL_HWDEC_ALLOC_SURFACE, // struct mp_image**
VOCTRL_NEWFRAME,
VOCTRL_SKIPFRAME,
@@ -285,7 +285,7 @@ int vo_config(struct vo *vo, uint32_t width, uint32_t height,
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_draw_image(struct vo *vo, struct mp_image *mpi);
int vo_redraw_frame(struct vo *vo);
int vo_get_buffered_frame(struct vo *vo, bool eof);
void vo_skip_frame(struct vo *vo);
diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c
index 6ae06fffec..7d846da92d 100644
--- a/video/out/vo_lavc.c
+++ b/video/out/vo_lavc.c
@@ -74,7 +74,7 @@ static int preinit(struct vo *vo, const char *arg)
return 0;
}
-static void draw_image(struct vo *vo, mp_image_t *mpi, double pts);
+static void draw_image(struct vo *vo, mp_image_t *mpi);
static void uninit(struct vo *vo)
{
struct priv *vc = vo->priv;
@@ -82,7 +82,7 @@ static void uninit(struct vo *vo)
return;
if (vc->lastipts >= 0 && vc->stream)
- draw_image(vo, NULL, MP_NOPTS_VALUE);
+ draw_image(vo, NULL);
if (vc->lastimg) {
// palette hack
@@ -284,7 +284,7 @@ static int encode_video(struct vo *vo, AVFrame *frame, AVPacket *packet)
}
}
-static void draw_image(struct vo *vo, mp_image_t *mpi, double pts)
+static void draw_image(struct vo *vo, mp_image_t *mpi)
{
struct priv *vc = vo->priv;
struct encode_lavc_context *ectx = vo->encode_lavc_ctx;
@@ -294,6 +294,8 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, double pts)
int64_t frameipts;
double nextpts;
+ double pts = mpi ? mpi->pts : MP_NOPTS_VALUE;
+
if (!vc)
return;
if (!encode_lavc_start(ectx)) {
@@ -540,7 +542,7 @@ const struct vo_driver video_out_lavc = {
.control = control,
.uninit = uninit,
.check_events = check_events,
- .draw_image_pts = draw_image,
+ .draw_image = draw_image,
.draw_osd = draw_osd,
.flip_page_timed = flip_page_timed,
};
diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c
index 661072b814..48080ba186 100644
--- a/video/out/vo_vdpau.c
+++ b/video/out/vo_vdpau.c
@@ -140,7 +140,8 @@ struct vdpctx {
struct mp_osd_res osd_rect;
struct vdpau_render_state surface_render[MAX_VIDEO_SURFACES];
- int surface_num;
+ bool surface_in_use[MAX_VIDEO_SURFACES];
+ int surface_num; // indexes output_surfaces
int query_surface_num;
VdpTime recent_vsync_time;
float user_fps;
@@ -332,15 +333,12 @@ static void add_new_video_surface(struct vo *vo, VdpVideoSurface surface,
struct vdpctx *vc = vo->priv;
struct buffered_video_surface *bv = vc->buffered_video;
- if (reserved_mpi)
- reserved_mpi->usage_count++;
- if (bv[NUM_BUFFERED_VIDEO - 1].mpi)
- bv[NUM_BUFFERED_VIDEO - 1].mpi->usage_count--;
+ mp_image_unrefp(&bv[NUM_BUFFERED_VIDEO - 1].mpi);
for (int i = NUM_BUFFERED_VIDEO - 1; i > 0; i--)
bv[i] = bv[i - 1];
bv[0] = (struct buffered_video_surface){
- .mpi = reserved_mpi,
+ .mpi = reserved_mpi ? mp_image_new_ref(reserved_mpi) : NULL,
.surface = surface,
.pts = pts,
};
@@ -358,8 +356,7 @@ static void forget_frames(struct vo *vo)
vc->dropped_frame = false;
for (int i = 0; i < NUM_BUFFERED_VIDEO; i++) {
struct buffered_video_surface *p = vc->buffered_video + i;
- if (p->mpi)
- p->mpi->usage_count--;
+ mp_image_unrefp(&p->mpi);
*p = (struct buffered_video_surface){
.surface = VDP_INVALID_HANDLE,
};
@@ -1299,7 +1296,7 @@ static struct vdpau_render_state *get_surface(struct vo *vo, int number)
return &vc->surface_render[number];
}
-static void draw_image(struct vo *vo, mp_image_t *mpi, double pts)
+static void draw_image(struct vo *vo, mp_image_t *mpi)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
@@ -1329,7 +1326,7 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, double pts)
else
vc->top_field_first = 1;
- add_new_video_surface(vo, rndr->surface, reserved_mpi, pts);
+ add_new_video_surface(vo, rndr->surface, reserved_mpi, mpi->pts);
return;
}
@@ -1392,23 +1389,38 @@ static struct mp_image *get_window_screenshot(struct vo *vo)
return image;
}
-static uint32_t get_decoder_surface(struct vo *vo, mp_image_t *mpi)
+static void release_decoder_surface(void *ptr)
+{
+ bool *in_use_ptr = ptr;
+ *in_use_ptr = false;
+}
+
+static struct mp_image *get_decoder_surface(struct vo *vo)
{
struct vdpctx *vc = vo->priv;
- struct vdpau_render_state *rndr;
if (!IMGFMT_IS_VDPAU(vc->image_format))
- return VO_FALSE;
+ return NULL;
- rndr = get_surface(vo, mpi->number);
- if (!rndr) {
- mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] no surfaces available in "
- "get_decoder_surface\n");
- // TODO: this probably breaks things forever, provide a dummy buffer?
- return VO_FALSE;
+ for (int n = 0; n < MAX_VIDEO_SURFACES; n++) {
+ if (!vc->surface_in_use[n]) {
+ vc->surface_in_use[n] = true;
+ struct mp_image *res =
+ mp_image_new_custom_ref(&(struct mp_image){0},
+ &vc->surface_in_use[n],
+ release_decoder_surface);
+ mp_image_setfmt(res, vc->image_format);
+ mp_image_set_size(res, vc->vid_width, vc->vid_height);
+ struct vdpau_render_state *rndr = get_surface(vo, n);
+ res->planes[0] = (void *)rndr;
+ return res;
+ }
}
- mpi->planes[0] = (void *)rndr;
- return VO_TRUE;
+
+ mp_msg(MSGT_VO, MSGL_ERR, "[vdpau] no surfaces available in "
+ "get_decoder_surface\n");
+ // TODO: this probably breaks things forever, provide a dummy buffer?
+ return NULL;
}
static int query_format(struct vo *vo, uint32_t format)
@@ -1587,8 +1599,9 @@ static int control(struct vo *vo, uint32_t request, void *data)
if (vc->dropped_frame)
vo->want_redraw = true;
return true;
- case VOCTRL_HWDEC_GET_SURFACE:
- return get_decoder_surface(vo, data);
+ case VOCTRL_HWDEC_ALLOC_SURFACE:
+ *(struct mp_image **)data = get_decoder_surface(vo);
+ return true;
case VOCTRL_HWDEC_DECODER_RENDER:
return decoder_render(vo, data);
case VOCTRL_BORDER:
@@ -1672,7 +1685,7 @@ const struct vo_driver video_out_vdpau = {
.query_format = query_format,
.config = config,
.control = control,
- .draw_image_pts = draw_image,
+ .draw_image = draw_image,
.get_buffered_frame = set_next_frame_info,
.draw_osd = draw_osd,
.flip_page_timed = flip_page_timed,