Commit aedd5311 authored by Jean-Paul Saman's avatar Jean-Paul Saman

codec/avcodec/vaapi: Release subpicture associations (corner cases).

When surfaces are reclaimed or released before they are being displayed,
then the subpicture association still exists. This code tries to catch
such pictures and will release the subpictures association.
parent 57c5e16c
...@@ -213,8 +213,6 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t ...@@ -213,8 +213,6 @@ static int CreateSurfaces( vlc_va_vaapi_t *p_va, void **pp_hw_ctx, vlc_fourcc_t
p_surface->i_id = pi_surface_id[i]; p_surface->i_id = pi_surface_id[i];
p_surface->i_refcount = 0; p_surface->i_refcount = 0;
p_surface->i_order = 0; p_surface->i_order = 0;
p_surface->i_sub = 0;
p_surface->subpicture = NULL;
vlc_mutex_init(&p_surface->lock); vlc_mutex_init(&p_surface->lock);
} }
...@@ -403,10 +401,6 @@ static vlc_va_surface_t *FindSurface( vlc_va_t *p_external, const VASurfaceID i_ ...@@ -403,10 +401,6 @@ static vlc_va_surface_t *FindSurface( vlc_va_t *p_external, const VASurfaceID i_
*/ */
p_tmp->i_refcount++; p_tmp->i_refcount++;
p_surface = p_tmp; p_surface = p_tmp;
assert(p_surface->subpicture == NULL);
free(p_surface->subpicture);
p_surface->subpicture = NULL;
p_surface->i_sub = 0;
vlc_mutex_unlock(&p_tmp->lock); vlc_mutex_unlock(&p_tmp->lock);
break; break;
} }
......
...@@ -34,6 +34,7 @@ void vlc_va_Terminate(vlc_va_conn_t *conn); ...@@ -34,6 +34,7 @@ void vlc_va_Terminate(vlc_va_conn_t *conn);
typedef struct typedef struct
{ {
VASubpictureID i_id; /* VASubpictureIDs */ VASubpictureID i_id; /* VASubpictureIDs */
VASurfaceID i_surface;
VAImage image; VAImage image;
} vlc_va_subpicture_t; } vlc_va_subpicture_t;
...@@ -43,16 +44,18 @@ typedef struct ...@@ -43,16 +44,18 @@ typedef struct
int i_refcount; int i_refcount;
unsigned int i_order; unsigned int i_order;
/* subpicture */
vlc_va_subpicture_t *subpicture;
unsigned int i_sub; /* number of vlc_va_subpicures_t */
vlc_mutex_t lock; vlc_mutex_t lock;
} vlc_va_surface_t; } vlc_va_surface_t;
struct picture_sys_t struct picture_sys_t
{ {
/* surface */
vlc_va_surface_t *surface; vlc_va_surface_t *surface;
/* subpicture */
vlc_va_subpicture_t *subpicture;
unsigned int i_sub; /* number of vlc_va_subpicures_t */
bool b_own_vout; /* surface owned by vout? */ bool b_own_vout; /* surface owned by vout? */
}; };
#endif #endif
...@@ -361,9 +361,8 @@ static int Control (vout_display_t *vd, int query, va_list ap) ...@@ -361,9 +361,8 @@ static int Control (vout_display_t *vd, int query, va_list ap)
} }
} }
static VASubpictureID SubpictureCreate(vout_display_t *vd, vlc_va_surface_t *surface, static VASubpictureID SubpictureCreate(vout_display_t *vd, const subpicture_t *subpicture,
const subpicture_t *subpicture, const subpicture_region_t *region, const subpicture_region_t *region, vlc_va_subpicture_t *vasubpicture)
vlc_va_subpicture_t *vasubpicture)
{ {
vout_display_sys_t *sys = vd->sys; vout_display_sys_t *sys = vd->sys;
...@@ -423,11 +422,12 @@ static VASubpictureID SubpictureCreate(vout_display_t *vd, vlc_va_surface_t *sur ...@@ -423,11 +422,12 @@ static VASubpictureID SubpictureCreate(vout_display_t *vd, vlc_va_surface_t *sur
/* Associate subpicture with surface */ /* Associate subpicture with surface */
status = vaAssociateSubpicture(sys->conn->p_display, subpic, status = vaAssociateSubpicture(sys->conn->p_display, subpic,
&surface->i_id, 1, /* array of surfaces */ &vasubpicture->i_surface, 1, /* array of surfaces */
/* src rectangle */ /* src rectangle */
src_left, src_top, src_right, src_bottom, src_left, src_top, src_right, src_bottom,
/* dest rectangle */ /* dest rectangle */
((video.width - dst_right) / 2), dst_top, dst_right - dst_left, dst_bottom - dst_top, ((video.width - dst_right) / 2), dst_top,
dst_right - dst_left, dst_bottom - dst_top,
flags); flags);
if (status != VA_STATUS_SUCCESS) if (status != VA_STATUS_SUCCESS)
{ {
...@@ -437,25 +437,19 @@ static VASubpictureID SubpictureCreate(vout_display_t *vd, vlc_va_surface_t *sur ...@@ -437,25 +437,19 @@ static VASubpictureID SubpictureCreate(vout_display_t *vd, vlc_va_surface_t *sur
return subpic; return subpic;
} }
static void SubpictureDestroy(vout_display_t *vd, vlc_va_surface_t *surface) static void SubpictureDestroy(vout_display_t *vd, vlc_va_subpicture_t *subpicture, const int i_sub)
{ {
vout_display_sys_t *sys = vd->sys; vout_display_sys_t *sys = vd->sys;
vlc_va_subpicture_t *subpicture = surface->subpicture;
int i_sub = surface->i_sub;
surface->i_sub = 0;
surface->subpicture = NULL;
VAStatus status; VAStatus status;
for (int i = 0; i < i_sub; i++) for (int i = 0; i < i_sub; i++)
{ {
if ((surface->i_id != VA_INVALID_ID) && if ((subpicture[i].i_surface != VA_INVALID_SURFACE) &&
(subpicture[i].i_id != VA_INVALID_ID)) (subpicture[i].i_id != VA_INVALID_ID))
{ {
status = vaDeassociateSubpicture(sys->conn->p_display, status = vaDeassociateSubpicture(sys->conn->p_display,
subpicture[i].i_id, subpicture[i].i_id,
&surface->i_id, 1); &subpicture[i].i_surface, 1);
if (status != VA_STATUS_SUCCESS) if (status != VA_STATUS_SUCCESS)
msg_Err(vd, "Failed unlinking subpicture from surface (%d)", status); msg_Err(vd, "Failed unlinking subpicture from surface (%d)", status);
} }
...@@ -475,6 +469,11 @@ static void SubpictureDestroy(vout_display_t *vd, vlc_va_surface_t *surface) ...@@ -475,6 +469,11 @@ static void SubpictureDestroy(vout_display_t *vd, vlc_va_surface_t *surface)
if (status != VA_STATUS_SUCCESS) if (status != VA_STATUS_SUCCESS)
msg_Err(vd, "Failed destroying subpicture image"); msg_Err(vd, "Failed destroying subpicture image");
} }
subpicture[i].i_surface = VA_INVALID_SURFACE;
subpicture[i].image.image_id = VA_INVALID_ID;
subpicture[i].image.buf = VA_INVALID_ID;
subpicture[i].i_id = VA_INVALID_ID;
} }
/* */ /* */
...@@ -637,7 +636,7 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic ...@@ -637,7 +636,7 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic
{ {
vout_display_sys_t *sys = vd->sys; vout_display_sys_t *sys = vd->sys;
assert(picture->p_sys->surface->subpicture == NULL); assert(picture->p_sys->subpicture == NULL);
vlc_va_subpicture_t *vasubpic = (vlc_va_subpicture_t*) calloc(i_region, sizeof(vlc_va_subpicture_t)); vlc_va_subpicture_t *vasubpic = (vlc_va_subpicture_t*) calloc(i_region, sizeof(vlc_va_subpicture_t));
if (!vasubpic) if (!vasubpic)
...@@ -668,9 +667,10 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic ...@@ -668,9 +667,10 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic
vasubpic[i_sub].image.format.blue_mask = region->p_picture->format.i_bmask; vasubpic[i_sub].image.format.blue_mask = region->p_picture->format.i_bmask;
vasubpic[i_sub].image.format.green_mask = region->p_picture->format.i_gmask; vasubpic[i_sub].image.format.green_mask = region->p_picture->format.i_gmask;
vasubpic[i_sub].i_surface = picture->p_sys->surface->i_id;
/* Create Subpicture */ /* Create Subpicture */
vasubpic[i_sub].i_id = SubpictureCreate(vd, picture->p_sys->surface, vasubpic[i_sub].i_id = SubpictureCreate(vd, subpicture, region,
subpicture, region,
&vasubpic[i_sub]); &vasubpic[i_sub]);
if (vasubpic[i_sub].i_id == VA_INVALID_ID) if (vasubpic[i_sub].i_id == VA_INVALID_ID)
{ {
...@@ -683,8 +683,8 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic ...@@ -683,8 +683,8 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic
} }
/* remember what was created, so it can be released in DisplayPicture() */ /* remember what was created, so it can be released in DisplayPicture() */
picture->p_sys->surface->subpicture = vasubpic; picture->p_sys->subpicture = vasubpic;
picture->p_sys->surface->i_sub = i_sub; picture->p_sys->i_sub = i_sub;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -709,7 +709,7 @@ static void PictureReleaseVoutOwned(picture_t *picture) ...@@ -709,7 +709,7 @@ static void PictureReleaseVoutOwned(picture_t *picture)
#if 0 #if 0
/* FIXME: pictures discarded by core will leak VASurfaces */ /* FIXME: pictures discarded by core will leak VASurfaces */
if (surface->i_id != VA_INVALID_SURFACE) if (surface->i_id != VA_INVALID_SURFACE)
vaDestroySurfaces(sys->conn->p_display, &psurface->i_id, 1); vaDestroySurfaces(sys->conn->p_display, &surface->i_id, 1);
#endif #endif
vlc_mutex_destroy(&surface->lock); vlc_mutex_destroy(&surface->lock);
free(surface); free(surface);
...@@ -725,6 +725,16 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict ...@@ -725,6 +725,16 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict
if (subpicture->b_ephemer) if (subpicture->b_ephemer)
return; return;
/* Cleanup for reclaimed surface */
if (picture->p_sys &&
picture->p_sys->subpicture &&
(picture->format.i_chroma == VLC_CODEC_VAAPI_SURFACE))
{
SubpictureDestroy(vd, picture->p_sys->subpicture, picture->p_sys->i_sub);
picture->p_sys->subpicture = NULL;
picture->p_sys->i_sub = 0;
}
if (picture->format.i_chroma != VLC_CODEC_VAAPI_SURFACE) if (picture->format.i_chroma != VLC_CODEC_VAAPI_SURFACE)
{ {
assert(picture->p_sys); assert(picture->p_sys);
...@@ -736,7 +746,7 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict ...@@ -736,7 +746,7 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict
picture->pf_release = PictureReleaseVoutOwned; picture->pf_release = PictureReleaseVoutOwned;
} }
if (picture->p_sys->surface == NULL) if (!picture->p_sys->surface)
return; return;
vlc_mutex_lock(&picture->p_sys->surface->lock); vlc_mutex_lock(&picture->p_sys->surface->lock);
...@@ -806,8 +816,12 @@ static void DisplayPicture(vout_display_t *vd, picture_t *pic, subpicture_t *sub ...@@ -806,8 +816,12 @@ static void DisplayPicture(vout_display_t *vd, picture_t *pic, subpicture_t *sub
{ {
assert(!pic->p_sys->b_own_vout); assert(!pic->p_sys->b_own_vout);
msg_Err(vd, "Discarding picture without surface information"); msg_Err(vd, "Discarding picture without surface information");
if (pic->p_sys->subpicture)
SubpictureDestroy(vd, pic->p_sys->subpicture, pic->p_sys->i_sub);
if (subpicture) if (subpicture)
subpicture_Delete(subpicture); subpicture_Delete(subpicture);
pic->p_sys->subpicture = NULL;
pic->p_sys->i_sub = 0;
picture_Release(pic); picture_Release(pic);
return; return;
} }
...@@ -832,22 +846,26 @@ static void DisplayPicture(vout_display_t *vd, picture_t *pic, subpicture_t *sub ...@@ -832,22 +846,26 @@ static void DisplayPicture(vout_display_t *vd, picture_t *pic, subpicture_t *sub
DisplayVASurface(vd, pic->p_sys->surface->i_id, pic); DisplayVASurface(vd, pic->p_sys->surface->i_id, pic);
cleanup: cleanup:
if (pic->p_sys->subpicture)
SubpictureDestroy(vd, pic->p_sys->subpicture, pic->p_sys->i_sub);
if (subpicture) if (subpicture)
{
SubpictureDestroy(vd, pic->p_sys->surface);
subpicture_Delete(subpicture); subpicture_Delete(subpicture);
}
if (pic->p_sys->b_own_vout) if (pic->p_sys->b_own_vout)
{ {
if (pic->p_sys->surface->i_id != VA_INVALID_SURFACE) if (pic->p_sys->surface->i_id != VA_INVALID_SURFACE)
vaDestroySurfaces(sys->conn->p_display, &pic->p_sys->surface->i_id, 1); vaDestroySurfaces(sys->conn->p_display, &pic->p_sys->surface->i_id, 1);
} }
ReleaseSurfaceLocked(pic->p_sys->surface); ReleaseSurfaceLocked(pic->p_sys->surface);
vlc_mutex_unlock(&pic->p_sys->surface->lock); vlc_mutex_unlock(&pic->p_sys->surface->lock);
if (!pic->p_sys->b_own_vout) if (!pic->p_sys->b_own_vout)
pic->p_sys->surface = NULL; pic->p_sys->surface = NULL;
pic->p_sys->subpicture = NULL;
pic->p_sys->i_sub = 0;
picture_Release(pic); picture_Release(pic);
} }
...@@ -873,14 +891,18 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count) ...@@ -873,14 +891,18 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
if (!pic) if (!pic)
break; break;
assert(pic->p_sys == NULL); assert(pic->p_sys == NULL);
picture_sys_t *sys = (picture_sys_t *) calloc(1, sizeof(picture_sys_t)); picture_sys_t *sys = (picture_sys_t *) malloc(sizeof(picture_sys_t));
if (!sys) if (!sys)
{ {
picture_Release(pic); picture_Release(pic);
break; break;
} }
pic->format.i_chroma = VLC_CODEC_VAAPI_SURFACE; pic->format.i_chroma = VLC_CODEC_VAAPI_SURFACE;
sys->b_own_vout = false; sys->b_own_vout = false;
sys->subpicture = NULL;
sys->surface = NULL;
sys->i_sub = 0;
pic_array[count] = pic; pic_array[count] = pic;
pic_array[count]->b_progressive = true; pic_array[count]->b_progressive = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment