OSDN Git Service

Add va_MessagingInit().
[android-x86/hardware-intel-common-libva.git] / va / va.c
diff --git a/va/va.c b/va/va.c
index 851a41f..0a129a9 100644 (file)
--- a/va/va.c
+++ b/va/va.c
 #include <string.h>
 #include <dlfcn.h>
 #include <unistd.h>
+#ifdef ANDROID
+#include <cutils/log.h>
+/* support versions < JellyBean */
+#ifndef ALOGE
+#define ALOGE LOGE
+#endif
+#ifndef ALOGI
+#define ALOGI LOGI
+#endif
+#endif
 
 #define DRIVER_EXTENSION       "_drv_video.so"
 
@@ -50,7 +60,7 @@
 
 /*
  * read a config "env" for libva.conf or from environment setting
- * liva.conf has higher priority
+ * libva.conf has higher priority
  * return 0: the "env" is set, and the value is copied into env_value
  *        1: the env is not set
  */
@@ -65,17 +75,19 @@ int va_parseConfig(char *env, char *env_value)
     
     fp = fopen("/etc/libva.conf", "r");
     while (fp && (fgets(oneline, 1024, fp) != NULL)) {
-       if (strlen(oneline) == 1)
-           continue;
+        if (strlen(oneline) == 1)
+            continue;
         token = strtok_r(oneline, "=\n", &saveptr);
-       value = strtok_r(NULL, "=\n", &saveptr);
+        value = strtok_r(NULL, "=\n", &saveptr);
 
-       if (NULL == token || NULL == value)
-           continue;
+        if (NULL == token || NULL == value)
+            continue;
 
         if (strcmp(token, env) == 0) {
-            if (env_value)
+            if (env_value) {
                 strncpy(env_value,value, 1024);
+                env_value[1023] = '\0';
+            }
 
             fclose(fp);
 
@@ -88,8 +100,10 @@ int va_parseConfig(char *env, char *env_value)
     /* no setting in config file, use env setting */
     value = getenv(env);
     if (value) {
-        if (env_value)
+        if (env_value) {
             strncpy(env_value, value, 1024);
+            env_value[1023] = '\0';
+        }
         return 0;
     }
     
@@ -102,12 +116,77 @@ int vaDisplayIsValid(VADisplay dpy)
     return pDisplayContext && (pDisplayContext->vadpy_magic == VA_DISPLAY_MAGIC) && pDisplayContext->vaIsValid(pDisplayContext);
 }
 
+static void default_log_error(const char *buffer)
+{
+# ifdef ANDROID
+    ALOGE("%s", buffer);
+# else
+    fprintf(stderr, "libva error: %s", buffer);
+# endif
+}
+
+static void default_log_info(const char *buffer)
+{
+# ifdef ANDROID
+    ALOGI("%s", buffer);
+# else
+    fprintf(stderr, "libva info: %s", buffer);
+# endif
+}
+
+static vaMessageCallback va_log_error = default_log_error;
+static vaMessageCallback va_log_info = default_log_info;
+
+/**
+ * Set the callback for error messages, or NULL for no logging.
+ * Returns the previous one, or NULL if it was disabled.
+ */
+vaMessageCallback vaSetErrorCallback(vaMessageCallback callback)
+{
+    vaMessageCallback old_callback = va_log_error;
+    va_log_error = callback;
+    return old_callback;
+}
+
+/**
+ * Set the callback for info messages, or NULL for no logging.
+ * Returns the previous one, or NULL if it was disabled.
+ */
+vaMessageCallback vaSetInfoCallback(vaMessageCallback callback)
+{
+    vaMessageCallback old_callback = va_log_info;
+    va_log_info = callback;
+    return old_callback;
+}
+
+void va_MessagingInit()
+{
+#if ENABLE_VA_MESSAGING
+    char env_value[1024];
+
+    if (va_parseConfig("LIBVA_MESSAGING_LEVEL", &env_value[0]) == 0) {
+        if (strcmp(env_value, "0") == 0) {
+            vaSetInfoCallback(NULL);
+            vaSetErrorCallback(NULL);
+        }
+
+        if (strcmp(env_value, "1") == 0) {
+            vaSetInfoCallback(NULL);
+        }
+    }
+#endif
+}
+
 void va_errorMessage(const char *msg, ...)
 {
+#if ENABLE_VA_MESSAGING
     char buf[512], *dynbuf;
     va_list args;
     int n, len;
 
+    if (va_log_error == NULL)
+        return;
+
     va_start(args, msg);
     len = vsnprintf(buf, sizeof(buf), msg, args);
     va_end(args);
@@ -125,14 +204,19 @@ void va_errorMessage(const char *msg, ...)
     }
     else if (len > 0)
         va_log_error(buf);
+#endif
 }
 
 void va_infoMessage(const char *msg, ...)
 {
+#if ENABLE_VA_MESSAGING
     char buf[512], *dynbuf;
     va_list args;
     int n, len;
 
+    if (va_log_info == NULL)
+        return;
+
     va_start(args, msg);
     len = vsnprintf(buf, sizeof(buf), msg, args);
     va_end(args);
@@ -150,6 +234,7 @@ void va_infoMessage(const char *msg, ...)
     }
     else if (len > 0)
         va_log_info(buf);
