1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
media / base / win / media_foundation_package_locator_helper.cc [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/base/win/media_foundation_package_locator_helper.h"
#include <windows.h>
#include <appmodel.h>
#include "base/logging.h"
namespace media {
std::vector<base::FilePath> MediaFoundationPackageInstallPaths(
const std::vector<std::wstring_view>& package_family_names,
std::wstring_view decoder_lib_name,
MediaFoundationCodecPackage codec_package) {
std::vector<base::FilePath> package_paths; // Collected paths to return.
for (const auto& package_family_name : package_family_names) {
// Loop for each package family name.
DVLOG(2) << __func__ << ": Use package_family_name=" << package_family_name;
uint32_t package_count = 0;
uint32_t buffer_size = 0;
long rc =
GetPackagesByPackageFamily(package_family_name.data(), &package_count,
nullptr, &buffer_size, nullptr);
if ((rc != ERROR_SUCCESS && rc != ERROR_INSUFFICIENT_BUFFER) ||
package_count == 0) {
DVLOG(2) << package_family_name
<< " decoder package family is not installed. rc=" << rc;
continue;
}
DVLOG(2) << __func__ << ":" << package_family_name << " is installed.";
// Allocate required sizes to get all the package fullnames.
std::vector<wchar_t> buffer(buffer_size);
std::vector<wchar_t*> package_full_names(package_count);
rc = GetPackagesByPackageFamily(package_family_name.data(), &package_count,
package_full_names.data(), &buffer_size,
buffer.data());
if (package_count == 0) {
DLOG(WARNING) << "Cannot find " << package_family_name << ". rc=" << rc;
return package_paths;
}
wchar_t package_path[MAX_PATH];
// Get all the package paths for each package full name.
for (const wchar_t* package_full_name : package_full_names) {
DVLOG(2) << __func__ << ": package_full_name=" << package_full_name;
uint32_t package_path_len = std::size(package_path);
rc = GetPackagePathByFullName(package_full_name, &package_path_len,
package_path);
if (rc != ERROR_SUCCESS) {
DLOG(WARNING) << "Cannot find " << package_full_name << ". rc=" << rc;
package_paths.clear();
return package_paths;
}
// Dolby places their MFT inside a 'MFT' folder.
if (codec_package == MediaFoundationCodecPackage::kEAC3 ||
codec_package == MediaFoundationCodecPackage::kAC4) {
package_paths.emplace_back(base::FilePath(package_path).Append(L"MFT"));
} else {
package_paths.emplace_back(package_path);
}
}
}
if (package_paths.empty()) {
DVLOG(2) << __func__ << ": empty package_paths.";
return package_paths;
}
// AV1 1.1.50332.0 or later does not have the 'build' folder in the path.
if (codec_package == MediaFoundationCodecPackage::kAV1) {
std::vector<base::FilePath> legacy_av1_package_paths;
for (const auto& package_path : package_paths) {
legacy_av1_package_paths.emplace_back(package_path.Append(L"build"));
}
package_paths.insert(package_paths.end(), legacy_av1_package_paths.begin(),
legacy_av1_package_paths.end());
}
// Append the path to the library based on binary architecture.
for (auto& package_path : package_paths) {
constexpr wchar_t kArch[] =
#ifdef _M_AMD64
L"x64";
#elif _M_IX86
L"x86";
#elif _M_ARM64
L"arm64";
#else
#error Unsupported processor type.
#endif
package_path = package_path.Append(kArch);
package_path = package_path.Append(decoder_lib_name);
DVLOG(2) << __func__ << ": package_path=" << package_path.value();
}
return package_paths;
}
} // namespace media