Extend run_ffprobe to allow arguments and capture of stdout.
authorCarl Hetherington <cth@carlh.net>
Thu, 24 Aug 2023 13:43:06 +0000 (15:43 +0200)
committerCarl Hetherington <cth@carlh.net>
Sat, 26 Aug 2023 08:23:21 +0000 (10:23 +0200)
src/lib/cross.h
src/lib/cross_linux.cc
src/lib/cross_osx.cc
src/lib/cross_windows.cc

index 4281700a77dbd63be719d17612a87aaf194ff552..6904811b756bd7299c57c96bbdad45baac079761 100644 (file)
@@ -44,7 +44,7 @@ struct AVIOContext;
 extern void dcpomatic_sleep_seconds (int);
 extern void dcpomatic_sleep_milliseconds (int);
 extern std::string cpu_info ();
-extern void run_ffprobe (boost::filesystem::path, boost::filesystem::path);
+extern void run_ffprobe(boost::filesystem::path content, boost::filesystem::path out, bool err = true, std::string args = {});
 extern std::list<std::pair<std::string, std::string>> mount_info ();
 extern boost::filesystem::path openssl_path ();
 extern void make_foreground_application ();
index 919927fdacddd53cf14b7e05c79d9052718b5a76..0a12d7ccadc42e28f0edda0fed7fe13282d03e7e 100644 (file)
@@ -99,9 +99,10 @@ libdcp_resources_path ()
 
 
 void
-run_ffprobe (boost::filesystem::path content, boost::filesystem::path out)
+run_ffprobe(boost::filesystem::path content, boost::filesystem::path out, bool err, string args)
 {
-       string ffprobe = "ffprobe \"" + content.string() + "\" 2> \"" + out.string() + "\"";
+       string const redirect = err ? "2>" : ">";
+       auto const ffprobe = String::compose("ffprobe %1 \"%2\" %3 \"%4\"", args.empty() ? " " : args, content.string(), redirect, out.string());
        LOG_GENERAL (N_("Probing with %1"), ffprobe);
        int const r = system (ffprobe.c_str());
        if (r == -1 || (WIFEXITED(r) && WEXITSTATUS(r) != 0)) {
index 3b04f1011d40bd1daed90ac1a26c041ef833a7d4..0f25732f2aa3e667050998f94e4cfc07f578542d 100644 (file)
@@ -103,13 +103,18 @@ libdcp_resources_path ()
 
 
 void
-run_ffprobe (boost::filesystem::path content, boost::filesystem::path out)
+run_ffprobe(boost::filesystem::path content, boost::filesystem::path out, bool err, string args)
 {
        auto path = directory_containing_executable () / "ffprobe";
+       if (!boost::filesystem::exists(path)) {
+               /* This is a hack but we need ffprobe during tests */
+               path = "/Users/ci/workspace/bin/ffprobe";
+       }
+       string const redirect = err ? "2>" : ">";
 
-       string ffprobe = "\"" + path.string() + "\" \"" + content.string() + "\" 2> \"" + out.string() + "\"";
+       auto const ffprobe = String::compose("\"%1\" %2 \"%3\" %4 \"%5\"", path, args.empty() ? " " : args, content.string(), redirect, out.string());
        LOG_GENERAL (N_("Probing with %1"), ffprobe);
-       system (ffprobe.c_str ());
+       system (ffprobe.c_str());
 }
 
 
index 200b724854731b2582110f752d45abf87921831b..9480f77545fbaa5f8f3e2165b5a3164a5045a89a 100644 (file)
@@ -125,37 +125,51 @@ cpu_info ()
 
 
 void
-run_ffprobe (boost::filesystem::path content, boost::filesystem::path out)
+run_ffprobe(boost::filesystem::path content, boost::filesystem::path out, bool err, string args)
 {
        SECURITY_ATTRIBUTES security;
        security.nLength = sizeof (security);
        security.bInheritHandle = TRUE;
        security.lpSecurityDescriptor = 0;
 
-       HANDLE child_stderr_read;
-       HANDLE child_stderr_write;
-       if (!CreatePipe (&child_stderr_read, &child_stderr_write, &security, 0)) {
+       HANDLE child_out_read;
+       HANDLE child_out_write;
+       if (!CreatePipe(&child_out_read, &child_out_write, &security, 0)) {
                LOG_ERROR_NC ("ffprobe call failed (could not CreatePipe)");
                return;
        }
 
+       if (!SetHandleInformation(child_out_read, HANDLE_FLAG_INHERIT, 0)) {
+               LOG_ERROR_NC("ffprobe call failed (could not SetHandleInformation)");
+               return;
+       }
+
        wchar_t dir[512];
        MultiByteToWideChar (CP_UTF8, 0, directory_containing_executable().string().c_str(), -1, dir, sizeof(dir));
 
        STARTUPINFO startup_info;
        ZeroMemory (&startup_info, sizeof (startup_info));
        startup_info.cb = sizeof (startup_info);
-       startup_info.hStdError = child_stderr_write;
+       if (err) {
+               startup_info.hStdError = child_out_write;
+       } else {
+               startup_info.hStdOutput = child_out_write;
+       }
        startup_info.dwFlags |= STARTF_USESTDHANDLES;
 
        wchar_t command[512];
-       wcscpy (command, L"ffprobe.exe \"");
+       wcscpy(command, L"ffprobe.exe ");
+
+       wchar_t tmp[512];
+       MultiByteToWideChar(CP_UTF8, 0, args.c_str(), -1, tmp, sizeof(tmp));
+       wcscat(command, tmp);
+
+       wcscat(command, L" \"");
 
-       wchar_t file[512];
-       MultiByteToWideChar (CP_UTF8, 0, content.string().c_str(), -1, file, sizeof(file));
-       wcscat (command, file);
+       MultiByteToWideChar(CP_UTF8, 0, boost::filesystem::canonical(content).make_preferred().string().c_str(), -1, tmp, sizeof(tmp));
+       wcscat(command, tmp);
 
-       wcscat (command, L"\"");
+       wcscat(command, L"\"");
 
        PROCESS_INFORMATION process_info;
        ZeroMemory (&process_info, sizeof (process_info));
@@ -170,12 +184,12 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out)
                return;
        }
 
-       CloseHandle (child_stderr_write);
+       CloseHandle(child_out_write);
 
        while (true) {
                char buffer[512];
                DWORD read;
-               if (!ReadFile(child_stderr_read, buffer, sizeof(buffer), &read, 0) || read == 0) {
+               if (!ReadFile(child_out_read, buffer, sizeof(buffer), &read, 0) || read == 0) {
                        break;
                }
                o.write(buffer, read, 1);
@@ -186,7 +200,7 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out)
        WaitForSingleObject (process_info.hProcess, INFINITE);
        CloseHandle (process_info.hProcess);
        CloseHandle (process_info.hThread);
-       CloseHandle (child_stderr_read);
+       CloseHandle(child_out_read);
 }