summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUoti Urpala <uau@symbol.nonexistent.invalid>2008-04-04 09:57:58 +0300
committerUoti Urpala <uau@symbol.nonexistent.invalid>2008-04-23 13:41:05 +0300
commitf894294bae1ff9b2c1802a5ae7e73cfdbc26e645 (patch)
tree946aafc44d5c9c82a6838c8bd282f40d04808243
parentb91826280c468b1b5b4baf6e0225dfdb878e214a (diff)
downloadmpv-f894294bae1ff9b2c1802a5ae7e73cfdbc26e645.tar.bz2
mpv-f894294bae1ff9b2c1802a5ae7e73cfdbc26e645.tar.xz
vo_xv: Free resources in error cases
If preinit() failed after allocating some resources it didn't free them. Also if preinit() completed but all (if any) calls to config() failed then uninit() it not free resources. Add checks to uninit() to make it safe with only a subset of resources allocated, then make it execute independently of vo_config_count and also make preinit() call it in error cases.
-rw-r--r--libvo/vo_xv.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c
index b7c24948af..fa25f673e4 100644
--- a/libvo/vo_xv.c
+++ b/libvo/vo_xv.c
@@ -82,6 +82,8 @@ struct xvctx {
int is_paused;
uint32_t drwX, drwY;
uint32_t max_width, max_height; // zero means: not set
+ int event_fd_registered; // for uninit called from preinit
+ int mode_switched;
void (*draw_alpha_fnc)(void *ctx, int x0, int y0, int w, int h,
unsigned char *src, unsigned char *srca,
int stride);
@@ -239,6 +241,7 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
}
vo_vm_switch(vm_width, vm_height, &modeline_width,
&modeline_height);
+ ctx->mode_switched = 1;
hint.x = (vo_screenwidth - modeline_width) / 2;
hint.y = (vo_screenheight - modeline_height) / 2;
hint.width = modeline_width;
@@ -684,10 +687,9 @@ static void uninit(struct vo *vo)
struct xvctx *ctx = vo->priv;
int i;
- if (!vo_config_count)
- return;
ctx->visible_buf = -1;
- XvFreeAdaptorInfo(ctx->ai);
+ if (ctx->ai)
+ XvFreeAdaptorInfo(ctx->ai);
ctx->ai = NULL;
if (ctx->fo) {
XFree(ctx->fo);
@@ -696,9 +698,12 @@ static void uninit(struct vo *vo)
for (i = 0; i < ctx->num_buffers; i++)
deallocate_xvimage(vo, i);
#ifdef HAVE_XF86VM
- vo_vm_close(mDisplay);
+ if (ctx->mode_switched)
+ vo_vm_close(mDisplay);
#endif
- mp_input_rm_event_fd(ConnectionNumber(mDisplay));
+ if (ctx->event_fd_registered)
+ mp_input_rm_event_fd(ConnectionNumber(mDisplay));
+ // uninit() shouldn't get called unless initialization went past vo_init()
vo_x11_uninit();
free(ctx);
vo->priv = NULL;
@@ -748,7 +753,7 @@ static int preinit(struct vo *vo, const char *arg)
{
mp_msg(MSGT_VO, MSGL_ERR,
MSGTR_LIBVO_XV_XvNotSupportedByX11);
- return -1;
+ goto error;
}
/* check for Xvideo support */
@@ -757,7 +762,7 @@ static int preinit(struct vo *vo, const char *arg)
&ctx->ai))
{
mp_msg(MSGT_VO, MSGL_ERR, MSGTR_LIBVO_XV_XvQueryAdaptorsFailed);
- return -1;
+ goto error;
}
/* check adaptors */
@@ -818,12 +823,12 @@ static int preinit(struct vo *vo, const char *arg)
else
mp_msg(MSGT_VO, MSGL_ERR,
MSGTR_LIBVO_XV_NoXvideoSupport);
- return -1;
+ goto error;
}
if ( !vo_xv_init_colorkey() )
{
- return -1; // bail out, colorkey setup failed
+ goto error; // bail out, colorkey setup failed
}
vo_xv_enable_vsync();
vo_xv_get_max_img_dim(&ctx->max_width, &ctx->max_height);
@@ -831,7 +836,12 @@ static int preinit(struct vo *vo, const char *arg)
ctx->fo = XvListImageFormats(mDisplay, xv_port, (int *) &ctx->formats);
mp_input_add_event_fd(ConnectionNumber(mDisplay), x11_fd_callback, vo);
+ ctx->event_fd_registered = 1;
return 0;
+
+ error:
+ uninit(vo); // free resources
+ return -1;
}
static int control(struct vo *vo, uint32_t request, void *data)