brillcodec: introduce plug-in context management 98/27998/3
authorSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 24 Sep 2014 07:30:27 +0000 (16:30 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Thu, 25 Sep 2014 07:15:36 +0000 (16:15 +0900)
Now context management of HWACCEL plugin is enabled.
Fix memory leaks.
Fix device resource leaks.

Change-Id: I2651ba331214ffb48c89f6b826ecc93bcb4d34fb
Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
tizen/src/hw/pci/maru_brillcodec.c
tizen/src/hw/pci/maru_brillcodec.h
tizen/src/hw/pci/maru_brillcodec_plugin.h
tizen/src/hw/pci/maru_brillcodec_vaapi.c
tizen/src/hw/pci/maru_dxva2_plugin.c

index a10238d..f4784cb 100644 (file)
@@ -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;
+}
index 1304447..53b3681 100644 (file)
@@ -68,6 +68,7 @@ typedef struct CodecContext {
     bool                    requested_close;
 
     bool                    is_hwaccel;
+    void                    *plugin_context;
 } CodecContext;
 
 typedef struct CodecThreadPool {
index cfbf52d..cc3a485 100644 (file)
 
 #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);
index 45a6118..b3b7bbb 100644 (file)
 
 #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,
index 1edd267..83b63b0 100644 (file)
@@ -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)