From: SeokYeon Hwang Date: Wed, 24 Sep 2014 07:30:27 +0000 (+0900) Subject: brillcodec: introduce plug-in context management X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.2~620^2~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7b136cbf146862c6dfe2d194effd07435fa53314;p=sdk%2Femulator%2Fqemu.git brillcodec: introduce plug-in context management Now context management of HWACCEL plugin is enabled. Fix memory leaks. Fix device resource leaks. Change-Id: I2651ba331214ffb48c89f6b826ecc93bcb4d34fb Signed-off-by: SeokYeon Hwang --- diff --git a/tizen/src/hw/pci/maru_brillcodec.c b/tizen/src/hw/pci/maru_brillcodec.c index a10238d2d7..f4784cbcff 100644 --- a/tizen/src/hw/pci/maru_brillcodec.c +++ b/tizen/src/hw/pci/maru_brillcodec.c @@ -1510,9 +1510,11 @@ static enum PixelFormat get_format(AVCodecContext *avctx, goto end; } - if (!s->hwaccel_plugin->setup(avctx, avctx->width, avctx->height)) { + void *plugin_context = s->hwaccel_plugin->setup(avctx, avctx->width, avctx->height); + if (!plugin_context) { goto end; } + set_plugin_context(avctx, plugin_context); for (i = 0; pi_fmt[i] != PIX_FMT_NONE; ++i) { if (pi_fmt[i] == s->hwaccel_plugin->pix_fmt) { @@ -1814,35 +1816,47 @@ static bool deinit(MaruBrillCodecState *s, int ctx_id, void *data_buf) INFO("close avcontext of %d\n", ctx_id); avcodec_close(avctx); - CONTEXT(s, ctx_id)->opened_context = false; + + if (CONTEXT(s, ctx_id)->is_hwaccel) { + CodecPlugin *plugin = CONTEXT(s, ctx_id)->state->hwaccel_plugin; + plugin->cleanup(get_plugin_context(avctx)); + } if (avctx->extradata) { TRACE("free context extradata\n"); av_free(avctx->extradata); - CONTEXT(s, ctx_id)->avctx->extradata = NULL; } if (frame) { TRACE("free frame\n"); avcodec_free_frame(&frame); - CONTEXT(s, ctx_id)->frame = NULL; } if (avctx) { TRACE("free codec context\n"); av_free(avctx); - CONTEXT(s, ctx_id)->avctx = NULL; } if (parserctx) { INFO("close parser context\n"); av_parser_close(parserctx); - CONTEXT(s, ctx_id)->parser_ctx = NULL; } + memset(CONTEXT(s, ctx_id), 0x00, sizeof(CodecContext)); + brillcodec_push_writequeue(s, NULL, 0, ctx_id, NULL); TRACE("leave: %s\n", __func__); return true; } + +inline void set_plugin_context(AVCodecContext *avctx, void *plugin_context) +{ + ((CodecContext *)avctx->opaque)->plugin_context = plugin_context; +} + +inline void *get_plugin_context(AVCodecContext *avctx) +{ + return ((CodecContext *)avctx->opaque)->plugin_context; +} diff --git a/tizen/src/hw/pci/maru_brillcodec.h b/tizen/src/hw/pci/maru_brillcodec.h index 1304447f45..53b3681927 100644 --- a/tizen/src/hw/pci/maru_brillcodec.h +++ b/tizen/src/hw/pci/maru_brillcodec.h @@ -68,6 +68,7 @@ typedef struct CodecContext { bool requested_close; bool is_hwaccel; + void *plugin_context; } CodecContext; typedef struct CodecThreadPool { diff --git a/tizen/src/hw/pci/maru_brillcodec_plugin.h b/tizen/src/hw/pci/maru_brillcodec_plugin.h index cfbf52d4a4..cc3a485f1e 100644 --- a/tizen/src/hw/pci/maru_brillcodec_plugin.h +++ b/tizen/src/hw/pci/maru_brillcodec_plugin.h @@ -33,12 +33,16 @@ #include "stdbool.h" +extern void *get_plugin_context(AVCodecContext *avctx); +extern void set_plugin_context(AVCodecContext *avctx, void *plugin_context); + typedef struct CodecPlugin { char const *name; enum PixelFormat pix_fmt; enum PixelFormat output_pix_fmt; bool (*probe)(void); - bool (*setup)(AVCodecContext *, int , int); + void *(*setup)(AVCodecContext *, int , int); + void (*cleanup)(void *); int (*get_buffer)(struct AVCodecContext *, AVFrame *); void (*release_buffer)(struct AVCodecContext *, AVFrame *); void (*get_picture)(void *dst, void *src); diff --git a/tizen/src/hw/pci/maru_brillcodec_vaapi.c b/tizen/src/hw/pci/maru_brillcodec_vaapi.c index 45a6118925..b3b7bbb43a 100644 --- a/tizen/src/hw/pci/maru_brillcodec_vaapi.c +++ b/tizen/src/hw/pci/maru_brillcodec_vaapi.c @@ -44,31 +44,44 @@ #include "maru_brillcodec_plugin.h" -#define SURFACE_COUNT 4 +#define DEFAULT_SURFACE_COUNT 4 -typedef struct VAPluginContext { +struct SurfaceState; +typedef struct SurfaceState SurfaceState; + +typedef struct { + void *display; + VAConfigID config_id; VAContextID context_id; - VASurfaceID surface_id[SURFACE_COUNT]; - bool surface_is_occupied[SURFACE_COUNT]; + + unsigned int surface_count; + VASurfaceID *surface_id; + SurfaceState *surface_state; VAImage image; bool is_supports_derive; } VAPluginContext; +struct SurfaceState { + VAPluginContext *va_ctx; + bool is_occupied; +}; + static void *va_display; static int va_major_version, va_minor_version; // FIXME -static VAPluginContext *va_ctx = &(VAPluginContext) {}; - +//static VAPluginContext *va_ctx = &(VAPluginContext) {}; // fuction pointers to VAAPI VADisplay (*_vaGetDisplay)(Display *); VAStatus (*_vaInitialize)(VADisplay, int *, int *); + int (*_vaMaxNumProfiles)(VADisplay); VAStatus (*_vaQueryConfigProfiles)(VADisplay, VAProfile *, int *); VAStatus (*_vaGetConfigAttributes)(VADisplay, VAProfile, VAEntrypoint, VAConfigAttrib *, int); VAStatus (*_vaCreateConfig)(VADisplay, VAProfile, VAEntrypoint, VAConfigAttrib *, int, VAConfigID *); +VAStatus (*_vaDestroyConfig)(VADisplay, VAConfigID); void (*_vaCreateSurfaces)(void); // for VAAPI version >= 0.34 @@ -76,8 +89,10 @@ typedef VAStatus (*_vaCreateSurfaces8)(VADisplay, unsigned int, unsigned int, un unsigned int, VASurfaceAttrib *, unsigned int); // for VAAPI version < 0.34 typedef VAStatus (*_vaCreateSurfaces6)(VADisplay, int, int, int, int, VASurfaceID *); +VAStatus (*_vaDestroySurfaces)(VADisplay, VASurfaceID *, int); VAStatus (*_vaCreateContext)(VADisplay, VAConfigID, int, int, int, VASurfaceID *, int, VAContextID *); +VAStatus (*_vaDestroyContext)(VADisplay, VAContextID); int (*_vaMaxNumImageFormats)(VADisplay dpy); VAStatus (*_vaQueryImageFormats)(VADisplay, VAImageFormat *, int *); VAStatus (*_vaDeriveImage)(VADisplay, VASurfaceID, VAImage *); @@ -155,8 +170,11 @@ static bool probe(void) DLSYM(vaQueryConfigProfiles); DLSYM(vaGetConfigAttributes); DLSYM(vaCreateConfig); + DLSYM(vaDestroyConfig); DLSYM(vaCreateSurfaces); + DLSYM(vaDestroySurfaces); DLSYM(vaCreateContext); + DLSYM(vaDestroyContext); DLSYM(vaMaxNumImageFormats); DLSYM(vaQueryImageFormats); DLSYM(vaDeriveImage); @@ -181,17 +199,19 @@ error: return false; } -static int create_surfaces(AVCodecContext *ctx, int width, int height, VAProfile profile) +static int create_surfaces(VAPluginContext *va_ctx, + int width, int height, VAProfile profile) { assert(width > 0 && height > 0); - VAConfigID config_id; + int i; + VAImageFormat *p_fmt = NULL; /* Create a VA configuration */ VAConfigAttrib attrib; memset(&attrib, 0, sizeof(attrib)); attrib.type = VAConfigAttribRTFormat; - if (_vaGetConfigAttributes(va_display, + if (_vaGetConfigAttributes(va_ctx->display, profile, VAEntrypointVLD, &attrib, 1)) { goto error; } @@ -200,79 +220,109 @@ static int create_surfaces(AVCodecContext *ctx, int width, int height, VAProfile if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) goto error; - if (_vaCreateConfig(va_display, - profile, VAEntrypointVLD, &attrib, 1, &config_id)) { + if (_vaCreateConfig(va_ctx->display, + profile, VAEntrypointVLD, &attrib, 1, &va_ctx->config_id)) { goto error; } + va_ctx->surface_count = DEFAULT_SURFACE_COUNT; // FIXME + + va_ctx->surface_id = g_malloc_n(va_ctx->surface_count, sizeof(VASurfaceID)); + va_ctx->surface_state = g_malloc_n(va_ctx->surface_count, sizeof(SurfaceState)); + + for (i = 0; i < va_ctx->surface_count; ++i) { + va_ctx->surface_state[i].va_ctx = va_ctx; + va_ctx->surface_state[i].is_occupied = false; + } + /* Create surfaces */ if (check_version(0, 34)) { - if (((_vaCreateSurfaces8)_vaCreateSurfaces)(va_display, VA_RT_FORMAT_YUV420, width, height, - va_ctx->surface_id, SURFACE_COUNT, NULL, 0)) { + if (((_vaCreateSurfaces8)_vaCreateSurfaces)(va_ctx->display, VA_RT_FORMAT_YUV420, width, height, + va_ctx->surface_id, va_ctx->surface_count, NULL, 0)) { goto error; } } else { - if (((_vaCreateSurfaces6)_vaCreateSurfaces)(va_display, width, height, VA_RT_FORMAT_YUV420, - SURFACE_COUNT, va_ctx->surface_id)) { + if (((_vaCreateSurfaces6)_vaCreateSurfaces)(va_ctx->display, width, height, VA_RT_FORMAT_YUV420, + va_ctx->surface_count, va_ctx->surface_id)) { goto error; } } va_ctx->context_id = VA_INVALID_ID; /* Create a context */ - if (_vaCreateContext(va_display, config_id, + if (_vaCreateContext(va_ctx->display, va_ctx->config_id, width, height, VA_PROGRESSIVE, - va_ctx->surface_id, SURFACE_COUNT, &va_ctx->context_id)) { + va_ctx->surface_id, va_ctx->surface_count, &va_ctx->context_id)) { goto error; } - int fmt_count = _vaMaxNumImageFormats(va_display); - VAImageFormat *p_fmt = g_malloc0_n(fmt_count, sizeof(*p_fmt)); + int fmt_count = _vaMaxNumImageFormats(va_ctx->display); + p_fmt = g_malloc0_n(fmt_count, sizeof(*p_fmt)); if (!p_fmt) { goto error; } - if (_vaQueryImageFormats(va_display, p_fmt, &fmt_count)) { - g_free(p_fmt); + if (_vaQueryImageFormats(va_ctx->display, p_fmt, &fmt_count)) { goto error; } VAImage test_image; - if (_vaDeriveImage(va_display, va_ctx->surface_id[0], &test_image) == VA_STATUS_SUCCESS) { + if (_vaDeriveImage(va_ctx->display, va_ctx->surface_id[0], &test_image) == VA_STATUS_SUCCESS) { va_ctx->is_supports_derive = true; - _vaDestroyImage(va_display, test_image.image_id); + _vaDestroyImage(va_ctx->display, test_image.image_id); } - int i; for (i = 0; i < fmt_count; ++i) { if (p_fmt[i].fourcc == VA_FOURCC_YV12) { // we support only VA_FOURCC_YV12 for now... - if (_vaCreateImage(va_display, &p_fmt[i], width, height, &va_ctx->image )) { + if (_vaCreateImage(va_ctx->display, &p_fmt[i], width, height, &va_ctx->image )) { goto error; } } } if (va_ctx->is_supports_derive) { - _vaDestroyImage(va_display, va_ctx->image.image_id); + _vaDestroyImage(va_ctx->display, va_ctx->image.image_id); va_ctx->image.image_id = VA_INVALID_ID; } - // prepare the libav hardware context - struct vaapi_context *hw_context = g_malloc0(sizeof(struct vaapi_context)); - ctx->hwaccel_context = hw_context; - - hw_context->display = va_display; - hw_context->config_id = config_id; - hw_context->context_id = va_ctx->context_id; + g_free(p_fmt); return 0; error: - // TODO: destroy sufaces + g_free(p_fmt); return -1; } -static bool setup(AVCodecContext *ctx, int width, int height) { +static void cleanup(void *opaque) +{ + VAPluginContext *va_ctx = (VAPluginContext *)opaque; + + if (va_ctx->context_id) { + _vaDestroyContext(va_ctx->display, va_ctx->context_id); + va_ctx->context_id = 0; + } + + if (va_ctx->surface_id) { + _vaDestroySurfaces(va_ctx->display, va_ctx->surface_id, va_ctx->surface_count); + va_ctx->surface_id = NULL; + } + + if (va_ctx->config_id) { + _vaDestroyConfig(va_ctx->display, va_ctx->config_id); + va_ctx->config_id = 0; + } + + g_free(va_ctx->surface_id); + g_free(va_ctx->surface_state); + g_free(va_ctx); +} + + +static void *setup(AVCodecContext *ctx, int width, int height) { + VAPluginContext *va_ctx = g_malloc0(sizeof(VAPluginContext)); + va_ctx->display = va_display; + VAProfile profile; int codec_id = ctx->codec_id; @@ -298,7 +348,7 @@ static bool setup(AVCodecContext *ctx, int width, int height) { goto error; } - int num_profiles = _vaMaxNumProfiles(va_display); + int num_profiles = _vaMaxNumProfiles(va_ctx->display); VAProfile *profiles_list = g_malloc0_n(num_profiles, sizeof(VAProfile)); bool is_supported_profile; int i; @@ -307,7 +357,7 @@ static bool setup(AVCodecContext *ctx, int width, int height) { goto error; } - VAStatus status = _vaQueryConfigProfiles(va_display, profiles_list, &num_profiles); + VAStatus status = _vaQueryConfigProfiles(va_ctx->display, profiles_list, &num_profiles); if (status == VA_STATUS_SUCCESS) { for (i = 0; i < num_profiles; ++i) { if (profiles_list[i] == profile) { @@ -323,15 +373,26 @@ static bool setup(AVCodecContext *ctx, int width, int height) { goto error; } - if(create_surfaces(ctx, width, height, profile)) { + + if(create_surfaces(va_ctx, width, height, profile)) { printf("Failed to initialize the VAAPI device\n"); + goto error; } - return true; + // prepare the libav hardware context + struct vaapi_context *hw_context = g_malloc0(sizeof(struct vaapi_context)); + ctx->hwaccel_context = hw_context; + + hw_context->display = va_ctx->display; + hw_context->config_id = va_ctx->config_id; + hw_context->context_id = va_ctx->context_id; + + return va_ctx; error: - // TODO: error handling - return false; + cleanup(va_ctx); + g_free(va_ctx); + return NULL; } static void copy_plane(uint8_t *dst, @@ -366,23 +427,24 @@ static void extract(void* dst, void *src) { AVFrame *frame = (AVFrame *)src; VASurfaceID surface_id = (VASurfaceID)(uintptr_t)frame->data[3]; + VAPluginContext *va_ctx = (VAPluginContext *)((SurfaceState *)frame->opaque)->va_ctx; if (check_version(0, 31)) { - if (((_vaSyncSurface2)_vaSyncSurface)(va_display, surface_id)) { + if (((_vaSyncSurface2)_vaSyncSurface)(va_ctx->display, surface_id)) { return; } } else { - if (((_vaSyncSurface3)_vaSyncSurface)(va_display, va_ctx->context_id, surface_id)) { + if (((_vaSyncSurface3)_vaSyncSurface)(va_ctx->display, va_ctx->context_id, surface_id)) { return; } } if (va_ctx->is_supports_derive) { - if (_vaDeriveImage(va_display, surface_id, &va_ctx->image) != VA_STATUS_SUCCESS) { + if (_vaDeriveImage(va_ctx->display, surface_id, &va_ctx->image) != VA_STATUS_SUCCESS) { return; } } else { - if (_vaGetImage(va_display, surface_id, + if (_vaGetImage(va_ctx->display, surface_id, 0, 0, frame->width, frame->height, va_ctx->image.image_id)) { return; @@ -390,7 +452,7 @@ static void extract(void* dst, void *src) } void *p_base; - if (_vaMapBuffer(va_display, va_ctx->image.buf, &p_base)) { + if (_vaMapBuffer(va_ctx->display, va_ctx->image.buf, &p_base)) { return; } @@ -417,49 +479,54 @@ static void extract(void* dst, void *src) return; } - if (_vaUnmapBuffer(va_display, va_ctx->image.buf)) { + if (_vaUnmapBuffer(va_ctx->display, va_ctx->image.buf)) { return; } if (va_ctx->is_supports_derive) { - _vaDestroyImage(va_display, va_ctx->image.image_id); + _vaDestroyImage(va_ctx->display, va_ctx->image.image_id); va_ctx->image.image_id = VA_INVALID_ID; } return; } -static int get_surface(AVCodecContext *p_context, +static int get_surface(AVCodecContext *ctx, AVFrame *frame) { int i; - for (i = 0; i < SURFACE_COUNT; ++i) { - if (va_ctx->surface_is_occupied[i]) continue; + VAPluginContext *va_ctx = (VAPluginContext *)get_plugin_context(ctx); + + for (i = 0; i < va_ctx->surface_count; ++i) { + if (va_ctx->surface_state[i].is_occupied) { + continue; + } break; } + va_ctx->surface_state[i].is_occupied = true; + frame->data[0] = (void *)(uintptr_t)va_ctx->surface_id[i]; frame->data[3] = frame->data[0]; frame->type = FF_BUFFER_TYPE_USER; - frame->opaque = (void *)&(va_ctx->surface_is_occupied[i]); - // is_occupied = true; - *((bool *)frame->opaque) = true; + + frame->opaque = (void *)&(va_ctx->surface_state[i]); return 0; } -static void release_surface(AVCodecContext *p_context, +static void release_surface(AVCodecContext *ctx, AVFrame *frame) { int i; + for (i = 0; i < 4; ++i) { frame->data[i] = NULL; } - // is_occupied = false; - *((bool *)frame->opaque) = false; + ((SurfaceState *)frame->opaque)->is_occupied = false; } CodecPlugin vaapi_plugin = { @@ -468,6 +535,7 @@ CodecPlugin vaapi_plugin = { .output_pix_fmt = PIX_FMT_YUV420P, .probe = probe, .setup = setup, + .cleanup = cleanup, .get_buffer = get_surface, .release_buffer = release_surface, .get_picture = extract, diff --git a/tizen/src/hw/pci/maru_dxva2_plugin.c b/tizen/src/hw/pci/maru_dxva2_plugin.c index 1edd267989..83b63b0c93 100644 --- a/tizen/src/hw/pci/maru_dxva2_plugin.c +++ b/tizen/src/hw/pci/maru_dxva2_plugin.c @@ -837,11 +837,11 @@ error: return false; } -static bool dxva_setup(AVCodecContext *dec_ctx, int width, int height) +static void *dxva_setup(AVCodecContext *dec_ctx, int width, int height) { if (DxFindVideoServiceConversion(dec_ctx->codec_id)) { ERR("DxFindVideoServiceConversion failed\n"); - return false; + return NULL; } dxva_ctx->thread_count = dec_ctx->thread_count; @@ -851,7 +851,7 @@ static bool dxva_setup(AVCodecContext *dec_ctx, int width, int height) if (DxCreateVideoDecoder(dec_ctx) < -1) { ERR("DxCreateVideoDecoder failed\n"); - return false; + return NULL; } // prepare the libav hardware context @@ -867,7 +867,7 @@ static bool dxva_setup(AVCodecContext *dec_ctx, int width, int height) DxCreateVideoConversion(); - return true; + return dxva_ctx; } static int dxva_get_surface(AVCodecContext *dec_ctx, AVFrame *frame)