2 proposal of enhancement for multilib exe/dll

Issue #156 closed
Ma0 created an issue

Now there is possible to make one big multilib DLL, but x265.exe can't handle such DLL. So the first proposition:

*** api.cpp.org Wed Jul  8 02:31:02 2015
--- api.cpp Wed Jul  8 22:06:25 2015
***************
*** 366,376 ****

  #if _WIN32
          HMODULE h = LoadLibraryA(libname);
          if (h)
          {
              api_get_func get = (api_get_func)GetProcAddress(h, method);
              if (get)
!                 api = get(0);
          }
  #else
          void* h = dlopen(libname, RTLD_LAZY | RTLD_LOCAL);
--- 366,381 ----

  #if _WIN32
          HMODULE h = LoadLibraryA(libname);
+         if (h == NULL)
+         {
+             libname = "libx265" ext;
+             h = LoadLibraryA(libname);
+         }
          if (h)
          {
              api_get_func get = (api_get_func)GetProcAddress(h, method);
              if (get)
!                 api = get(bitDepth);
          }
  #else
          void* h = dlopen(libname, RTLD_LAZY | RTLD_LOCAL);
***************
*** 437,442 ****
--- 442,452 ----

  #if _WIN32
          HMODULE h = LoadLibraryA(libname);
+         if (h == NULL)
+         {
+             libname = "libx265" ext;
+             h = LoadLibraryA(libname);
+         }
          if (h)
          {
              e = X265_API_QUERY_ERR_FUNC_NOT_FOUND; 

If the attempt to load "libx265_mainX.dll" fails, we can try with "libx265.dll" + specify exactly bit-depth what we want: api = get(bitDepth);

Second proposal: if we use multilib EXE we have default 8-bit encoding, but we can use 10-bit EXE + multilib DLL and we have default 10-bit encoding. So there are options sets that are valid for one model and wrong for another (and with this both cases we can encode with any bit depth). My proposition is to try to switch to required bit-depth if the user set --profile|-P option:

*** x265.cpp.org    Wed Jul  8 02:33:24 2015
--- x265.cpp    Wed Jul  8 02:50:01 2015
***************
*** 376,381 ****
--- 376,398 ----
              tune = optarg;
          else if (c == 'D')
              outputBitDepth = atoi(optarg);
+         else if (c == 'P')
+         {
+             profile = optarg;
+             if (!outputBitDepth)
+             {
+                 if (!strcmp(profile, "main") || !strcmp(profile, "mainstillpicture") || !strcmp(profile, "msp") ||
+                     !strcmp(profile, "main444-8") || !strcmp(profile, "main-intra") ||
+                     !strcmp(profile, "main444-intra") || !strcmp(profile, "main444-stillpicture"))
+                     outputBitDepth = 8;
+                 else if (!strcmp(profile, "main10") || !strcmp(profile, "main422-10") || !strcmp(profile, "main444-10") ||
+                     !strcmp(profile, "main10-intra") || !strcmp(profile, "main422-10-intra") || !strcmp(profile, "main444-10-intra"))
+                     outputBitDepth = 10;
+                 else if (!strcmp(profile, "main12") || !strcmp(profile, "main422-12") || !strcmp(profile, "main444-12") ||
+                     !strcmp(profile, "main12-intra") || !strcmp(profile, "main422-12-intra") || !strcmp(profile, "main444-12-intra"))
+                     outputBitDepth = 12;
+             }
+         }
          else if (c == '?')
              bShowHelp = true;
      }
***************
*** 471,477 ****
              OPT("dither") this->bDither = true;
              OPT("recon-depth") reconFileBitDepth = (uint32_t)x265_atoi(optarg, bError);
              OPT("y4m") this->bForceY4m = true;
!             OPT("profile") profile = optarg; /* handled last */
              OPT("preset") /* handled above */;
              OPT("tune")   /* handled above */;
              OPT("output-depth")   /* handled above */;
--- 488,494 ----
              OPT("dither") this->bDither = true;
              OPT("recon-depth") reconFileBitDepth = (uint32_t)x265_atoi(optarg, bError);
              OPT("y4m") this->bForceY4m = true;
!             OPT("profile") /* handled above */;
              OPT("preset") /* handled above */;
              OPT("tune")   /* handled above */;
              OPT("output-depth")   /* handled above */; 

Comments (6)

  1. Steve Borho

    I'm not sure I see the point of supporting multilib DLLs when you can just as easily make a multilib executable (an x265.exe that supports all bit depths). On Windows the EXE must statically link to libx265 so at least one bit depth of libx265 is being linked into the EXE. Why not link them all?

    we had a discussion about using --profile to select the bit depth but in the end decided to add an explicit -D|--output-depth argument. This was thought to be more consistent with the way x265 is used by ffmpeg, and has the least surprise.

  2. Deepthi Nandakumar

    api: fallback to multilib library if profile-named library not found (refs #156)

    If you call x265_api_get(10) and libx265_main10.dll is not found, it will now fallback to trying to bind libx265.dll and request bitDepth 10 from that library (in the hope that it is a multilib library supporting all bit depths)

    → <<cset 13b2356290d6>>

  3. Ma0 reporter

    Unfortunately x265_api_query and x265_api_get are wrong. Consider libx265.dll with only 8-bit encoder inside and x265.exe with only 8-bit encoder inside. Command x265 -D10 -V hangs x265.

    My solution:

    diff -r 996ebce8c874 source/encoder/api.cpp
    --- a/source/encoder/api.cpp    Mon Aug 17 10:52:15 2015 +0530
    +++ b/source/encoder/api.cpp    Mon Aug 17 19:56:17 2015 +0200
    @@ -365,36 +365,43 @@
                 return NULL;
    
             const x265_api* api = NULL;
    -        int reqDepth = 0;
    +        static int Recursion;
    +
    +        if (Recursion)
    +            return NULL;
    +
    +        Recursion = 1;
    
     #if _WIN32
             HMODULE h = LoadLibraryA(libname);
             if (!h)
             {
    -            h = LoadLibraryA(multilibname);
    -            reqDepth = bitDepth;
    +            libname = multilibname;
    +            h = LoadLibraryA(libname);
             }
             if (h)
             {
                 api_get_func get = (api_get_func)GetProcAddress(h, method);
                 if (get)
    -                api = get(reqDepth);
    +                api = get(bitDepth);
             }
     #else
             void* h = dlopen(libname, RTLD_LAZY | RTLD_LOCAL);
             if (!h)
             {
    -            h = dlopen(multilibname, RTLD_LAZY | RTLD_LOCAL);
    -            reqDepth = bitDepth;
    +            libname = multilibname;
    +            h = dlopen(libname, RTLD_LAZY | RTLD_LOCAL);
             }
             if (h)
             {
                 api_get_func get = (api_get_func)dlsym(h, method);
                 if (get)
    -                api = get(reqDepth);
    +                api = get(bitDepth);
             }
     #endif
    
    +        Recursion = 0;
    +
             if (api && bitDepth != api->bit_depth)
             {
                 x265_log(NULL, X265_LOG_WARNING, "%s does not support requested bitDepth %d\n", libname, bitDepth);
    @@ -447,39 +454,49 @@
             }
    
             const x265_api* api = NULL;
    -        int reqDepth = 0;
             int e = X265_API_QUERY_ERR_LIB_NOT_FOUND;
    +        static int Recursion;
    +
    +        if (Recursion)
    +        {
    +            if (err) *err = X265_API_QUERY_ERR_WRONG_BITDEPTH;
    +            return NULL;
    +        }
    +
    +        Recursion = 1;
    
     #if _WIN32
             HMODULE h = LoadLibraryA(libname);
             if (!h)
             {
    -            h = LoadLibraryA(multilibname);
    -            reqDepth = bitDepth;
    +            libname = multilibname;
    +            h = LoadLibraryA(libname);
             }
             if (h)
             {
                 e = X265_API_QUERY_ERR_FUNC_NOT_FOUND;
                 api_query_func query = (api_query_func)GetProcAddress(h, method);
                 if (query)
    -                api = query(reqDepth, apiVersion, err);
    +                api = query(bitDepth, apiVersion, err);
             }
     #else
             void* h = dlopen(libname, RTLD_LAZY | RTLD_LOCAL);
             if (!h)
             {
    -            h = dlopen(multilibname, RTLD_LAZY | RTLD_LOCAL);
    -            reqDepth = bitDepth;
    +            libname = multilibname;
    +            h = dlopen(libname, RTLD_LAZY | RTLD_LOCAL);
             }
             if (h)
             {
                 e = X265_API_QUERY_ERR_FUNC_NOT_FOUND;
                 api_query_func query = (api_query_func)dlsym(h, method);
                 if (query)
    -                api = query(reqDepth, apiVersion, err);
    +                api = query(bitDepth, apiVersion, err);
             }
     #endif
    
    +        Recursion = 0;
    +
             if (api && bitDepth != api->bit_depth)
             {
                 x265_log(NULL, X265_LOG_WARNING, "%s does not support requested bitDepth %d\n", libname, bitDepth);
    
  4. Deepthi Nandakumar

    api: prevent recursion in libx265.dll fallback (refs #156)

    If libx265.dll did not contain a requested bitdepth, it would result in infinite recursion. So we use a global int to break the recursion

    → <<cset b99b4940c063>>

  5. Log in to comment