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

VAAPI: Cleanup video_output/vaapi/spu.{c,h}

Rename functions and structures.
parent 50eebc56
...@@ -94,8 +94,7 @@ struct vout_display_sys_t ...@@ -94,8 +94,7 @@ struct vout_display_sys_t
subpicture_t *prev_subpicture; subpicture_t *prev_subpicture;
} render; } render;
vlc_mutex_t cache_lock; vlc_va_spu_cache_t *spu;
vlc_array_t cache; /* array of subpicture_subpicture_cache_t */
xcb_cursor_t cursor; /* blank cursor */ xcb_cursor_t cursor; /* blank cursor */
xcb_window_t window; /* drawable X window */ xcb_window_t window; /* drawable X window */
...@@ -455,8 +454,12 @@ int OpenVaapiGLX(vlc_object_t *obj) ...@@ -455,8 +454,12 @@ int OpenVaapiGLX(vlc_object_t *obj)
vd->sys = sys; vd->sys = sys;
vlc_array_init(&sys->cache); sys->spu = vlc_va_spu_cache_New();
vlc_mutex_init(&sys->cache_lock); if (!sys->spu)
{
free(sys);
return VLC_ENOMEM;
}
sys->render.prev_subpicture = NULL; sys->render.prev_subpicture = NULL;
sys->render.i_cache = 0; sys->render.i_cache = 0;
...@@ -620,8 +623,8 @@ void CloseVaapiGLX(vlc_object_t *obj) ...@@ -620,8 +623,8 @@ void CloseVaapiGLX(vlc_object_t *obj)
} }
/* Cleanup cache */ /* Cleanup cache */
vlc_mutex_destroy(&sys->cache_lock); if (sys->spu)
cache_SubpictureEmpty(obj, va, &sys->cache); vlc_va_spu_cache_Delete(va, sys->spu);
/* Cleanup VAAPI resources and connection */ /* Cleanup VAAPI resources and connection */
if (va) if (va)
...@@ -692,47 +695,36 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict ...@@ -692,47 +695,36 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict
subpicture, sys->render.prev_subpicture, subpicture, sys->render.prev_subpicture,
sys->render.i_cache, picture->p_sys->i_id); sys->render.i_cache, picture->p_sys->i_id);
#endif #endif
vlc_mutex_lock(&sys->cache_lock); int ret = vlc_va_spu_cache_Get(VLC_OBJECT(vd), sys->spu, sys->render.i_cache,
int ret = RenderCachedSubpictures(VLC_OBJECT(vd), sys->va, &sys->cache, picture, subpicture);
sys->render.i_cache, picture, subpicture);
vlc_mutex_unlock(&sys->cache_lock);
if (ret == VLC_SUCCESS) if (ret == VLC_SUCCESS)
return; return;
} }
/* new subpicture */
vlc_mutex_lock(&sys->cache_lock);
/* Release exra reference */ /* Release exra reference */
if (sys->render.i_cache > 0) if (sys->render.i_cache > 0)
cache_SubpictureRelease(VLC_OBJECT(vd), sys->va, &sys->cache, sys->render.i_cache); vlc_va_spu_cache_Release(sys->va, sys->spu, sys->render.i_cache);
/* render new subpicture */ /* render new subpicture */
subpicture_cache_t *cache = RenderDirectSubpicture(VLC_OBJECT(vd), sys->va, &sys->sub_fmt, spu_cache_t *cache = vlc_va_spu_cache_Prepare(VLC_OBJECT(vd), sys->va, &sys->sub_fmt,
picture, subpicture, sys->sflags); picture, subpicture, sys->sflags);
if (cache == NULL) if (cache == NULL)
{
vlc_mutex_unlock(&sys->cache_lock);
return; return;
}
#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_GetCacheID(cache), surface->i_id); subpicture, sys->render.prev_subpicture, vlc_va_spu_cache_GetID(cache), surface->i_id);
#endif #endif
/* remember what was created, so it can be released in DisplayPicture() */ /* remember what was created, so it can be released in DisplayPicture() */
vlc_array_append(&sys->cache, (void *)cache); vlc_va_spu_cache_Put(sys->spu, cache);
sys->render.i_cache = cache_GetCacheID(cache); sys->render.i_cache = vlc_va_spu_cache_GetID(cache);
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 */ /* Hold extra reference */
cache_SubpictureHold(VLC_OBJECT(vd), &sys->cache, cache_GetCacheID(cache)); vlc_va_spu_cache_Hold(sys->spu, vlc_va_spu_cache_GetID(cache));
vlc_mutex_unlock(&sys->cache_lock);
} }
static void DisplayVASurfaceGLX(vout_display_t *vd, picture_t *picture) static void DisplayVASurfaceGLX(vout_display_t *vd, picture_t *picture)
...@@ -821,11 +813,9 @@ static void DisplayPicture(vout_display_t *vd, picture_t *picture, subpicture_t ...@@ -821,11 +813,9 @@ static void DisplayPicture(vout_display_t *vd, picture_t *picture, subpicture_t
if (subpicture) if (subpicture)
{ {
vlc_mutex_lock(&sys->cache_lock); ret = vlc_va_spu_cache_Link(VLC_OBJECT(vd), sys->va, sys->spu, picture, sys->sflags);
ret = SubpictureRegionsLink(VLC_OBJECT(vd), sys->va, &sys->cache, picture, sys->sflags);
if (ret == VLC_EGENERIC) if (ret == VLC_EGENERIC)
msg_Err(vd, "Failed linking subpicture to surface"); msg_Err(vd, "Failed linking subpicture to surface");
vlc_mutex_unlock(&sys->cache_lock);
} }
if (!vlc_gl_Lock(&sys->gl)) if (!vlc_gl_Lock(&sys->gl))
...@@ -840,16 +830,14 @@ static void DisplayPicture(vout_display_t *vd, picture_t *picture, subpicture_t ...@@ -840,16 +830,14 @@ static void DisplayPicture(vout_display_t *vd, picture_t *picture, subpicture_t
if (subpicture) if (subpicture)
{ {
vlc_mutex_lock(&sys->cache_lock);
if (ret == VLC_SUCCESS) if (ret == VLC_SUCCESS)
{ {
if (SubpictureRegionsUnlink(VLC_OBJECT(vd), sys->va, &sys->cache, picture) == VLC_EGENERIC) if (vlc_va_spu_cache_Unlink(VLC_OBJECT(vd), sys->va, sys->spu, picture) == VLC_EGENERIC)
msg_Err(vd, "Could not find subpicture in cache"); msg_Err(vd, "Could not find subpicture in cache");
} }
if (picture->p_sys->i_cache > 0) if (picture->p_sys->i_cache > 0)
cache_SubpictureRelease(VLC_OBJECT(vd), sys->va, &sys->cache, picture->p_sys->i_cache); vlc_va_spu_cache_Release(sys->va, sys->spu, picture->p_sys->i_cache);
picture->p_sys->i_cache = 0; picture->p_sys->i_cache = 0;
vlc_mutex_unlock(&sys->cache_lock);
} }
out: out:
......
...@@ -46,7 +46,13 @@ ...@@ -46,7 +46,13 @@
/* subpicture region cache management */ /* subpicture region cache management */
static unsigned int cache_counter = 0; static unsigned int cache_counter = 0;
struct vasubpicture_cache_t struct vlc_va_spu_cache_t
{
vlc_mutex_t lock;
vlc_array_t cache;
};
typedef struct va_spu_cache_t
{ {
VASubpictureID i_id; VASubpictureID i_id;
VAImage *image; VAImage *image;
...@@ -55,9 +61,9 @@ struct vasubpicture_cache_t ...@@ -55,9 +61,9 @@ struct vasubpicture_cache_t
int i_x, i_y; int i_x, i_y;
int i_width, i_height; int i_width, i_height;
} rect; } rect;
}; } va_spu_cache_t;
struct subpicture_cache_t struct spu_cache_t
{ {
unsigned int i_id; unsigned int i_id;
unsigned int i_refcount; /* refcount usage */ unsigned int i_refcount; /* refcount usage */
...@@ -67,9 +73,9 @@ struct subpicture_cache_t ...@@ -67,9 +73,9 @@ struct subpicture_cache_t
}; };
/* */ /* */
static subpicture_cache_t *cache_new(void) static spu_cache_t *cache_new(void)
{ {
subpicture_cache_t *cache = calloc(1, sizeof(subpicture_cache_t)); spu_cache_t *cache = calloc(1, sizeof(spu_cache_t));
if (cache == NULL) if (cache == NULL)
return NULL; return NULL;
...@@ -86,7 +92,7 @@ static subpicture_cache_t *cache_new(void) ...@@ -86,7 +92,7 @@ static subpicture_cache_t *cache_new(void)
return cache; return cache;
} }
static void cache_destroy(subpicture_cache_t *cache) static void cache_destroy(spu_cache_t *cache)
{ {
assert(cache); assert(cache);
assert(cache->i_refcount == 0); assert(cache->i_refcount == 0);
...@@ -99,14 +105,14 @@ static void cache_destroy(subpicture_cache_t *cache) ...@@ -99,14 +105,14 @@ static void cache_destroy(subpicture_cache_t *cache)
free(cache); free(cache);
} }
static subpicture_cache_t *cache_find(vlc_array_t *cache, const unsigned int id) static spu_cache_t *cache_find(vlc_array_t *cache, const unsigned int id)
{ {
assert(cache); assert(cache);
const int count = vlc_array_count(cache); const int count = vlc_array_count(cache);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
subpicture_cache_t *c = (subpicture_cache_t *) vlc_array_item_at_index(cache, i); spu_cache_t *c = (spu_cache_t *) vlc_array_item_at_index(cache, i);
if (!c) if (!c)
continue; continue;
if (c->i_id == id) if (c->i_id == id)
...@@ -115,13 +121,13 @@ static subpicture_cache_t *cache_find(vlc_array_t *cache, const unsigned int id) ...@@ -115,13 +121,13 @@ static subpicture_cache_t *cache_find(vlc_array_t *cache, const unsigned int id)
return NULL; return NULL;
} }
static inline void cache_ref(subpicture_cache_t *cache) static inline void cache_ref(spu_cache_t *cache)
{ {
assert(cache); assert(cache);
cache->i_refcount++; cache->i_refcount++;
} }
static inline void cache_unref(subpicture_cache_t *cache) static inline void cache_unref(spu_cache_t *cache)
{ {
assert(cache); assert(cache);
assert(cache->i_refcount > 0); assert(cache->i_refcount > 0);
...@@ -129,9 +135,9 @@ static inline void cache_unref(subpicture_cache_t *cache) ...@@ -129,9 +135,9 @@ static inline void cache_unref(subpicture_cache_t *cache)
cache->i_refcount--; cache->i_refcount--;
} }
static vasubpicture_cache_t *subpicture_cache_new( void ) static va_spu_cache_t *subpicture_cache_new( void )
{ {
vasubpicture_cache_t *cache = calloc(1, sizeof(vasubpicture_cache_t)); va_spu_cache_t *cache = calloc(1, sizeof(va_spu_cache_t));
if (cache == NULL) if (cache == NULL)
return NULL; return NULL;
...@@ -146,7 +152,7 @@ static vasubpicture_cache_t *subpicture_cache_new( void ) ...@@ -146,7 +152,7 @@ static vasubpicture_cache_t *subpicture_cache_new( void )
return cache; return cache;
} }
static void subpicture_cache_destroy(vasubpicture_cache_t *cache) static void subpicture_cache_destroy(va_spu_cache_t *cache)
{ {
assert(cache); assert(cache);
assert(cache->i_id == VA_INVALID_ID); assert(cache->i_id == VA_INVALID_ID);
...@@ -170,7 +176,7 @@ static void subpicture_cache_destroy(vasubpicture_cache_t *cache) ...@@ -170,7 +176,7 @@ static void subpicture_cache_destroy(vasubpicture_cache_t *cache)
cache = NULL; cache = NULL;
} }
static void subpicture_cache_link(vasubpicture_cache_t *cache, VASurfaceID *id) static void subpicture_cache_link(va_spu_cache_t *cache, VASurfaceID *id)
{ {
assert(cache); assert(cache);
...@@ -191,7 +197,7 @@ static void subpicture_cache_link(vasubpicture_cache_t *cache, VASurfaceID *id) ...@@ -191,7 +197,7 @@ static void subpicture_cache_link(vasubpicture_cache_t *cache, VASurfaceID *id)
} }
} }
static void subpicture_cache_unlink(vasubpicture_cache_t *cache, VASurfaceID *id) static void subpicture_cache_unlink(va_spu_cache_t *cache, VASurfaceID *id)
{ {
assert(cache); assert(cache);
...@@ -211,8 +217,7 @@ static void subpicture_cache_unlink(vasubpicture_cache_t *cache, VASurfaceID *id ...@@ -211,8 +217,7 @@ static void subpicture_cache_unlink(vasubpicture_cache_t *cache, VASurfaceID *id
} }
} }
unsigned int vlc_va_spu_cache_GetID(const spu_cache_t *cache)
unsigned int cache_GetCacheID(const subpicture_cache_t *cache)
{ {
assert(cache); assert(cache);
return cache->i_id; return cache->i_id;
...@@ -391,12 +396,12 @@ static int CopyRGBAToVAImage(vlc_object_t *obj, VADisplay p_display, ...@@ -391,12 +396,12 @@ static int CopyRGBAToVAImage(vlc_object_t *obj, VADisplay p_display,
/* 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 */
vasubpicture_cache_t *cache_SubpictureCreate(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *fmt, static va_spu_cache_t *va_spu_cache_Create(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *fmt,
const subpicture_t *subpicture, const subpicture_region_t *region, const int flags) const subpicture_t *subpicture, const subpicture_region_t *region, const int flags)
{ {
assert(subpicture); assert(subpicture);
vasubpicture_cache_t *vasub_cache = subpicture_cache_new(); va_spu_cache_t *vasub_cache = subpicture_cache_new();
if (unlikely(!vasub_cache)) if (unlikely(!vasub_cache))
return NULL; return NULL;
...@@ -470,29 +475,23 @@ cleanup: ...@@ -470,29 +475,23 @@ cleanup:
/* 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 */
void cache_SubpictureDestroy(vlc_object_t *obj, vlc_va_conn_t *va, subpicture_cache_t *cache, const bool b_force) static void va_spu_cache_Destroy(vlc_va_conn_t *va, spu_cache_t *cache, const bool b_force)
{ {
VLC_UNUSED(obj); assert(va);
assert(cache);
#ifdef VAAPI_DEBUG
msg_Dbg(obj, "cache_SubpictureDestroy cache %d", cache->i_id);
#endif
va->lock(); va->lock();
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--)
{ {
vasubpicture_cache_t *subpic; va_spu_cache_t *subpic;
subpic = (vasubpicture_cache_t *)vlc_array_item_at_index(&cache->subpictures, i); subpic = (va_spu_cache_t *)vlc_array_item_at_index(&cache->subpictures, i);
if (!subpic) if (!subpic)
continue; continue;
vlc_array_remove(&cache->subpictures, i); vlc_array_remove(&cache->subpictures, i);
#ifdef VAAPI_DEBUG
msg_Dbg(obj, "- %d: sub_id %d, image_id %d",
i, subpic->i_id, subpic->image->image_id);
#endif
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);
...@@ -510,16 +509,39 @@ void cache_SubpictureDestroy(vlc_object_t *obj, vlc_va_conn_t *va, subpicture_ca ...@@ -510,16 +509,39 @@ void cache_SubpictureDestroy(vlc_object_t *obj, vlc_va_conn_t *va, subpicture_ca
va->unlock(); va->unlock();
} }
int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array, static void va_spu_cache_ReleaseUnlocked(vlc_va_conn_t *va, vlc_va_spu_cache_t *spu, const int cache_id)
{
assert(spu);
spu_cache_t *cache = cache_find(&spu->cache, cache_id);
if (cache)
{
cache_unref(cache);
/* Do we still need need this subpicture cache ? */
if (cache->i_refcount == 0)
{
int index = vlc_array_index_of_item(&spu->cache, (void*)cache);
vlc_array_remove(&spu->cache, index);
va_spu_cache_Destroy(va, cache, false);
}
}
}
/* External API */
int vlc_va_spu_cache_Link(vlc_object_t *obj, vlc_va_conn_t *va, vlc_va_spu_cache_t *spu,
const picture_t *picture, const int flags) const picture_t *picture, const int flags)
{ {
assert(cache_array); assert(spu);
assert(picture);
assert(picture->p_sys); assert(picture->p_sys);
vlc_mutex_lock(&spu->lock);
picture_sys_t *surface = picture->p_sys; picture_sys_t *surface = picture->p_sys;
assert(surface->i_id != VA_INVALID_SURFACE); assert(surface->i_id != VA_INVALID_SURFACE);
subpicture_cache_t *cache = (subpicture_cache_t *) cache_find(cache_array, surface->i_cache); spu_cache_t *cache = cache_find(&spu->cache, surface->i_cache);
if (cache == NULL) if (cache == NULL)
goto error; goto error;
...@@ -534,8 +556,8 @@ int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cac ...@@ -534,8 +556,8 @@ int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cac
int i_sub = 0; int i_sub = 0;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
vasubpicture_cache_t *vasubpic; va_spu_cache_t *vasubpic;
vasubpic = (vasubpicture_cache_t *) vlc_array_item_at_index(&cache->subpictures, i); vasubpic = (va_spu_cache_t *) vlc_array_item_at_index(&cache->subpictures, i);
if (!vasubpic) if (!vasubpic)
goto cleanup; goto cleanup;
...@@ -576,6 +598,7 @@ int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cac ...@@ -576,6 +598,7 @@ int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cac
vasubpic = NULL; vasubpic = NULL;
i_sub++; i_sub++;
} }
vlc_mutex_unlock(&spu->lock);
return VLC_SUCCESS; return VLC_SUCCESS;
cleanup: cleanup:
...@@ -585,7 +608,7 @@ cleanup: ...@@ -585,7 +608,7 @@ cleanup:
#endif #endif
for (int i = 0; i < i_sub; i++) for (int i = 0; i < i_sub; i++)
{ {
vasubpicture_cache_t *sub = vlc_array_item_at_index(&cache->subpictures, i); va_spu_cache_t *sub = vlc_array_item_at_index(&cache->subpictures, i);
assert(sub); assert(sub);
if (sub->i_id != VA_INVALID_ID) if (sub->i_id != VA_INVALID_ID)
...@@ -606,38 +629,37 @@ cleanup: ...@@ -606,38 +629,37 @@ cleanup:
} }
error: error:
vlc_mutex_unlock(&spu->lock);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
int SubpictureRegionsUnlink(vlc_object_t *obj, vlc_va_conn_t *va, int vlc_va_spu_cache_Unlink(vlc_object_t *obj, vlc_va_conn_t *va,
vlc_array_t *cache_array, const picture_t *picture) vlc_va_spu_cache_t *spu, const picture_t *picture)
{ {
assert(cache_array); assert(spu);
assert(va);
vlc_mutex_lock(&spu->lock);
picture_sys_t *surface = picture->p_sys; picture_sys_t *surface = picture->p_sys;
assert(surface); assert(surface);
assert(surface->i_id != VA_INVALID_SURFACE); assert(surface->i_id != VA_INVALID_SURFACE);
assert(surface->i_cache > 0); assert(surface->i_cache > 0);
subpicture_cache_t *cache = cache_find(cache_array, surface->i_cache); spu_cache_t *cache = cache_find(&spu->cache, surface->i_cache);
if (cache == NULL) if (cache == NULL)
{
vlc_mutex_unlock(&spu->lock);
return VLC_EGENERIC; return VLC_EGENERIC;
}
assert(cache->i_id > 0); assert(cache->i_id > 0);
#ifdef VAAPI_DEBUG
msg_Dbg(obj, "unlink surface %d cache %d size %d",
surface->i_id, surface->i_cache, count);
#endif
const int count = vlc_array_count(&cache->subpictures); const int count = vlc_array_count(&cache->subpictures);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
vasubpicture_cache_t *sub = vlc_array_item_at_index(&cache->subpictures, i); va_spu_cache_t *sub = vlc_array_item_at_index(&cache->subpictures, i);
assert(sub); assert(sub);
#ifdef VAAPI_DEBUG
msg_Dbg(vd, "- %u: subid %d", i, sub->i_id);
#endif
VAStatus status = VA_STATUS_ERROR_UNKNOWN; VAStatus status = VA_STATUS_ERROR_UNKNOWN;
if (sub->i_id != VA_INVALID_ID) if (sub->i_id != VA_INVALID_ID)
{ {
...@@ -653,60 +675,34 @@ int SubpictureRegionsUnlink(vlc_object_t *obj, vlc_va_conn_t *va, ...@@ -653,60 +675,34 @@ int SubpictureRegionsUnlink(vlc_object_t *obj, vlc_va_conn_t *va,
subpicture_cache_unlink(sub, &surface->i_id); subpicture_cache_unlink(sub, &surface->i_id);
} }
} }
vlc_mutex_unlock(&spu->lock);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
void cache_SubpictureRelease(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array, const int cache_id) void vlc_va_spu_cache_Release(vlc_va_conn_t *va, vlc_va_spu_cache_t *spu, const int cache_id)
{ {
assert(cache_array); vlc_mutex_lock(&spu->lock);
va_spu_cache_ReleaseUnlocked(va, spu, cache_id);
subpicture_cache_t *cache = cache_find(cache_array, cache_id); vlc_mutex_unlock(&spu->lock);
if (cache)
{
#ifdef VAAPI_DEBUG
msg_Info(obj, "Release cache %d count %d refcount %d",
cache->i_id, vlc_array_count(cache_array), cache->i_refcount);
#endif
cache_unref(cache);
/* Do we still need need this subpicture cache ? */
if (cache->i_refcount == 0)
{
#ifdef VAAPI_DEBUG
msg_Info(obj, "Deleting subpicture cache %d refcount %d",
cache->i_id, cache->i_refcount);
#endif
int index = vlc_array_index_of_item(cache_array, (void*)cache);
vlc_array_remove(cache_array, index);
cache_SubpictureDestroy(obj, va, cache, false);
}
#ifdef VAAPI_DEBUG
msg_Info(obj, "cache id %d refcount %d", cache_id, cache->i_refcount);
#endif
}
} }
void cache_SubpictureHold(vlc_object_t *obj, vlc_array_t *cache_array, const int cache_id) void vlc_va_spu_cache_Hold(vlc_va_spu_cache_t *spu, const int cache_id)
{ {
VLC_UNUSED(obj); assert(spu);
subpicture_cache_t *cache = cache_find(cache_array, cache_id); vlc_mutex_lock(&spu->lock);
spu_cache_t *cache = cache_find(&spu->cache, cache_id);
if (cache) if (cache)
{
#ifdef VAAPI_DEBUG
msg_Info(obj, "Subpicture cache %d refcount %d",
cache->i_id, cache->i_refcount);
#endif
cache_ref(cache); cache_ref(cache);
} vlc_mutex_unlock(&spu->lock);
} }
subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *fmt, spu_cache_t *vlc_va_spu_cache_Prepare(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *fmt,
picture_t *picture, subpicture_t *subpicture, int flags) picture_t *picture, subpicture_t *subpicture, int flags)
{ {
picture_sys_t *surface = picture->p_sys; picture_sys_t *surface = picture->p_sys;
subpicture_cache_t *cache = cache_new(); spu_cache_t *cache = cache_new();
if (unlikely(!cache)) if (unlikely(!cache))
return NULL; return NULL;
...@@ -725,8 +721,8 @@ subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *va, ...@@ -725,8 +721,8 @@ subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *va,
assert(region->p_picture->format.i_height > 0); assert(region->p_picture->format.i_height > 0);
/* Create Subpicture */ /* Create Subpicture */
vasubpicture_cache_t *vasub_cache; va_spu_cache_t *vasub_cache;
vasub_cache = cache_SubpictureCreate(obj, va, fmt, subpicture, region, flags); vasub_cache = va_spu_cache_Create(obj, va, fmt, subpicture, region, flags);
if (vasub_cache == NULL) if (vasub_cache == NULL)
goto cleanup; goto cleanup;
...@@ -748,24 +744,35 @@ subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *va, ...@@ -748,24 +744,35 @@ subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *va,
cleanup: cleanup:
msg_Err(obj, "failed creating subpicture cache %d for surface %d", msg_Err(obj, "failed creating subpicture cache %d for surface %d",
cache->i_id, surface->i_id); cache->i_id, surface->i_id);
cache_SubpictureDestroy(obj, va, cache, false); va_spu_cache_Destroy(va, cache, false);
return NULL; return NULL;
} }
int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array, void vlc_va_spu_cache_Put(vlc_va_spu_cache_t *spu, spu_cache_t *cache)
const unsigned int cache_id, picture_t *picture, subpicture_t *subpicture)
{ {
VLC_UNUSED(va); assert(spu);
assert(cache);
vlc_mutex_lock(&spu->lock);
vlc_array_append(&spu->cache, (void *)cache);
vlc_mutex_unlock(&spu->lock);
}
int vlc_va_spu_cache_Get(vlc_object_t *obj, vlc_va_spu_cache_t *spu, const unsigned int cache_id,
picture_t *picture, subpicture_t *subpicture)
{
assert(spu);
assert(picture); assert(picture);
assert(subpicture); assert(subpicture);
vlc_mutex_lock(&spu->lock);
picture_sys_t *surface = picture->p_sys; picture_sys_t *surface = picture->p_sys;
subpicture_cache_t *cache = (subpicture_cache_t *) cache_find(cache_array, cache_id); spu_cache_t *cache = cache_find(&spu->cache, cache_id);
if (unlikely(cache == NULL)) if (unlikely(cache == NULL))
{ {
msg_Warn(obj, "subpicture cache id %d not found", cache_id); msg_Warn(obj, "subpicture cache id %d not found", cache_id);
vlc_mutex_unlock(&spu->lock);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -790,8 +797,8 @@ int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *c ...@@ -790,8 +797,8 @@ int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *c
if (i_sub >= count) if (i_sub >= count)
abort(); abort();
vasubpicture_cache_t *vasubpic; va_spu_cache_t *vasubpic;
vasubpic = (vasubpicture_cache_t *) vlc_array_item_at_index(&cache->subpictures, i_sub); vasubpic = (va_spu_cache_t *) vlc_array_item_at_index(&cache->subpictures, i_sub);
if (!vasubpic) if (!vasubpic)
goto cleanup; goto cleanup;
...@@ -813,30 +820,47 @@ int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *c ...@@ -813,30 +820,47 @@ int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *c
assert(cache->i_id == cache_id); assert(cache->i_id == cache_id);
surface->i_cache = cache->i_id; surface->i_cache = cache->i_id;
cache_ref(cache); cache_ref(cache);
vlc_mutex_unlock(&spu->lock);
return VLC_SUCCESS; return VLC_SUCCESS;
cleanup: cleanup:
/* Cannot reuse this cached subpicture */ /* Cannot reuse this cached subpicture */
msg_Warn(obj, "cannot reuse cached subpicture %d for surface %d -- resetting", msg_Warn(obj, "cannot reuse cached subpicture %d for surface %d -- resetting",
cache->i_id, surface->i_id); cache->i_id, surface->i_id);
vlc_mutex_unlock(&spu->lock);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
void cache_SubpictureEmpty(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *restrict cache) vlc_va_spu_cache_t *vlc_va_spu_cache_New(void)
{ {
const int count = vlc_array_count(cache); vlc_va_spu_cache_t *spu = malloc(sizeof(vlc_va_spu_cache_t));
if (!spu)
return NULL;
vlc_array_init(&spu->cache);
vlc_mutex_init(&spu->lock);
return spu;
}
void vlc_va_spu_cache_Delete(vlc_va_conn_t *va, vlc_va_spu_cache_t *restrict spu)
{
vlc_mutex_lock(&spu->lock);
const int count = vlc_array_count(&spu->cache);
for (int i = count - 1; i >= 0; i--) for (int i = count - 1; i >= 0; i--)
{ {
subpicture_cache_t *spu_cache; spu_cache_t *spu_cache;
spu_cache = (subpicture_cache_t*) vlc_array_item_at_index(cache, i); spu_cache = (spu_cache_t*) vlc_array_item_at_index(&spu->cache, i);
if (!spu_cache) if (!spu_cache)
continue; continue;
vlc_array_remove(cache, i); vlc_array_remove(&spu->cache, i);
cache_SubpictureRelease(obj, va, cache, cache_GetCacheID(spu_cache)); va_spu_cache_ReleaseUnlocked(va, spu, vlc_va_spu_cache_GetID(spu_cache));
cache_SubpictureDestroy(obj, va, spu_cache, true); va_spu_cache_Destroy(va, spu_cache, true);
} }
vlc_array_clear(cache); vlc_array_clear(&spu->cache);
vlc_mutex_unlock(&spu->lock);
vlc_mutex_destroy(&spu->lock);
} }
#endif #endif
...@@ -28,45 +28,39 @@ static const vlc_fourcc_t va_subpicture_chromas[] = { ...@@ -28,45 +28,39 @@ static const vlc_fourcc_t va_subpicture_chromas[] = {
0 0
}; };
/* NOTE: call all functions with sys->cache_lock held */
/* Check if subtitle format is supported by VA API */ /* Check if subtitle format is supported by VA API */
int VASubtitleFourCC(vlc_va_conn_t *va, const unsigned int vafourcc, VAImageFormat *sub_fmt, int *flags); int VASubtitleFourCC(vlc_va_conn_t *va, const unsigned int vafourcc, VAImageFormat *sub_fmt, int *flags);
/* */ /* */
typedef struct vasubpicture_cache_t vasubpicture_cache_t; typedef struct vlc_va_spu_cache_t vlc_va_spu_cache_t;
typedef struct subpicture_cache_t subpicture_cache_t; typedef struct spu_cache_t spu_cache_t;
/* Get Cache id */ /* Get Cache id */
unsigned int cache_GetCacheID(const subpicture_cache_t *cache); unsigned int vlc_va_spu_cache_GetID(const spu_cache_t *cache);
/* Empty the array of cached subpictures */ /* Empty the array of cached subpictures */
void cache_SubpictureEmpty(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *restrict cache); vlc_va_spu_cache_t *vlc_va_spu_cache_New(void);
void vlc_va_spu_cache_Delete(vlc_va_conn_t *va, vlc_va_spu_cache_t *restrict spu);
/* Create new VASubpicture */
vasubpicture_cache_t *cache_SubpictureCreate(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *sub_fmt,
const subpicture_t *subpicture, const subpicture_region_t *region, const int flags);
/* Destory VASubpicture and cached subpicture */
void cache_SubpictureDestroy(vlc_object_t *obj, vlc_va_conn_t *conn, subpicture_cache_t *cache, const bool b_force);
/* Hold reference to subpicture cache object */ /* Hold and Release reference to subpicture cache object */
void cache_SubpictureHold(vlc_object_t *obj, vlc_array_t *cache_array, const int cache_id); void vlc_va_spu_cache_Hold(vlc_va_spu_cache_t *spu, const int cache_id);
/* Release reference to subpicture cache object */ void vlc_va_spu_cache_Release(vlc_va_conn_t *va, vlc_va_spu_cache_t *spu, const int cache_id);
void cache_SubpictureRelease(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array, const int cache_id);
/* Link VASubpicture to VASurface */ /* Link/Unlink VASubpicture to/from VASurface */
int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array, int vlc_va_spu_cache_Link(vlc_object_t *obj, vlc_va_conn_t *va, vlc_va_spu_cache_t *spu,
const picture_t *picture, const int flags); const picture_t *picture, const int flags);
/* Unlink VASubpicture from VASurface */ int vlc_va_spu_cache_Unlink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_va_spu_cache_t *spu,
int SubpictureRegionsUnlink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array,
const picture_t *picture); const picture_t *picture);
/* Render VLC subpictures as VASubpictures and put them into a subpicture cache */ /* Create VLC subpictures as VASubpictures and put them into a subpicture cache */
subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *fmt, spu_cache_t *vlc_va_spu_cache_Prepare(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *fmt,
picture_t *picture, subpicture_t *subpicture, int flags); picture_t *picture, subpicture_t *subpicture, int flags);
/* Check if cached subpicture can be reused for the next Subpicture Render cycle */ /* Check if cached subpicture can be reused for the next Subpicture Render cycle */
int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array, int vlc_va_spu_cache_Get(vlc_object_t *obj, vlc_va_spu_cache_t *spu, const unsigned int cache_id,
const unsigned int cache_id, picture_t *picture, subpicture_t *subpicture); picture_t *picture, subpicture_t *subpicture);
void vlc_va_spu_cache_Put(vlc_va_spu_cache_t *spu, spu_cache_t *cache);
#endif #endif
#endif #endif
...@@ -92,8 +92,7 @@ struct vout_display_sys_t ...@@ -92,8 +92,7 @@ struct vout_display_sys_t
subpicture_t *prev_subpicture; subpicture_t *prev_subpicture;
} render; } render;
vlc_mutex_t cache_lock; vlc_va_spu_cache_t *spu;
vlc_array_t cache; /* array of subpicture_subpicture_cache_t */
xcb_cursor_t cursor; /* blank cursor */ xcb_cursor_t cursor; /* blank cursor */
xcb_window_t window; /* drawable X window */ xcb_window_t window; /* drawable X window */
...@@ -222,8 +221,12 @@ int OpenVaapiXCB(vlc_object_t *obj) ...@@ -222,8 +221,12 @@ int OpenVaapiXCB(vlc_object_t *obj)
vd->sys = sys; vd->sys = sys;
vlc_array_init(&sys->cache); sys->spu = vlc_va_spu_cache_New();
vlc_mutex_init(&sys->cache_lock); if (!sys->spu)
{
free(sys);
return VLC_ENOMEM;
}
sys->render.prev_subpicture = NULL; sys->render.prev_subpicture = NULL;
sys->render.i_cache = 0; sys->render.i_cache = 0;
...@@ -354,8 +357,8 @@ void CloseVaapiXCB(vlc_object_t *obj) ...@@ -354,8 +357,8 @@ void CloseVaapiXCB(vlc_object_t *obj)
sys->visible = false; sys->visible = false;
/* Cleanup cache */ /* Cleanup cache */
vlc_mutex_destroy(&sys->cache_lock); if (sys->spu)
cache_SubpictureEmpty(obj, va, &sys->cache); vlc_va_spu_cache_Delete(va, sys->spu);
/* */ /* */
if (va) if (va)
...@@ -424,47 +427,36 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict ...@@ -424,47 +427,36 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict
subpicture, sys->render.prev_subpicture, subpicture, sys->render.prev_subpicture,
sys->render.i_cache, picture->p_sys->i_id); sys->render.i_cache, picture->p_sys->i_id);
#endif #endif
vlc_mutex_lock(&sys->cache_lock); int ret = vlc_va_spu_cache_Get(VLC_OBJECT(vd), sys->spu, sys->render.i_cache,
int ret = RenderCachedSubpictures(VLC_OBJECT(vd), sys->va, &sys->cache, picture, subpicture);
sys->render.i_cache, picture, subpicture);
vlc_mutex_unlock(&sys->cache_lock);
if (ret == VLC_SUCCESS) if (ret == VLC_SUCCESS)
return; return;
} }
/* new subpicture */
vlc_mutex_lock(&sys->cache_lock);
/* Release exra reference */ /* Release exra reference */
if (sys->render.i_cache > 0) if (sys->render.i_cache > 0)
cache_SubpictureRelease(VLC_OBJECT(vd), sys->va, &sys->cache, sys->render.i_cache); vlc_va_spu_cache_Release(sys->va, sys->spu, sys->render.i_cache);
/* render new subpicture */ /* render new subpicture */
subpicture_cache_t *cache = RenderDirectSubpicture(VLC_OBJECT(vd), sys->va, &sys->sub_fmt, spu_cache_t *cache = vlc_va_spu_cache_Prepare(VLC_OBJECT(vd), sys->va, &sys->sub_fmt,
picture, subpicture, sys->sflags); picture, subpicture, sys->sflags);
if (cache == NULL) if (cache == NULL)
{
vlc_mutex_unlock(&sys->cache_lock);
return; return;
}
#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_GetCacheID(cache), surface->i_id); subpicture, sys->render.prev_subpicture, vlc_va_spu_cache_GetID(cache), surface->i_id);
#endif #endif
/* remember what was created, so it can be released in DisplayPicture() */ /* remember what was created, so it can be released in DisplayPicture() */
vlc_array_append(&sys->cache, (void *)cache); vlc_va_spu_cache_Put(sys->spu, cache);
sys->render.i_cache = cache_GetCacheID(cache); sys->render.i_cache = vlc_va_spu_cache_GetID(cache);
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 */ /* Hold extra reference */
cache_SubpictureHold(VLC_OBJECT(vd), &sys->cache, cache_GetCacheID(cache)); vlc_va_spu_cache_Hold(sys->spu, vlc_va_spu_cache_GetID(cache));
vlc_mutex_unlock(&sys->cache_lock);
} }
static void DisplayVASurface(vout_display_t *vd, picture_t *picture) static void DisplayVASurface(vout_display_t *vd, picture_t *picture)
...@@ -531,26 +523,22 @@ static void DisplayPicture(vout_display_t *vd, picture_t *picture, subpicture_t ...@@ -531,26 +523,22 @@ static void DisplayPicture(vout_display_t *vd, picture_t *picture, subpicture_t
if (subpicture) if (subpicture)
{ {
vlc_mutex_lock(&sys->cache_lock); ret = vlc_va_spu_cache_Link(VLC_OBJECT(vd), sys->va, sys->spu, picture, sys->sflags);
ret = SubpictureRegionsLink(VLC_OBJECT(vd), sys->va, &sys->cache, picture, sys->sflags);
if (ret == VLC_EGENERIC) if (ret == VLC_EGENERIC)
msg_Err(vd, "Failed linking subpicture to surface"); msg_Err(vd, "Failed linking subpicture to surface");
vlc_mutex_unlock(&sys->cache_lock);
} }
DisplayVASurface(vd, picture); DisplayVASurface(vd, picture);
if (subpicture) if (subpicture)
{ {
vlc_mutex_lock(&sys->cache_lock);
if (ret == VLC_SUCCESS) if (ret == VLC_SUCCESS)
{ {
if (SubpictureRegionsUnlink(VLC_OBJECT(vd), sys->va, &sys->cache, picture) == VLC_EGENERIC) if (vlc_va_spu_cache_Unlink(VLC_OBJECT(vd), sys->va, sys->spu, picture) == VLC_EGENERIC)
msg_Err(vd, "Could not find subpicture in cache"); msg_Err(vd, "Could not find subpicture in cache");
} }
if (picture->p_sys->i_cache > 0) if (picture->p_sys->i_cache > 0)
cache_SubpictureRelease(VLC_OBJECT(vd), sys->va, &sys->cache, picture->p_sys->i_cache); vlc_va_spu_cache_Release(sys->va, sys->spu, picture->p_sys->i_cache);
picture->p_sys->i_cache = 0; picture->p_sys->i_cache = 0;
vlc_mutex_unlock(&sys->cache_lock);
} }
out: out:
......
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