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

VAAPI-X11: Rework subpicture cache management.

- rework refcounting
- rename functions to have cache_ prefix
- fix resetting of sys->render.i_cache in failure paths
parent c25b4e35
...@@ -126,9 +126,9 @@ typedef struct ...@@ -126,9 +126,9 @@ typedef struct
vlc_array_t subpictures; /* subpicture regions */ vlc_array_t subpictures; /* subpicture regions */
} subpicture_cache_t; } subpicture_cache_t;
static vasubpicture_cache_t *SubpictureCreate(vout_display_t *vd, const subpicture_t *subpicture, static vasubpicture_cache_t *cache_SubpictureCreate(vout_display_t *vd, const subpicture_t *subpicture,
const subpicture_region_t *region, const int flags); const subpicture_region_t *region, const int flags);
static void SubpictureDestroy(vout_display_t *vd, vlc_va_conn_t *conn, subpicture_cache_t *cache); static void cache_SubpictureDestroy(vout_display_t *vd, vlc_va_conn_t *conn, subpicture_cache_t *cache);
static subpicture_cache_t *cache_new(void) static subpicture_cache_t *cache_new(void)
{ {
...@@ -520,7 +520,7 @@ void CloseVaapiX11(vlc_object_t *obj) ...@@ -520,7 +520,7 @@ void CloseVaapiX11(vlc_object_t *obj)
vlc_array_remove(&sys->cache, i); vlc_array_remove(&sys->cache, i);
SubpictureDestroy(vd, sys->conn, cache); cache_SubpictureDestroy(vd, sys->conn, cache);
cache_destroy(cache); cache_destroy(cache);
cache = NULL; cache = NULL;
} }
...@@ -777,10 +777,10 @@ out_va_free: ...@@ -777,10 +777,10 @@ out_va_free:
/* Create subpicture cache for this subpicture and /* Create subpicture cache for this subpicture and
* allocate needed VA API resources. Call this * allocate needed VA API resources. Call this
* function when holding cache->lock */ * function when holding cache->lock */
static vasubpicture_cache_t *SubpictureCreate(vout_display_t *vd, const subpicture_t *subpicture, static vasubpicture_cache_t *cache_SubpictureCreate(vout_display_t *vd, const subpicture_t *subpicture,
const subpicture_region_t *region, const int flags) const subpicture_region_t *region, const int flags)
{ {
vout_display_sys_t *sys = vd->sys; vout_display_sys_t *sys = (vout_display_sys_t *) vd->sys;
sys->conn->lock(); sys->conn->lock();
...@@ -860,12 +860,12 @@ error: ...@@ -860,12 +860,12 @@ error:
/* Destroy subpicture cache for this subpicture and /* Destroy subpicture cache for this subpicture and
* release allocated VA API resources. Call this * release allocated VA API resources. Call this
* function when holding cache->lock */ * function when holding cache->lock */
static void SubpictureDestroy(vout_display_t *vd, vlc_va_conn_t *conn, subpicture_cache_t *cache) static void cache_SubpictureDestroy(vout_display_t *vd, vlc_va_conn_t *conn, subpicture_cache_t *cache)
{ {
vout_display_sys_t *sys = (vout_display_sys_t *)vd->sys; VLC_UNUSED(vd);
#ifdef VAAPI_DEBUG #ifdef VAAPI_DEBUG
msg_Dbg(vd, "SubpictureDestroy cache %d", cache->i_id); msg_Dbg(vd, "cache_SubpictureDestroy cache %d", cache->i_id);
#endif #endif
const int num = vlc_array_count(&cache->subpictures); const int num = vlc_array_count(&cache->subpictures);
for (int i = num - 1; i >= 0; i--) for (int i = num - 1; i >= 0; i--)
...@@ -883,7 +883,7 @@ static void SubpictureDestroy(vout_display_t *vd, vlc_va_conn_t *conn, subpictur ...@@ -883,7 +883,7 @@ static void SubpictureDestroy(vout_display_t *vd, vlc_va_conn_t *conn, subpictur
assert(subpic->i_id != VA_INVALID_ID); assert(subpic->i_id != VA_INVALID_ID);
assert(subpic->image.image_id != VA_INVALID_ID); assert(subpic->image.image_id != VA_INVALID_ID);
sys->conn->lock(); conn->lock();
vaDestroySubpicture(conn->p_display, subpic->i_id); vaDestroySubpicture(conn->p_display, subpic->i_id);
vaDestroyImage(conn->p_display, subpic->image.image_id); vaDestroyImage(conn->p_display, subpic->image.image_id);
...@@ -892,7 +892,7 @@ static void SubpictureDestroy(vout_display_t *vd, vlc_va_conn_t *conn, subpictur ...@@ -892,7 +892,7 @@ static void SubpictureDestroy(vout_display_t *vd, vlc_va_conn_t *conn, subpictur
subpic->image.buf = VA_INVALID_ID; subpic->image.buf = VA_INVALID_ID;
subpic->image.image_id = VA_INVALID_ID; subpic->image.image_id = VA_INVALID_ID;
sys->conn->unlock(); conn->unlock();
subpicture_cache_destroy(subpic); subpicture_cache_destroy(subpic);
subpic = NULL; subpic = NULL;
...@@ -916,10 +916,9 @@ static int SubpictureRegionsLink(vout_display_t *vd, const picture_t *picture) ...@@ -916,10 +916,9 @@ static int SubpictureRegionsLink(vout_display_t *vd, const picture_t *picture)
assert(cache->i_id > 0); assert(cache->i_id > 0);
const int count = vlc_array_count(&cache->subpictures); const int count = vlc_array_count(&cache->subpictures);
msg_Info(vd, "Subpicture cache count %d", vlc_array_count(&sys->cache));
#ifdef VAAPI_DEBUG #ifdef VAAPI_DEBUG
msg_Dbg(vd, "link surface %d cache %d size %d", msg_Dbg(vd, " link surface %d cache %d refcount %d",
surface->i_id, cache->i_id, count); surface->i_id, cache->i_id, cache->i_refcount);
#endif #endif
int i_sub = 0; int i_sub = 0;
...@@ -967,7 +966,6 @@ static int SubpictureRegionsLink(vout_display_t *vd, const picture_t *picture) ...@@ -967,7 +966,6 @@ static int SubpictureRegionsLink(vout_display_t *vd, const picture_t *picture)
i_sub++; i_sub++;
} }
cache_ref(cache);
vlc_mutex_unlock(&sys->cache_lock); vlc_mutex_unlock(&sys->cache_lock);
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -1016,7 +1014,8 @@ static void SubpictureRegionsUnlink(vout_display_t *vd, picture_t *picture) ...@@ -1016,7 +1014,8 @@ static void SubpictureRegionsUnlink(vout_display_t *vd, picture_t *picture)
assert(cache->i_id > 0); assert(cache->i_id > 0);
#ifdef VAAPI_DEBUG #ifdef VAAPI_DEBUG
msg_Dbg(vd, "unlink surface %d cache %d", surface->i_id, surface->i_cache); msg_Dbg(vd, "unlink surface %d cache %d size %d",
surface->i_id, surface->i_cache, count);
#endif #endif
const int count = vlc_array_count(&cache->subpictures); const int count = vlc_array_count(&cache->subpictures);
...@@ -1040,24 +1039,56 @@ static void SubpictureRegionsUnlink(vout_display_t *vd, picture_t *picture) ...@@ -1040,24 +1039,56 @@ static void SubpictureRegionsUnlink(vout_display_t *vd, picture_t *picture)
} }
} }
error:
vlc_mutex_unlock(&sys->cache_lock);
}
/* NOTE: call with sys->cache_lock held */
static void cache_SubpictureRelease(vout_display_t *vd, const int cache_id)
{
vout_display_sys_t *sys = vd->sys;
assert(cache_id > 0);
subpicture_cache_t *cache = cache_find(&sys->cache, cache_id);
if (cache)
{
#ifdef VAAPI_DEBUG
msg_Info(vd, "Release cache %d count %d refcount %d",
cache->i_id, vlc_array_count(&sys->cache), cache->i_refcount);
#endif
cache_unref(cache); cache_unref(cache);
/* Do we still need need this subpicture cache ? */ /* Do we still need need this subpicture cache ? */
if ((cache->i_refcount == 0) && if (cache->i_refcount == 0)
(sys->render.i_cache != surface->i_cache) &&
(mdate() > cache->i_stop))
{ {
#ifdef VAAPI_DEBUG
msg_Info(vd, "Deleting subpicture cache %d refcount %d",
cache->i_id, cache->i_refcount);
#endif
int index = vlc_array_index_of_item(&sys->cache, (void*)cache); int index = vlc_array_index_of_item(&sys->cache, (void*)cache);
vlc_array_remove(&sys->cache, index); vlc_array_remove(&sys->cache, index);
SubpictureDestroy(vd, sys->conn, cache); cache_SubpictureDestroy(vd, sys->conn, cache);
cache_destroy(cache); cache_destroy(cache);
cache = NULL; cache = NULL;
} }
}
}
surface->i_cache = 0; /* NOTE: call with sys->cache_lock held */
static void cache_SubpictureHold(vout_display_t *vd, const int cache_id)
{
vout_display_sys_t *sys = vd->sys;
error: subpicture_cache_t *cache = cache_find(&sys->cache, cache_id);
vlc_mutex_unlock(&sys->cache_lock); if (cache)
{
#ifdef VAAPI_DEBUG
msg_Info(vd, "Subpicture cache %d refcount %d",
cache->i_id, cache->i_refcount);
#endif
cache_ref(cache);
}
} }
static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture) static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
...@@ -1068,9 +1099,13 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic ...@@ -1068,9 +1099,13 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic
subpicture_cache_t *cache = cache_new(); subpicture_cache_t *cache = cache_new();
if (!cache) if (!cache)
return VLC_EGENERIC; return VLC_EGENERIC;
cache->i_start = subpicture->i_start; cache->i_start = subpicture->i_start;
cache->i_stop = subpicture->i_stop; cache->i_stop = subpicture->i_stop;
msg_Info(vd, "Subpicture cache count %d (%d/%d)",
vlc_array_count(&sys->cache), sys->render.i_cache, cache->i_id);
#ifdef VAAPI_DEBUG #ifdef VAAPI_DEBUG
msg_Dbg(vd, "new subpicture %p prev %p cache %d surface %d", msg_Dbg(vd, "new subpicture %p prev %p cache %d surface %d",
subpicture, sys->render.prev_subpicture, cache->i_id, surface->i_id); subpicture, sys->render.prev_subpicture, cache->i_id, surface->i_id);
...@@ -1089,7 +1124,7 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic ...@@ -1089,7 +1124,7 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic
/* Create Subpicture */ /* Create Subpicture */
vasubpicture_cache_t *vasub_cache; vasubpicture_cache_t *vasub_cache;
vasub_cache = SubpictureCreate(vd, subpicture, region, sys->sflags); vasub_cache = cache_SubpictureCreate(vd, subpicture, region, sys->sflags);
if (vasub_cache == NULL) if (vasub_cache == NULL)
goto cleanup; goto cleanup;
...@@ -1106,17 +1141,16 @@ static int RenderDirectSubpicture(vout_display_t *vd, picture_t *picture, subpic ...@@ -1106,17 +1141,16 @@ 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() */
vlc_mutex_lock(&sys->cache_lock); vlc_mutex_lock(&sys->cache_lock);
vlc_array_append(&sys->cache, (void *)cache); vlc_array_append(&sys->cache, (void *)cache);
//cache_ref(cache); cache_ref(cache);
sys->render.i_cache = cache->i_id; sys->render.i_cache = cache->i_id;
surface->i_cache = cache->i_id; surface->i_cache = cache->i_id;
vlc_mutex_unlock(&sys->cache_lock); vlc_mutex_unlock(&sys->cache_lock);
return VLC_SUCCESS; return VLC_SUCCESS;
cleanup: cleanup:
surface->i_cache = VA_INVALID_ID;
msg_Err(vd, "failed creating subpicture cache %d for surface %d", msg_Err(vd, "failed creating subpicture cache %d for surface %d",
cache->i_id, surface->i_id); cache->i_id, surface->i_id);
SubpictureDestroy(vd, sys->conn, cache); cache_SubpictureDestroy(vd, sys->conn, cache);
cache_destroy(cache); cache_destroy(cache);
cache = NULL; cache = NULL;
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -1183,7 +1217,7 @@ static int RenderCachedSubpictures(vout_display_t *vd, picture_t *picture, ...@@ -1183,7 +1217,7 @@ static int RenderCachedSubpictures(vout_display_t *vd, picture_t *picture,
goto cleanup; goto cleanup;
picture->p_sys->i_cache = cache->i_id; picture->p_sys->i_cache = cache->i_id;
//cache_ref(cache); cache_ref(cache);
vlc_mutex_unlock(&sys->cache_lock); vlc_mutex_unlock(&sys->cache_lock);
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -1191,7 +1225,6 @@ cleanup: ...@@ -1191,7 +1225,6 @@ cleanup:
/* Cannot reuse this cached subpicture */ /* Cannot reuse this cached subpicture */
msg_Err(vd, "cannot reuse cached subpicture %d for surface %d -- resetting", msg_Err(vd, "cannot reuse cached subpicture %d for surface %d -- resetting",
cache->i_id, surface->i_id); cache->i_id, surface->i_id);
sys->render.i_cache = 0;
sys->render.prev_subpicture = NULL; sys->render.prev_subpicture = NULL;
vlc_mutex_unlock(&sys->cache_lock); vlc_mutex_unlock(&sys->cache_lock);
return VLC_EGENERIC; return VLC_EGENERIC;
...@@ -1226,21 +1259,26 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict ...@@ -1226,21 +1259,26 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict
again: again:
/* same as previous subpicture? */ /* same as previous subpicture? */
if ((sys->render.prev_subpicture == subpicture) && if ((sys->render.prev_subpicture == subpicture) &&
(sys->render.i_cache > 0) && (sys->render.i_cache > 0))
(sys->render.i_start == subpicture->i_start) &&
(sys->render.i_stop == subpicture->i_stop))
{ {
assert(sys->render.i_cache > 0);
if (RenderCachedSubpictures(vd, picture, subpicture) != VLC_SUCCESS) if (RenderCachedSubpictures(vd, picture, subpicture) != VLC_SUCCESS)
goto again; goto again;
} }
else else
{ {
/* Release exra reference */
if (sys->render.i_cache > 0)
cache_SubpictureRelease(vd, sys->render.i_cache);
/* render new subpicture */
if (RenderDirectSubpicture(vd, picture, subpicture) != VLC_SUCCESS) if (RenderDirectSubpicture(vd, picture, subpicture) != VLC_SUCCESS)
return; return;
sys->render.prev_subpicture = subpicture; sys->render.prev_subpicture = subpicture;
sys->render.i_start = subpicture->i_start; sys->render.i_start = subpicture->i_start;
sys->render.i_stop = subpicture->i_stop; sys->render.i_stop = subpicture->i_stop;
/* Hold extra reference */
cache_SubpictureHold(vd, sys->render.i_cache);
} }
} }
...@@ -1299,6 +1337,12 @@ out: ...@@ -1299,6 +1337,12 @@ out:
{ {
if (ret == VLC_SUCCESS) if (ret == VLC_SUCCESS)
SubpictureRegionsUnlink(vd, picture); SubpictureRegionsUnlink(vd, picture);
vlc_mutex_lock(&sys->cache_lock);
cache_SubpictureRelease(vd, picture->p_sys->i_cache);
picture->p_sys->i_cache = 0;
vlc_mutex_unlock(&sys->cache_lock);
subpicture_Delete(subpicture); subpicture_Delete(subpicture);
} }
......
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