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
subpicture_t *prev_subpicture;
} render;
vlc_mutex_t cache_lock;
vlc_array_t cache; /* array of subpicture_subpicture_cache_t */
vlc_va_spu_cache_t *spu;
xcb_cursor_t cursor; /* blank cursor */
xcb_window_t window; /* drawable X window */
......@@ -455,8 +454,12 @@ int OpenVaapiGLX(vlc_object_t *obj)
vd->sys = sys;
vlc_array_init(&sys->cache);
vlc_mutex_init(&sys->cache_lock);
sys->spu = vlc_va_spu_cache_New();
if (!sys->spu)
{
free(sys);
return VLC_ENOMEM;
}
sys->render.prev_subpicture = NULL;
sys->render.i_cache = 0;
......@@ -620,8 +623,8 @@ void CloseVaapiGLX(vlc_object_t *obj)
}
/* Cleanup cache */
vlc_mutex_destroy(&sys->cache_lock);
cache_SubpictureEmpty(obj, va, &sys->cache);
if (sys->spu)
vlc_va_spu_cache_Delete(va, sys->spu);
/* Cleanup VAAPI resources and connection */
if (va)
......@@ -692,47 +695,36 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict
subpicture, sys->render.prev_subpicture,
sys->render.i_cache, picture->p_sys->i_id);
#endif
vlc_mutex_lock(&sys->cache_lock);
int ret = RenderCachedSubpictures(VLC_OBJECT(vd), sys->va, &sys->cache,
sys->render.i_cache, picture, subpicture);
vlc_mutex_unlock(&sys->cache_lock);
int ret = vlc_va_spu_cache_Get(VLC_OBJECT(vd), sys->spu, sys->render.i_cache,
picture, subpicture);
if (ret == VLC_SUCCESS)
return;
}
/* new subpicture */
vlc_mutex_lock(&sys->cache_lock);
/* Release exra reference */
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 */
subpicture_cache_t *cache = RenderDirectSubpicture(VLC_OBJECT(vd), sys->va, &sys->sub_fmt,
picture, subpicture, sys->sflags);
spu_cache_t *cache = vlc_va_spu_cache_Prepare(VLC_OBJECT(vd), sys->va, &sys->sub_fmt,
picture, subpicture, sys->sflags);
if (cache == NULL)
{
vlc_mutex_unlock(&sys->cache_lock);
return;
}
#ifdef VAAPI_DEBUG
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
/* 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.i_start = subpicture->i_start;
sys->render.i_stop = subpicture->i_stop;
/* Hold extra reference */
cache_SubpictureHold(VLC_OBJECT(vd), &sys->cache, cache_GetCacheID(cache));
vlc_mutex_unlock(&sys->cache_lock);
vlc_va_spu_cache_Hold(sys->spu, vlc_va_spu_cache_GetID(cache));
}
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
if (subpicture)
{
vlc_mutex_lock(&sys->cache_lock);
ret = SubpictureRegionsLink(VLC_OBJECT(vd), sys->va, &sys->cache, picture, sys->sflags);
ret = vlc_va_spu_cache_Link(VLC_OBJECT(vd), sys->va, sys->spu, picture, sys->sflags);
if (ret == VLC_EGENERIC)
msg_Err(vd, "Failed linking subpicture to surface");
vlc_mutex_unlock(&sys->cache_lock);
}
if (!vlc_gl_Lock(&sys->gl))
......@@ -840,16 +830,14 @@ static void DisplayPicture(vout_display_t *vd, picture_t *picture, subpicture_t
if (subpicture)
{
vlc_mutex_lock(&sys->cache_lock);
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");
}
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;
vlc_mutex_unlock(&sys->cache_lock);
}
out:
......
......@@ -46,7 +46,13 @@
/* subpicture region cache management */
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;
VAImage *image;
......@@ -55,9 +61,9 @@ struct vasubpicture_cache_t
int i_x, i_y;
int i_width, i_height;
} rect;
};
} va_spu_cache_t;
struct subpicture_cache_t
struct spu_cache_t
{
unsigned int i_id;
unsigned int i_refcount; /* refcount usage */
......@@ -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)
return NULL;
......@@ -86,7 +92,7 @@ static subpicture_cache_t *cache_new(void)
return cache;
}
static void cache_destroy(subpicture_cache_t *cache)
static void cache_destroy(spu_cache_t *cache)
{
assert(cache);
assert(cache->i_refcount == 0);
......@@ -99,14 +105,14 @@ static void cache_destroy(subpicture_cache_t *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);
const int count = vlc_array_count(cache);
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)
continue;
if (c->i_id == id)
......@@ -115,13 +121,13 @@ static subpicture_cache_t *cache_find(vlc_array_t *cache, const unsigned int id)
return NULL;
}
static inline void cache_ref(subpicture_cache_t *cache)
static inline void cache_ref(spu_cache_t *cache)
{
assert(cache);
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->i_refcount > 0);
......@@ -129,9 +135,9 @@ static inline void cache_unref(subpicture_cache_t *cache)
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)
return NULL;
......@@ -146,7 +152,7 @@ static vasubpicture_cache_t *subpicture_cache_new( void )
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->i_id == VA_INVALID_ID);
......@@ -170,7 +176,7 @@ static void subpicture_cache_destroy(vasubpicture_cache_t *cache)
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);
......@@ -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);
......@@ -211,8 +217,7 @@ static void subpicture_cache_unlink(vasubpicture_cache_t *cache, VASurfaceID *id
}
}
unsigned int cache_GetCacheID(const subpicture_cache_t *cache)
unsigned int vlc_va_spu_cache_GetID(const spu_cache_t *cache)
{
assert(cache);
return cache->i_id;
......@@ -391,12 +396,12 @@ static int CopyRGBAToVAImage(vlc_object_t *obj, VADisplay p_display,
/* Create subpicture cache for this subpicture and
* allocate needed VA API resources. Call this
* 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)
{
assert(subpicture);
vasubpicture_cache_t *vasub_cache = subpicture_cache_new();
va_spu_cache_t *vasub_cache = subpicture_cache_new();
if (unlikely(!vasub_cache))
return NULL;
......@@ -470,29 +475,23 @@ cleanup:
/* Destroy subpicture cache for this subpicture and
* release allocated VA API resources. Call this
* 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);
#ifdef VAAPI_DEBUG
msg_Dbg(obj, "cache_SubpictureDestroy cache %d", cache->i_id);
#endif
assert(va);
assert(cache);
va->lock();
const int num = vlc_array_count(&cache->subpictures);
for (int i = num - 1; i >= 0; i--)
{
vasubpicture_cache_t *subpic;
subpic = (vasubpicture_cache_t *)vlc_array_item_at_index(&cache->subpictures, i);
va_spu_cache_t *subpic;
subpic = (va_spu_cache_t *)vlc_array_item_at_index(&cache->subpictures, i);
if (!subpic)
continue;
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->image->image_id != VA_INVALID_ID);
......@@ -510,16 +509,39 @@ void cache_SubpictureDestroy(vlc_object_t *obj, vlc_va_conn_t *va, subpicture_ca
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)
{
assert(cache_array);
assert(spu);
assert(picture);
assert(picture->p_sys);
vlc_mutex_lock(&spu->lock);
picture_sys_t *surface = picture->p_sys;
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)
goto error;
......@@ -534,8 +556,8 @@ int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cac
int i_sub = 0;
for (int i = 0; i < count; i++)
{
vasubpicture_cache_t *vasubpic;
vasubpic = (vasubpicture_cache_t *) vlc_array_item_at_index(&cache->subpictures, i);
va_spu_cache_t *vasubpic;
vasubpic = (va_spu_cache_t *) vlc_array_item_at_index(&cache->subpictures, i);
if (!vasubpic)
goto cleanup;
......@@ -576,6 +598,7 @@ int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cac
vasubpic = NULL;
i_sub++;
}
vlc_mutex_unlock(&spu->lock);
return VLC_SUCCESS;
cleanup:
......@@ -585,7 +608,7 @@ cleanup:
#endif
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);
if (sub->i_id != VA_INVALID_ID)
......@@ -606,38 +629,37 @@ cleanup:
}
error:
vlc_mutex_unlock(&spu->lock);
return VLC_EGENERIC;
}
int SubpictureRegionsUnlink(vlc_object_t *obj, vlc_va_conn_t *va,
vlc_array_t *cache_array, const picture_t *picture)
int vlc_va_spu_cache_Unlink(vlc_object_t *obj, vlc_va_conn_t *va,
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;
assert(surface);
assert(surface->i_id != VA_INVALID_SURFACE);
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)
{
vlc_mutex_unlock(&spu->lock);
return VLC_EGENERIC;
}
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);
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);
#ifdef VAAPI_DEBUG
msg_Dbg(vd, "- %u: subid %d", i, sub->i_id);
#endif
VAStatus status = VA_STATUS_ERROR_UNKNOWN;
if (sub->i_id != VA_INVALID_ID)
{
......@@ -653,60 +675,34 @@ int SubpictureRegionsUnlink(vlc_object_t *obj, vlc_va_conn_t *va,
subpicture_cache_unlink(sub, &surface->i_id);
}
}
vlc_mutex_unlock(&spu->lock);
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);
subpicture_cache_t *cache = cache_find(cache_array, cache_id);
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
}
vlc_mutex_lock(&spu->lock);
va_spu_cache_ReleaseUnlocked(va, spu, cache_id);
vlc_mutex_unlock(&spu->lock);
}
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)
{
#ifdef VAAPI_DEBUG
msg_Info(obj, "Subpicture cache %d refcount %d",
cache->i_id, cache->i_refcount);
#endif
cache_ref(cache);
}
vlc_mutex_unlock(&spu->lock);
}
subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *va, VAImageFormat *fmt,
picture_t *picture, subpicture_t *subpicture, int flags)
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_sys_t *surface = picture->p_sys;
subpicture_cache_t *cache = cache_new();
spu_cache_t *cache = cache_new();
if (unlikely(!cache))
return NULL;
......@@ -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);
/* Create Subpicture */
vasubpicture_cache_t *vasub_cache;
vasub_cache = cache_SubpictureCreate(obj, va, fmt, subpicture, region, flags);
va_spu_cache_t *vasub_cache;
vasub_cache = va_spu_cache_Create(obj, va, fmt, subpicture, region, flags);
if (vasub_cache == NULL)
goto cleanup;
......@@ -748,24 +744,35 @@ subpicture_cache_t *RenderDirectSubpicture(vlc_object_t *obj, vlc_va_conn_t *va,
cleanup:
msg_Err(obj, "failed creating subpicture cache %d for surface %d",
cache->i_id, surface->i_id);
cache_SubpictureDestroy(obj, va, cache, false);
va_spu_cache_Destroy(va, cache, false);
return NULL;
}
int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array,
const unsigned int cache_id, picture_t *picture, subpicture_t *subpicture)
void vlc_va_spu_cache_Put(vlc_va_spu_cache_t *spu, spu_cache_t *cache)
{
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(subpicture);
vlc_mutex_lock(&spu->lock);
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))
{
msg_Warn(obj, "subpicture cache id %d not found", cache_id);
vlc_mutex_unlock(&spu->lock);
return VLC_EGENERIC;
}
......@@ -790,8 +797,8 @@ int RenderCachedSubpictures(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *c
if (i_sub >= count)
abort();
vasubpicture_cache_t *vasubpic;
vasubpic = (vasubpicture_cache_t *) vlc_array_item_at_index(&cache->subpictures, i_sub);
va_spu_cache_t *vasubpic;
vasubpic = (va_spu_cache_t *) vlc_array_item_at_index(&cache->subpictures, i_sub);
if (!vasubpic)
goto cleanup;
......@@ -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);
surface->i_cache = cache->i_id;
cache_ref(cache);
vlc_mutex_unlock(&spu->lock);
return VLC_SUCCESS;
cleanup:
/* Cannot reuse this cached subpicture */
msg_Warn(obj, "cannot reuse cached subpicture %d for surface %d -- resetting",
cache->i_id, surface->i_id);
vlc_mutex_unlock(&spu->lock);
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--)
{
subpicture_cache_t *spu_cache;
spu_cache = (subpicture_cache_t*) vlc_array_item_at_index(cache, i);
spu_cache_t *spu_cache;
spu_cache = (spu_cache_t*) vlc_array_item_at_index(&spu->cache, i);
if (!spu_cache)
continue;
vlc_array_remove(cache, i);
vlc_array_remove(&spu->cache, i);
cache_SubpictureRelease(obj, va, cache, cache_GetCacheID(spu_cache));
cache_SubpictureDestroy(obj, va, spu_cache, true);
va_spu_cache_ReleaseUnlocked(va, spu, vlc_va_spu_cache_GetID(spu_cache));
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
......@@ -28,45 +28,39 @@ static const vlc_fourcc_t va_subpicture_chromas[] = {
0
};
/* NOTE: call all functions with sys->cache_lock held */
/* 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);
/* */
typedef struct vasubpicture_cache_t vasubpicture_cache_t;
typedef struct subpicture_cache_t subpicture_cache_t;
typedef struct vlc_va_spu_cache_t vlc_va_spu_cache_t;
typedef struct spu_cache_t spu_cache_t;
/* 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 */
void cache_SubpictureEmpty(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *restrict cache);
/* 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);
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);
/* Hold reference to subpicture cache object */
void cache_SubpictureHold(vlc_object_t *obj, vlc_array_t *cache_array, const int cache_id);
/* Release reference to subpicture cache object */
void cache_SubpictureRelease(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array, const int cache_id);
/* Hold and Release reference to subpicture cache object */
void vlc_va_spu_cache_Hold(vlc_va_spu_cache_t *spu, 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);
/* Link VASubpicture to VASurface */
int SubpictureRegionsLink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array,
/* Link/Unlink VASubpicture to/from VASurface */
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);
/* Unlink VASubpicture from VASurface */
int SubpictureRegionsUnlink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_array_t *cache_array,
int vlc_va_spu_cache_Unlink(vlc_object_t *obj, vlc_va_conn_t *va, vlc_va_spu_cache_t *spu,
const picture_t *picture);
/* Render 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,
picture_t *picture, subpicture_t *subpicture, int flags);
/* Create VLC subpictures as VASubpictures and put them into a subpicture cache */
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);
/* 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,
const unsigned int cache_id, picture_t *picture, subpicture_t *subpicture);
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);
void vlc_va_spu_cache_Put(vlc_va_spu_cache_t *spu, spu_cache_t *cache);
#endif
#endif
......@@ -92,8 +92,7 @@ struct vout_display_sys_t
subpicture_t *prev_subpicture;
} render;
vlc_mutex_t cache_lock;
vlc_array_t cache; /* array of subpicture_subpicture_cache_t */
vlc_va_spu_cache_t *spu;
xcb_cursor_t cursor; /* blank cursor */
xcb_window_t window; /* drawable X window */
......@@ -222,8 +221,12 @@ int OpenVaapiXCB(vlc_object_t *obj)
vd->sys = sys;
vlc_array_init(&sys->cache);
vlc_mutex_init(&sys->cache_lock);
sys->spu = vlc_va_spu_cache_New();
if (!sys->spu)
{
free(sys);
return VLC_ENOMEM;
}
sys->render.prev_subpicture = NULL;
sys->render.i_cache = 0;
......@@ -354,8 +357,8 @@ void CloseVaapiXCB(vlc_object_t *obj)
sys->visible = false;
/* Cleanup cache */
vlc_mutex_destroy(&sys->cache_lock);
cache_SubpictureEmpty(obj, va, &sys->cache);
if (sys->spu)
vlc_va_spu_cache_Delete(va, sys->spu);
/* */
if (va)
......@@ -424,47 +427,36 @@ static void Render(vout_display_t *vd, picture_t *picture, subpicture_t *subpict
subpicture, sys->render.prev_subpicture,
sys->render.i_cache, picture->p_sys->i_id);
#endif
vlc_mutex_lock(&sys->cache_lock);
int ret = RenderCachedSubpictures(VLC_OBJECT(vd), sys->va, &sys->cache,
sys->render.i_cache, picture, subpicture);
vlc_mutex_unlock(&sys->cache_lock);
int ret = vlc_va_spu_cache_Get(VLC_OBJECT(vd), sys->spu, sys->render.i_cache,
picture, subpicture);
if (ret == VLC_SUCCESS)
return;
}
/* new subpicture */
vlc_mutex_lock(&sys->cache_lock);
/* Release exra reference */
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 */
subpicture_cache_t *cache = RenderDirectSubpicture(VLC_OBJECT(vd), sys->va, &sys->sub_fmt,
picture, subpicture, sys->sflags);
spu_cache_t *cache = vlc_va_spu_cache_Prepare(VLC_OBJECT(vd), sys->va, &sys->sub_fmt,
picture, subpicture, sys->sflags);
if (cache == NULL)
{
vlc_mutex_unlock(&sys->cache_lock);
return;
}
#ifdef VAAPI_DEBUG
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
/* 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.i_start = subpicture->i_start;
sys->render.i_stop = subpicture->i_stop;
/* Hold extra reference */
cache_SubpictureHold(VLC_OBJECT(vd), &sys->cache, cache_GetCacheID(cache));
vlc_mutex_unlock(&sys->cache_lock);
vlc_va_spu_cache_Hold(sys->spu, vlc_va_spu_cache_GetID(cache));
}
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
if (subpicture)
{
vlc_mutex_lock(&sys->cache_lock);
ret = SubpictureRegionsLink(VLC_OBJECT(vd), sys->va, &sys->cache, picture, sys->sflags);
ret = vlc_va_spu_cache_Link(VLC_OBJECT(vd), sys->va, sys->spu, picture, sys->sflags);
if (ret == VLC_EGENERIC)
msg_Err(vd, "Failed linking subpicture to surface");
vlc_mutex_unlock(&sys->cache_lock);
}
DisplayVASurface(vd, picture);
if (subpicture)
{
vlc_mutex_lock(&sys->cache_lock);
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");
}
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;
vlc_mutex_unlock(&sys->cache_lock);
}
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