+#endif
 }
 
 static bool va_checkVtable(void *ptr, char *function)
@@ -217,6 +302,7 @@ static VAStatus va_openDriver(VADisplay dpy, char *driver_name)
         if (!driver_path) {
             va_errorMessage("%s L%d Out of memory!n",
                                 __FUNCTION__, __LINE__);
+            free(search_path);    
             return VA_STATUS_ERROR_ALLOCATION_FAILED;
         }
 
@@ -245,6 +331,12 @@ static VAStatus va_openDriver(VADisplay dpy, char *driver_name)
                 int minor;
             } compatible_versions[] = {
                 { VA_MAJOR_VERSION, VA_MINOR_VERSION },
+                { 0, 39 },
+                { 0, 38 },
+                { 0, 37 },
+                { 0, 36 },
+                { 0, 35 },
+                { 0, 34 },
                 { 0, 33 },
                 { 0, 32 },
                 { -1, }
@@ -436,7 +528,68 @@ const char *vaErrorStr(VAStatus error_status)
     }
     return "unknown libva error / description missing";
 }
-      
+
+const static char *prefer_driver_list[4] = {
+    "i965",
+    "hybrid",
+    "pvr",
+    "iHD",
+};
+
+VAStatus vaSetDriverName(
+    VADisplay dpy,
+    char *driver_name
+)
+{
+    VADriverContextP ctx;
+    VAStatus vaStatus = VA_STATUS_SUCCESS;
+    char *override_driver_name = NULL;
+    int i, found;
+    ctx = CTX(dpy);
+
+    if (geteuid() != getuid()) {
+        vaStatus = VA_STATUS_ERROR_OPERATION_FAILED;
+        va_errorMessage("no permission to vaSetDriverName\n");
+        return vaStatus;
+    }
+
+    if (strlen(driver_name) == 0 || strlen(driver_name) >=256) {
+        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
+        va_errorMessage("vaSetDriverName returns %s\n",
+                         vaErrorStr(vaStatus));
+        return vaStatus;
+    }
+
+    found = 0;
+    for (i = 0; i < sizeof(prefer_driver_list) / sizeof(char *); i++) {
+        if (strlen(prefer_driver_list[i]) != strlen(driver_name))
+            continue;
+        if (!strncmp(prefer_driver_list[i], driver_name, strlen(driver_name))) {
+            found = 1;
+            break;
+        }
+    }
+
+    if (!found) {
+        vaStatus = VA_STATUS_ERROR_INVALID_PARAMETER;
+        va_errorMessage("vaSetDriverName returns %s. Incorrect parameter\n",
+                         vaErrorStr(vaStatus));
+        return vaStatus;
+    }
+
+    override_driver_name = strdup(driver_name);
+
+    if (!override_driver_name) {
+        vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
+        va_errorMessage("vaSetDriverName returns %s. Out of Memory\n",
+                         vaErrorStr(vaStatus));
+        return vaStatus;
+    }
+
+    ctx->override_driver_name = override_driver_name;
+    return VA_STATUS_SUCCESS;
+}
+
 VAStatus vaInitialize (
     VADisplay dpy,
     int *major_version,         /* out */
@@ -446,21 +599,41 @@ VAStatus vaInitialize (
     const char *driver_name_env = NULL;
     char *driver_name = NULL;
     VAStatus vaStatus;
+    VADriverContextP ctx;
 
     CHECK_DISPLAY(dpy);
 
+    ctx = CTX(dpy);
+
     va_TraceInit(dpy);
 
     va_FoolInit(dpy);
 
+    va_MessagingInit();
+
     va_infoMessage("VA-API version %s\n", VA_VERSION_S);
 
     vaStatus = va_getDriverName(dpy, &driver_name);
-    va_infoMessage("va_getDriverName() returns %d\n", vaStatus);
 
-    driver_name_env = getenv("LIBVA_DRIVER_NAME");
-    if ((VA_STATUS_SUCCESS == vaStatus) &&
-        driver_name_env && (geteuid() == getuid())) {
+    if (!ctx->override_driver_name) {
+        va_infoMessage("va_getDriverName() returns %d\n", vaStatus);
+
+        driver_name_env = getenv("LIBVA_DRIVER_NAME");
+    } else if (vaStatus == VA_STATUS_SUCCESS) {
+        if (driver_name)
+            free(driver_name);
+
+        driver_name = strdup(ctx->override_driver_name);
+        if (!driver_name) {
+            vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
+            va_errorMessage("vaInitialize() failed with %s, out of memory\n",
+                        vaErrorStr(vaStatus));
+            return vaStatus;
+        }
+        va_infoMessage("User requested driver '%s'\n", driver_name);
+    }
+
+    if (driver_name_env && (geteuid() == getuid())) {
         /* Don't allow setuid apps to use LIBVA_DRIVER_NAME */
         if (driver_name) /* memory is allocated in va_getDriverName */
             free(driver_name);
@@ -513,8 +686,10 @@ VAStatus vaTerminate (
   free(old_ctx->vtable_vpp);
   old_ctx->vtable_vpp = NULL;
 
-  if (VA_STATUS_SUCCESS == vaStatus)
-      pDisplayContext->vaDestroy(pDisplayContext);
+  if (old_ctx->override_driver_name) {
+      free(old_ctx->override_driver_name);
+      old_ctx->override_driver_name = NULL;
+  }
 
   VA_TRACE_LOG(va_TraceTerminate, dpy);
 
@@ -522,6 +697,9 @@ VAStatus vaTerminate (
 
   va_FoolEnd(dpy);
 
+  if (VA_STATUS_SUCCESS == vaStatus)
+      pDisplayContext->vaDestroy(pDisplayContext);
+
   return vaStatus;
 }
 
@@ -631,7 +809,6 @@ VAStatus vaCreateConfig (
 {
   VADriverContextP ctx;
   VAStatus vaStatus = VA_STATUS_SUCCESS;
-  int ret = 0;
   
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
@@ -639,7 +816,7 @@ VAStatus vaCreateConfig (
   vaStatus = ctx->vtable->vaCreateConfig ( ctx, profile, entrypoint, attrib_list, num_attribs, config_id );
 
   /* record the current entrypoint for further trace/fool determination */
-  VA_TRACE_LOG(va_TraceCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
+  VA_TRACE_ALL(va_TraceCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
   VA_FOOL_FUNC(va_FoolCreateConfig, dpy, profile, entrypoint, attrib_list, num_attribs, config_id);
   
   return vaStatus;
@@ -651,10 +828,16 @@ VAStatus vaDestroyConfig (
 )
 {
   VADriverContextP ctx;
+  VAStatus vaStatus = VA_STATUS_SUCCESS;
+
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
 
-  return ctx->vtable->vaDestroyConfig ( ctx, config_id );
+  vaStatus = ctx->vtable->vaDestroyConfig ( ctx, config_id );
+
+  VA_TRACE_ALL(va_TraceDestroyConfig, dpy, config_id);
+
+  return vaStatus;
 }
 
 VAStatus vaQueryConfigAttributes (
@@ -826,11 +1009,14 @@ vaQuerySurfaceAttributes(
         return VA_STATUS_ERROR_INVALID_DISPLAY;
 
     if (!ctx->vtable->vaQuerySurfaceAttributes)
-        return va_impl_query_surface_attributes(ctx, config,
-            attrib_list, num_attribs);
+        vaStatus = va_impl_query_surface_attributes(ctx, config,
+                                                    attrib_list, num_attribs);
+    else
+        vaStatus = ctx->vtable->vaQuerySurfaceAttributes(ctx, config,
+                                                         attrib_list, num_attribs);
+
+    VA_TRACE_LOG(va_TraceQuerySurfaceAttributes, dpy, config, attrib_list, num_attribs);
 
-    vaStatus = ctx->vtable->vaQuerySurfaceAttributes(ctx, config,
-        attrib_list, num_attribs);
     return vaStatus;
 }
 
@@ -855,16 +1041,14 @@ vaCreateSurfaces(
         return VA_STATUS_ERROR_INVALID_DISPLAY;
 
     if (ctx->vtable->vaCreateSurfaces2)
-        return ctx->vtable->vaCreateSurfaces2(ctx, format, width, height,
+        vaStatus = ctx->vtable->vaCreateSurfaces2(ctx, format, width, height,
                                               surfaces, num_surfaces,
                                               attrib_list, num_attribs);
-
-    if (attrib_list && num_attribs > 0)
-        return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
-
-    vaStatus = ctx->vtable->vaCreateSurfaces(ctx, width, height, format,
-                                             num_surfaces, surfaces);
-
+    else if (attrib_list && num_attribs > 0)
+        vaStatus = VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
+    else
+        vaStatus = ctx->vtable->vaCreateSurfaces(ctx, width, height, format,
+                                                 num_surfaces, surfaces);
     VA_TRACE_LOG(va_TraceCreateSurfaces,
                  dpy, width, height, format, num_surfaces, surfaces,
                  attrib_list, num_attribs);
@@ -880,10 +1064,17 @@ VAStatus vaDestroySurfaces (
 )
 {
   VADriverContextP ctx;
+  VAStatus vaStatus;
+  
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
 
-  return ctx->vtable->vaDestroySurfaces( ctx, surface_list, num_surfaces );
+  VA_TRACE_LOG(va_TraceDestroySurfaces,
+               dpy, surface_list, num_surfaces);
+  
+  vaStatus = ctx->vtable->vaDestroySurfaces( ctx, surface_list, num_surfaces );
+  
+  return vaStatus;
 }
 
 VAStatus vaCreateContext (
@@ -907,7 +1098,7 @@ VAStatus vaCreateContext (
                                       flag, render_targets, num_render_targets, context );
 
   /* keep current encode/decode resoluton */
-  VA_TRACE_LOG(va_TraceCreateContext, dpy, config_id, picture_width, picture_height, flag, render_targets, num_render_targets, context);
+  VA_TRACE_ALL(va_TraceCreateContext, dpy, config_id, picture_width, picture_height, flag, render_targets, num_render_targets, context);
 
   return vaStatus;
 }
@@ -918,10 +1109,16 @@ VAStatus vaDestroyContext (
 )
 {
   VADriverContextP ctx;
+  VAStatus vaStatus;
+
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
 
-  return ctx->vtable->vaDestroyContext( ctx, context );
+  vaStatus = ctx->vtable->vaDestroyContext( ctx, context );
+
+  VA_TRACE_ALL(va_TraceDestroyContext, dpy, context);
+
+  return vaStatus;
 }
 
 VAStatus vaCreateBuffer (
@@ -936,14 +1133,11 @@ VAStatus vaCreateBuffer (
 {
   VADriverContextP ctx;
   VAStatus vaStatus;
-  int ret = 0;
   
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
 
   VA_FOOL_FUNC(va_FoolCreateBuffer, dpy, context, type, size, num_elements, data, buf_id);
-  if (ret)
-      return VA_STATUS_SUCCESS;
 
   vaStatus = ctx->vtable->vaCreateBuffer( ctx, context, type, size, num_elements, data, buf_id);
 
@@ -962,8 +1156,8 @@ VAStatus vaBufferSetNumElements (
   VADriverContextP ctx;
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
-  
-  VA_FOOL_RETURN();
+
+  VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   
   return ctx->vtable->vaBufferSetNumElements( ctx, buf_id, num_elements );
 }
@@ -977,18 +1171,15 @@ VAStatus vaMapBuffer (
 {
   VADriverContextP ctx;
   VAStatus va_status;
-  int ret = 0;
   
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
-
+  
   VA_FOOL_FUNC(va_FoolMapBuffer, dpy, buf_id, pbuf);
-  if (ret)
-      return VA_STATUS_SUCCESS;
   
   va_status = ctx->vtable->vaMapBuffer( ctx, buf_id, pbuf );
 
-  VA_TRACE_LOG(va_TraceMapBuffer, dpy, buf_id, pbuf);
+  VA_TRACE_ALL(va_TraceMapBuffer, dpy, buf_id, pbuf);
   
   return va_status;
 }
@@ -1001,11 +1192,8 @@ VAStatus vaUnmapBuffer (
   VADriverContextP ctx;
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
-  int ret = 0;
 
-  VA_FOOL_FUNC(va_FoolUnmapBuffer, dpy, buf_id);
-  if (ret)
-      return VA_STATUS_SUCCESS;
+  VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
 
   return ctx->vtable->vaUnmapBuffer( ctx, buf_id );
 }
@@ -1019,7 +1207,7 @@ VAStatus vaDestroyBuffer (
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
 
-  VA_FOOL_RETURN();
+  VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
 
   VA_TRACE_LOG(va_TraceDestroyBuffer,
                dpy, buffer_id);
@@ -1037,18 +1225,43 @@ VAStatus vaBufferInfo (
 )
 {
   VADriverContextP ctx;
-  int ret = 0;
   
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
 
   VA_FOOL_FUNC(va_FoolBufferInfo, dpy, buf_id, type, size, num_elements);
-  if (ret)
-      return VA_STATUS_SUCCESS;
   
   return ctx->vtable->vaBufferInfo( ctx, buf_id, type, size, num_elements );
 }
 
+/* Locks buffer for external API usage */
+VAStatus
+vaAcquireBufferHandle(VADisplay dpy, VABufferID buf_id, VABufferInfo *buf_info)
+{
+    VADriverContextP ctx;
+
+    CHECK_DISPLAY(dpy);
+    ctx = CTX(dpy);
+
+    if (!ctx->vtable->vaAcquireBufferHandle)
+        return VA_STATUS_ERROR_UNIMPLEMENTED;
+    return ctx->vtable->vaAcquireBufferHandle(ctx, buf_id, buf_info);
+}
+
+/* Unlocks buffer after usage from external API */
+VAStatus
+vaReleaseBufferHandle(VADisplay dpy, VABufferID buf_id)
+{
+    VADriverContextP ctx;
+
+    CHECK_DISPLAY(dpy);
+    ctx = CTX(dpy);
+
+    if (!ctx->vtable->vaReleaseBufferHandle)
+        return VA_STATUS_ERROR_UNIMPLEMENTED;
+    return ctx->vtable->vaReleaseBufferHandle(ctx, buf_id);
+}
+
 VAStatus vaBeginPicture (
     VADisplay dpy,
     VAContextID context,
@@ -1061,8 +1274,8 @@ VAStatus vaBeginPicture (
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
 
-  VA_TRACE_LOG(va_TraceBeginPicture, dpy, context, render_target);
-  VA_FOOL_RETURN();
+  VA_TRACE_ALL(va_TraceBeginPicture, dpy, context, render_target);
+  VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
   
   va_status = ctx->vtable->vaBeginPicture( ctx, context, render_target );
   
@@ -1082,7 +1295,7 @@ VAStatus vaRenderPicture (
   ctx = CTX(dpy);
 
   VA_TRACE_LOG(va_TraceRenderPicture, dpy, context, buffers, num_buffers);
-  VA_FOOL_RETURN();
+  VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
 
   return ctx->vtable->vaRenderPicture( ctx, context, buffers, num_buffers );
 }
@@ -1098,11 +1311,12 @@ VAStatus vaEndPicture (
   CHECK_DISPLAY(dpy);
   ctx = CTX(dpy);
 
-  if (fool_codec == 0)
-      va_status = ctx->vtable->vaEndPicture( ctx, context );
+  VA_FOOL_FUNC(va_FoolCheckContinuity, dpy);
+
+  va_status = ctx->vtable->vaEndPicture( ctx, context );
 
   /* dump surface content */
-  VA_TRACE_SURFACE(va_TraceEndPicture, dpy, context, 1);
+  VA_TRACE_ALL(va_TraceEndPicture, dpy, context, 1);
 
   return va_status;
 }