From 6bc4d47ca14df5079ccc2a88cac52cc3a3cf69c8 Mon Sep 17 00:00:00 2001 From: Sunrisepeak Date: Fri, 30 Oct 2026 01:45:50 +0900 Subject: [PATCH] mcpplibs.mwrap.libvpx 1.17.0: libvpx-m (VP9 and WebM as C++23 modules) Descriptor pkgs/mwrap/libvpx.lua (form A, the immutable mwrap-1.17.0 release asset, tagged on libvpx-m's merged main; no CN mirror yet), over compat.libvpx 1.17.0 and compat.libwebm 1.0.0.32. Consumer tests/mwrap/libvpx-webm: VP9 frames encoded through the typed controls, muxed into a WebM with mkvmuxer (the same bytes twice), parsed back with mkvparser and decoded within a PSNR; and the side header beside the import. The installed-template check in validate.yml with its deployment contract (the wrapper's LICENSE/NOTICE, libvpx's and libwebm's README, LICENSE, PATENTS and AUTHORS, byte for byte in a relocated bundle), and the plan. --- .../docs/2026-10-30-add-libvpx-mwrap-plan.md | 63 ++++++++ .github/workflows/validate.yml | 5 + CHANGELOG.md | 10 ++ mcpp.toml | 1 + pkgs/mwrap/libvpx.lua | 44 ++++++ tests/mwrap/check_installed_template.py | 24 ++++ tests/mwrap/libvpx-webm/mcpp.toml | 11 ++ tests/mwrap/libvpx-webm/tests/behavior.cpp | 134 ++++++++++++++++++ tests/mwrap/libvpx-webm/tests/side_header.cpp | 32 +++++ 9 files changed, 324 insertions(+) create mode 100644 .agents/docs/2026-10-30-add-libvpx-mwrap-plan.md create mode 100644 pkgs/mwrap/libvpx.lua create mode 100644 tests/mwrap/libvpx-webm/mcpp.toml create mode 100644 tests/mwrap/libvpx-webm/tests/behavior.cpp create mode 100644 tests/mwrap/libvpx-webm/tests/side_header.cpp diff --git a/.agents/docs/2026-10-30-add-libvpx-mwrap-plan.md b/.agents/docs/2026-10-30-add-libvpx-mwrap-plan.md new file mode 100644 index 00000000..3624930d --- /dev/null +++ b/.agents/docs/2026-10-30-add-libvpx-mwrap-plan.md @@ -0,0 +1,63 @@ +# Add mcpplibs.mwrap.libvpx (libvpx-m 1.17.0) + +## Form + +- Third-party upstreams, both BSD-3-Clause with the WebM project's royalty-free patent grant: [libvpx](https://chromium.googlesource.com/webm/libvpx) + 1.17.0 (VP9) and [libwebm](https://github.com/webmproject/libwebm) 1.0.0.32 (the WebM container), the tag archives + compat.libvpx and compat.libwebm pin (#624). +- Form A external mwrap module repository [mcpplibs/libvpx-m](https://github.com/mcpplibs/libvpx-m), package + `mcpplibs.mwrap.libvpx`, version 1.17.0 (libvpx's version; the first release of the identity, no revision suffix; libwebm + 1.0.0.32 in `[package.metadata.mwrap]`), tag series `mwrap-${version}`, tagged on the merged main commit (`676fceb`); + release asset `libvpx-m-1.17.0.tar.gz` (`e6a5a062…9211`). No CN mirror yet (docs/cn-mirror.md: CN users fall back to the + GitHub release). +- The container is bundled with the codec as libogg is with libopus in opus-m: WebM is how VP9 travels, and libvpx's own + tree carries libwebm for vpxenc/vpxdec. +- Implementation ownership: the libraries are compat.libvpx and compat.libwebm (static libraries from the tag archives). + The wrapper vendors no library code. It retains each upstream's README, LICENSE, PATENTS and AUTHORS under + `upstream/{libvpx,libwebm}/`, with checksums in `upstream/documents.json`, and deploys them with its own LICENSE/NOTICE + (`runtime.deploy`). + +## Modules + +- `mcpplibs.mwrap.libvpx`: libvpx — 133 types, 192 enumerators, the 35 functions upstream exports (vpx/exports_* and vp9's + lists) and the two VP9 interfaces, by `export using`. VP8 is not built (compat.libvpx: `--disable-vp8`): its interfaces, + which vp8cx.h/vp8dx.h declare, are not exported. The headers' 86 typed controls (static functions made by + `VPX_CTRL_USE_TYPE`) adapted under the same names in `mcpplibs::mwrap::libvpx`, each calling `vpx_codec_control_` as + upstream's body does. Re-exports the two below. +- `mcpplibs.mwrap.libvpx.webm`: libwebm — the classes, types, enumerators and free functions of mkvmuxer (29/0/26), + mkvparser (24/0/11) and libwebm (4/154/9) in their own namespaces; the namespace-scope constants (internal linkage) under + the same names in `mcpplibs::mwrap::libvpx::mkvmuxer` / `::mkvparser`. +- `mcpplibs.mwrap.libvpx.macros`: 74 macros as `inline constexpr` of their expression's type, `vpx_codec_enc_init`, + `vpx_codec_enc_init_multi`, `vpx_codec_dec_init`, `vpx_codec_version_major/_minor/_patch` as functions, + `VPX_VERSION_MAJOR/_MINOR/_PATCH` as constexpr functions. +- Stay macros, in ``: `vpx_codec_control` (token concatenation), `VPX_CTRL_USE_TYPE*`, + `VPX_CTRL_VOID`, the 86 empty `VPX_CTRL_` feature tests, the declaration annotations, libwebm's + `LIBWEBM_DISALLOW_COPY_AND_ASSIGN`, the include guards. + +`tools/check_exports.py` fails when the generated sources are stale, a declaration is not exported, a control not adapted, +or a macro neither mapped nor accounted for; every mapping is checked against the raw headers in a header-mixing test, +and every exported function and control's address is taken in a link test. + +## Verification + +Wrapper CI (Linux x86_64 GCC 16.1 and LLVM 23.1.3, Linux arm64 GCC 16.1, macOS LLVM, Windows LLVM, wasm32-emscripten under +node; all required): build, the three test programs in the dev and release profiles — VP9 at good quality, real time, four +threads and lossless, muxed into WebM, parsed and decoded back, each file's FNV-1a pinned and the same on every row —, the +export audit, and the conformance run on Linux and macOS: `examples/vpxwebm`, written against the module, writes the same +IVF bytes as upstream's `vpxenc` (built from the same tag by its own configure) for six settings, and `vpxdec` reads its +WebM files to the same frames as the module reads `vpxenc`'s (18 comparisons). The templates job scaffolds the default +`webm` template as an installed package and runs it. + +Here, with the CI-pinned mcpp 2026.10.27.1: + +- `bash tests/run_members.sh libvpx-webm`: the real release archive; VP9 frames through the typed controls, muxed with + mkvmuxer (track UID given: the same bytes twice), parsed with mkvparser and decoded (50.7 dB), and the side header + beside the import: `test result ok`. +- `python3 tests/mwrap/check_installed_template.py --package mcpplibs.mwrap.libvpx@1.17.0 --deploy`: the unmodified + template from the real archive (60 frames, 51.8 dB), then a relocated self-contained bundle whose `licenses/libvpx/` + holds the wrapper's LICENSE/NOTICE and both libraries' README, LICENSE, PATENTS and AUTHORS byte for byte. + +## Motivation + +openmui's video component (openmui.video, D-86) encodes its frames and sound track into WebM: VP9 through this wrapper and +Opus through mcpplibs.mwrap.opus, both royalty-free and BSD-3-Clause, linked statically under the project's licence policy. diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 91b8709c..91f3f747 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -1663,6 +1663,11 @@ jobs: shell: bash run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.libwebp@1.5.0 --deploy + - name: Installed libvpx wrapper archive, actual default webm template and its relocated notices + if: contains(format(' {0} ', env.MEMBERS), ' libvpx-webm ') && matrix.toolchain == 'default' + shell: bash + run: python3 tests/mwrap/check_installed_template.py --mcpp "$MCPP" --package mcpplibs.mwrap.libvpx@1.17.0 --deploy + - name: Installed PocketPy wrapper archive, actual default script template and its relocated notices if: contains(format(' {0} ', env.MEMBERS), ' pocketpy-embed ') && matrix.toolchain == 'default' shell: bash diff --git a/CHANGELOG.md b/CHANGELOG.md index d5769df1..ba61dbdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,16 @@ ### Added +- **mcpplibs.mwrap.libvpx 1.17.0(新包)。** libvpx-m:以 C++23 模块(`import mcpplibs.mwrap.libvpx;`)使用 VP9 编解码库 + libvpx 1.17.0 与 WebM 容器库 libwebm 1.0.0.32(建立在 compat.libvpx 与 compat.libwebm 之上)。根模块导出 libvpx 头文件的 + 133 个类型、192 个枚举值、上游导出的 35 个函数与两个 VP9 接口(VP8 未构建,其接口不导出),头文件中 86 个类型化控制函数 + (`VPX_CTRL_USE_TYPE` 生成的 static 函数)在 `mcpplibs::mwrap::libvpx` 中同名适配;`mcpplibs.mwrap.libvpx.webm` 在各自 + 命名空间导出 libwebm 的 mkvmuxer、mkvparser 与 libwebm(命名空间作用域常量为内部链接,其值在 + `mcpplibs::mwrap::libvpx::mkvmuxer` / `::mkvparser` 下同名提供);`mcpplibs.mwrap.libvpx.macros` 把 74 个宏映射为常量、 + 函数与 constexpr 函数,其余(`vpx_codec_control` 等)留在 ``。描述符为 libvpx-m 的不可变 + `mwrap-1.17.0` 发布包(暂无 CN 镜像)。新增使用者 `tests/mwrap/libvpx-webm`:经类型化控制编码 VP9、mkvmuxer 封装、 + mkvparser 解析并解码(PSNR 下限)、两次封装字节相同,以及侧边头文件与 import 同时使用;validate.yml 新增已安装模板检查 + (wrapper 的 LICENSE/NOTICE 与两个库的 README、LICENSE、PATENTS、AUTHORS 在搬迁后的发布包中逐字节一致)。 - **compat.libvpx 1.17.0(新包)。** libvpx:WebM 项目的 VP9 视频编解码器(编码器与解码器;BSD-3-Clause,附 WebM 项目的 免版税专利授权 PATENTS)。从 `v1.17.0` 标签归档构建上游 `configure --target=generic-gnu --disable-vp8 --enable-vp9 --enable-multithread`(不含示例、工具、文档、单元测试、webm-io、libyuv)所编译的 101 个 C 源文件:通用 C 实现,无 SIMD、 diff --git a/mcpp.toml b/mcpp.toml index 69835f5d..e74e8882 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -27,6 +27,7 @@ members = [ "tests/mwrap/sheenbidi-bidi", "tests/mwrap/dr_libs-audio", "tests/mwrap/opus-ogg", + "tests/mwrap/libvpx-webm", "tests/mwrap/box2d-physics", "tests/mwrap/miniaudio-engine", "tests/mwrap/freetype-render", diff --git a/pkgs/mwrap/libvpx.lua b/pkgs/mwrap/libvpx.lua new file mode 100644 index 00000000..95152325 --- /dev/null +++ b/pkgs/mwrap/libvpx.lua @@ -0,0 +1,44 @@ +-- Immutable upstream-aligned mwrap source release (libvpx-m mwrap-1.17.0). +-- The CN mirror is added by a maintainer with mcpp-res access; until then CN +-- users fall back to the GitHub release (docs/cn-mirror.md). +-- +-- The wrapper is Apache-2.0. The libraries it links are BSD-3-Clause with the +-- WebM project's patent grant, linked statically: compat.libvpx (libvpx +-- 1.17.0, VP9) and compat.libwebm (libwebm 1.0.0.32, the WebM container). The +-- package deploys each one's README, LICENSE, PATENTS and AUTHORS beside +-- programs (runtime.deploy). +package = { + spec = "1", + namespace = "mcpplibs.mwrap", + name = "libvpx", + description = "libvpx-m: VP9 video (libvpx 1.17.0) and the WebM container (libwebm 1.0.0.32) as C++23 modules", + licenses = { "Apache-2.0" }, + repo = "https://github.com/mcpplibs/libvpx-m", + type = "package", + extensions = { + autoupdate = { + tag = "mwrap-${version}", + url = "https://github.com/mcpplibs/libvpx-m/releases/download/${tag}/libvpx-m-${version}.tar.gz", + }, + }, + xpm = { + linux = { + ["1.17.0"] = { + url = "https://github.com/mcpplibs/libvpx-m/releases/download/mwrap-1.17.0/libvpx-m-1.17.0.tar.gz", + sha256 = "e6a5a062923b17961d44c7d1d74cd4190f774d4eb38d639607530ff987669211", + }, + }, + macosx = { + ["1.17.0"] = { + url = "https://github.com/mcpplibs/libvpx-m/releases/download/mwrap-1.17.0/libvpx-m-1.17.0.tar.gz", + sha256 = "e6a5a062923b17961d44c7d1d74cd4190f774d4eb38d639607530ff987669211", + }, + }, + windows = { + ["1.17.0"] = { + url = "https://github.com/mcpplibs/libvpx-m/releases/download/mwrap-1.17.0/libvpx-m-1.17.0.tar.gz", + sha256 = "e6a5a062923b17961d44c7d1d74cd4190f774d4eb38d639607530ff987669211", + }, + }, + }, +} diff --git a/tests/mwrap/check_installed_template.py b/tests/mwrap/check_installed_template.py index 810ebf8b..ce4fd6bc 100644 --- a/tests/mwrap/check_installed_template.py +++ b/tests/mwrap/check_installed_template.py @@ -272,6 +272,30 @@ def main(): notice = (roots[0] / "NOTICE").read_bytes() assert b"mcpp-community" in notice and b"Google" in notice print(f"Verified {len(declared)} byte-identical wrapper/libwebp license files", flush=True) + elif identity == "mcpplibs.mwrap.libvpx": + # libvpx and libwebm (BSD-3-Clause with the WebM project's + # patent grant) are linked statically: the wrapper's + # LICENSE/NOTICE and each library's README, LICENSE, PATENTS + # and AUTHORS travel with the program. + sources = [path for store in (home / "xpkgs", home / "registry/data/xpkgs") + for path in store.glob(f"mcpplibs.mwrap-x-libvpx/{version}/*/src/libvpx.cppm")] + assert len(sources) == 1, sources + source = sources[0].parent.parent + declared = tomllib.loads((source / "mcpp.toml").read_text(encoding="utf-8"))["runtime"]["deploy"] + roots = list(relocated.rglob("licenses/libvpx")) + assert len(roots) == 1, f"Missing libvpx runtime license tree: {roots}" + for entry in declared: + notice = source / entry["from"] + copied = roots[0].parent.parent / entry["to"] / notice.name + assert copied.is_file() and copied.read_bytes() == notice.read_bytes(), copied + assert b"The WebM Project authors" in (roots[0] / "upstream/libvpx/LICENSE").read_bytes() + assert b"Google Inc." in (roots[0] / "upstream/libwebm/LICENSE.TXT").read_bytes() + for patents in ("upstream/libvpx/PATENTS", "upstream/libwebm/PATENTS.TXT"): + assert b"patent" in (roots[0] / patents).read_bytes(), patents + assert b"Apache License" in (roots[0] / "LICENSE").read_bytes() + notice = (roots[0] / "NOTICE").read_bytes() + assert b"mcpp-community" in notice and b"WebM Project" in notice + print(f"Verified {len(declared)} byte-identical wrapper/libvpx/libwebm license files", flush=True) elif identity == "mcpplibs.mwrap.pocketpy": # PocketPy is MIT and linked statically: its LICENSE and README # travel with the program beside the wrapper's LICENSE/NOTICE. diff --git a/tests/mwrap/libvpx-webm/mcpp.toml b/tests/mwrap/libvpx-webm/mcpp.toml new file mode 100644 index 00000000..b2252864 --- /dev/null +++ b/tests/mwrap/libvpx-webm/mcpp.toml @@ -0,0 +1,11 @@ +[package] +name = "libvpx-webm" +version = "1.17.0" +description = "Consume the immutable libvpx wrapper: VP9 frames encoded through the typed controls, muxed into a WebM with mkvmuxer, parsed back with mkvparser and decoded within a PSNR, the bytes the same twice; the side header beside the import" + +[indices] +# Use the complete candidate built-in index prepared by tests/run_members.sh. +# An explicit empty table overrides the legacy workspace redirect. + +[dependencies] +"mcpplibs.mwrap.libvpx" = "1.17.0" diff --git a/tests/mwrap/libvpx-webm/tests/behavior.cpp b/tests/mwrap/libvpx-webm/tests/behavior.cpp new file mode 100644 index 00000000..55613c9b --- /dev/null +++ b/tests/mwrap/libvpx-webm/tests/behavior.cpp @@ -0,0 +1,134 @@ +// The wrapper through its modules alone: VP9 frames encoded through the typed +// controls, muxed into a WebM in memory with mkvmuxer (track UID given), +// parsed back with mkvparser and decoded within a PSNR; the same bytes twice. +import std; +import mcpplibs.mwrap.libvpx; + +namespace m = mcpplibs::mwrap::libvpx::macros; +namespace vpx = mcpplibs::mwrap::libvpx; + +namespace { + +constexpr int W = 160, H = 96, FRAMES = 20; + +void draw(vpx_image_t& img, int t) { + for (int y = 0; y < H; ++y) + for (int x = 0; x < W; ++x) + img.planes[0][y * img.stride[0] + x] = static_cast(x >= 20 + 4 * t && x < 50 + 4 * t && y >= 30 && y < 60 ? 230 : 16 + (x + y + 3 * t) % 200); + for (int p = 1; p < 3; ++p) + for (int y = 0; y < H / 2; ++y) + for (int x = 0; x < W / 2; ++x) img.planes[p][y * img.stride[p] + x] = static_cast(p == 1 ? 100 + x : 150 - y); +} + +class Memory final : public mkvmuxer::IMkvWriter { +public: + std::vector bytes; + std::int64_t at = 0; + mkvmuxer::int32 Write(const void* buf, mkvmuxer::uint32 len) override { + if (bytes.size() < static_cast(at) + len) bytes.resize(static_cast(at) + len); + std::memcpy(bytes.data() + at, buf, len); + at += len; + return 0; + } + mkvmuxer::int64 Position() const override { return at; } + mkvmuxer::int32 Position(mkvmuxer::int64 p) override { return at = p, 0; } + bool Seekable() const override { return true; } + void ElementStartNotify(mkvmuxer::uint64, mkvmuxer::int64) override {} +}; + +class Reader final : public mkvparser::IMkvReader { +public: + explicit Reader(const std::vector& b) : bytes(b) {} + int Read(long long pos, long len, unsigned char* buf) override { + if (pos < 0 || len < 0 || static_cast(pos + len) > bytes.size()) return -1; + std::memcpy(buf, bytes.data() + pos, static_cast(len)); + return 0; + } + int Length(long long* total, long long* available) override { + *total = *available = static_cast(bytes.size()); + return 0; + } + const std::vector& bytes; +}; + +std::vector webm() { + vpx_codec_enc_cfg_t cfg; + vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &cfg, 0); + cfg.g_w = W; + cfg.g_h = H; + cfg.g_timebase = {1, 30}; + cfg.g_lag_in_frames = 0; + cfg.rc_end_usage = VPX_Q; + vpx_codec_ctx_t enc; + if (m::vpx_codec_enc_init(&enc, vpx_codec_vp9_cx(), &cfg, 0) != VPX_CODEC_OK) return {}; + vpx::vpx_codec_control_VP8E_SET_CPUUSED(&enc, VP8E_SET_CPUUSED, 6); + vpx::vpx_codec_control_VP8E_SET_CQ_LEVEL(&enc, VP8E_SET_CQ_LEVEL, 20u); + Memory out; + mkvmuxer::Segment segment; + segment.Init(&out); + segment.set_mode(mkvmuxer::Segment::kFile); + const auto track = segment.AddVideoTrack(W, H, 1); + auto* v = static_cast(segment.GetTrackByNumber(track)); + v->set_codec_id(mkvmuxer::Tracks::kVp9CodecId); + v->set_uid(7); + vpx_image_t img; + vpx_img_alloc(&img, VPX_IMG_FMT_I420, W, H, 16); + for (int t = 0; t <= FRAMES; ++t) { + if (t < FRAMES) draw(img, t); + vpx_codec_encode(&enc, t < FRAMES ? &img : nullptr, t, 1, 0, m::VPX_DL_GOOD_QUALITY); + vpx_codec_iter_t it = nullptr; + while (const vpx_codec_cx_pkt_t* p = vpx_codec_get_cx_data(&enc, &it)) + if (p->kind == VPX_CODEC_CX_FRAME_PKT) + segment.AddFrame(static_cast(p->data.frame.buf), p->data.frame.sz, track, + static_cast(p->data.frame.pts) * 1'000'000'000 / 30, (p->data.frame.flags & m::VPX_FRAME_IS_KEY) != 0); + } + vpx_img_free(&img); + vpx_codec_destroy(&enc); + segment.Finalize(); + return out.bytes; +} + +} // namespace + +int main() { + const auto file = webm(); + if (file.empty() || file != webm()) return 1; + Reader reader(file); + long long pos = 0; + mkvparser::EBMLHeader header; + mkvparser::Segment* raw = nullptr; + if (header.Parse(&reader, pos) != 0 || std::string_view(header.m_docType) != "webm") return 2; + if (mkvparser::Segment::CreateInstance(&reader, pos, raw) != 0 || !raw || raw->Load() < 0) return 3; + std::unique_ptr segment(raw); + vpx_codec_dec_cfg_t dcfg{}; + vpx_codec_ctx_t dec; + if (m::vpx_codec_dec_init(&dec, vpx_codec_vp9_dx(), &dcfg, 0) != VPX_CODEC_OK) return 4; + vpx_image_t ref; + vpx_img_alloc(&ref, VPX_IMG_FMT_I420, W, H, 16); + int frames = 0; + double worst = 99; + for (const mkvparser::Cluster* c = segment->GetFirst(); c && !c->EOS(); c = segment->GetNext(c)) { + const mkvparser::BlockEntry* e = nullptr; + for (c->GetFirst(e); e && !e->EOS(); c->GetNext(e, e)) { + const mkvparser::Block::Frame& f = e->GetBlock()->GetFrame(0); + std::vector data(static_cast(f.len)); + f.Read(&reader, data.data()); + vpx_codec_decode(&dec, data.data(), static_cast(data.size()), nullptr, 0); + vpx_codec_iter_t it = nullptr; + while (vpx_image_t* out = vpx_codec_get_frame(&dec, &it)) { + draw(ref, frames++); + double se = 0; + for (int y = 0; y < H; ++y) + for (int x = 0; x < W; ++x) { + const int d = out->planes[0][y * out->stride[0] + x] - ref.planes[0][y * ref.stride[0] + x]; + se += d * d; + } + if (se > 0) worst = std::min(worst, 10 * std::log10(255.0 * 255.0 * W * H / se)); + } + } + } + vpx_img_free(&ref); + vpx_codec_destroy(&dec); + std::println("{} frames in {} bytes of WebM, worst PSNR {:.1f} dB ({})", frames, file.size(), worst, vpx_codec_version_str()); + return frames == FRAMES && worst > 35 ? 0 : 5; +} diff --git a/tests/mwrap/libvpx-webm/tests/side_header.cpp b/tests/mwrap/libvpx-webm/tests/side_header.cpp new file mode 100644 index 00000000..d3f0b90c --- /dev/null +++ b/tests/mwrap/libvpx-webm/tests/side_header.cpp @@ -0,0 +1,32 @@ +// The side header from the installed package, beside the import: the +// header's vpx_codec_control macro (its typed static control) and the +// adapted control set the same thing; a VPX_CTRL_ feature test; the +// mapped constants beside the macros (a function-like macro is not expanded +// when its name is followed by `)`). +#include + +import std; +import mcpplibs.mwrap.libvpx; + +namespace m = mcpplibs::mwrap::libvpx::macros; + +#ifndef VPX_CTRL_VP9E_SET_ROW_MT +#error "the VPX_CTRL_ feature tests come with the header" +#endif + +int main() { + vpx_codec_enc_cfg_t cfg; + if (vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &cfg, 0) != VPX_CODEC_OK) return 1; + cfg.g_w = 64; + cfg.g_h = 64; + vpx_codec_ctx_t a, b; + if ((m::vpx_codec_enc_init)(&a, vpx_codec_vp9_cx(), &cfg, 0) != VPX_CODEC_OK) return 2; + if (vpx_codec_enc_init(&b, vpx_codec_vp9_cx(), &cfg, 0) != VPX_CODEC_OK) return 3; + if (vpx_codec_control(&a, VP8E_SET_CPUUSED, 7) != VPX_CODEC_OK) return 4; + if (mcpplibs::mwrap::libvpx::vpx_codec_control_VP8E_SET_CPUUSED(&b, VP8E_SET_CPUUSED, 7) != VPX_CODEC_OK) return 5; + if (&::vpx_codec_encode != &vpx_codec_encode) return 6; + static_assert((m::VPX_VERSION_MAJOR)(0x011100) == VPX_VERSION_MAJOR(0x011100)); + vpx_codec_destroy(&a); + vpx_codec_destroy(&b); + return 0; +}