Skip to content

feat: migrate video playback from AVPro to UUAV#9463

Open
NickKhalow wants to merge 38 commits into
devfrom
feat/migrate-avpro-to-uuav
Open

feat: migrate video playback from AVPro to UUAV#9463
NickKhalow wants to merge 38 commits into
devfrom
feat/migrate-avpro-to-uuav

Conversation

@NickKhalow

@NickKhalow NickKhalow commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Pull Request Description

What does this PR change?

Migrates video/audio media streaming from the AVPro Video Ultra package to UUAV - an FFmpeg-based player with a native Rust core, embedded directly in the repo under Assets/Plugins/UUAV. Supported platforms: Windows x86_64 (D3D11) and macOS arm64 (Metal); Linux stays compiled out, as before.

  • Removes com.renderheads.avpro.video-ultra from Packages/manifest.json - UUAV ships in-tree, no external package reference.

Plugin layout (Assets/Plugins/UUAV)

native/ - the Rust crate that builds the native player (uuav.dll / libuuav.dylib): FFmpeg 8 demux/decode, hardware-accelerated video decoding, audio pulled through OnAudioFilterRead. Platform-specific code lives in _windows/_macos sibling modules (hw_device_*, video_decoder_*, video_output_*) selected with #[cfg(target_os)] at the dispatch site - no cross-platform stub contracts.

  • Windows: D3D11VA hardware decode; one NV12 D3D11 resource shared by both planes. FFmpeg comes from prebuilt BtbN LGPL shared DLLs (avcodec-63 et al.).
  • macOS: VideoToolbox decode → CVPixelBuffer/IOSurface → two Metal plane textures (Y R8Unorm, UV RG8Unorm) blitted on the plugin's own MTLCommandQueue. FFmpeg (n8.1) is built from source via native/scripts/build-ffmpeg-macos.sh into a git-ignored .third_party/ (source-build sonames differ from the Windows DLLs: avcodec 62 etc. - build.sh resolves majors dynamically). build.sh also handles @rpath dylib naming and the mandatory ad-hoc code signing on arm64.
  • build.sh is cross-platform: it detects the host OS, builds the right cargo target, and deploys binaries into Packages/UUAV/Runtime/Plugins/{x86_64,macOS}.

Packages/UUAV/Runtime - the C# binding layer (NativeMethods, UUAVRuntime, UUAVPlayer, UUAVClient.asmdef) plus the prebuilt binaries. On both platforms the native side presents NV12 planes; Unity wraps them with Texture2D.CreateExternalTexture and converts to RGB with the bundled Hidden/UUAV/NV12ToRGB shader (Graphics.Blit), with frame presentation driven by GL.IssuePluginEvent. On macOS, UUAVRuntime refuses to initialize on any graphics API other than Metal. Local-file playback is editor-only; player builds accept streaming URLs only.

Packages/UUAV/AVProCompat - a RenderHeads.Media.AVProVideo.MediaPlayer facade over UUAVPlayer (MediaPlayer, MediaPlayerEvent, Enums, Interfaces, UUAVBackend), so the existing MediaStream code (systems, pool, tests) keeps compiling against the AVPro API surface largely unchanged.

Packages/UUAV/Example - a minimal standalone example scene/assembly for the player, independent of Explorer.

Explorer integration

  • Adapts MediaStream to the compat surface: drops the AutoOpen flag in MediaPlayerCustomPool and the manual SetAudioSource wiring in MultiMediaPlayer (the compat MediaPlayer handles audio itself); updates MediaPlayer.prefab accordingly.
  • Links UUAV.AVProCompat into the ECS.Unity, DCL.Plugins, and DCL.EditMode.Tests asmdefs; adds injection/skip logs to MediaPlayerPluginWrapper.
  • Retargets the AV_PRO_PRESENT version-define in DCL.Plugins from com.renderheads.avpro.video-ultra to com.nickkhalow.uuav (ProjectSettings scripting defines are unchanged vs dev).

Test Instructions

Steps (standard run):

metaforge explorer run 9463

Expected result:
Video streams in scenes play back correctly (e.g. video screens in Genesis Plaza or any scene using VideoPlayer/media streams), with audio in sync.

Steps (fresh account):

metaforge account create --clear
metaforge explorer run 9463

Expected result:
Same as above - media streams play with no errors in logs.

Prerequisites

  • Windows x86_64 build, or
  • macOS arm64 (Apple Silicon) build - requires Metal

Test Steps

  1. Enter a scene that uses video streaming (video screens / PBVideoPlayer).
  2. Verify the video plays, pauses, and seeks as driven by the scene.
  3. Verify audio plays and stays in sync with video.
  4. Roam between scenes to exercise media player pooling (create/release).
  5. Repeat on both platforms - the Windows D3D11 path and the macOS Metal path are separate native implementations.

Additional Testing Notes

  • Native binaries are included for win_x86_64 and macOS arm64 only - on other platforms the media player systems are compiled out (AV_PRO_PRESENT gate).
  • The AV_PRO_PRESENT version-define is keyed on the com.nickkhalow.uuav package name; verify it still activates now that UUAV is embedded under Assets/ rather than installed via UPM (watch for the [MediaPlayerPluginWrapper] Inject vs Ignore Inject log on startup).
  • Watch logs for native library load errors on startup (uuav.dll/libuuav.dylib, FFmpeg libraries).
  • On macOS, startup on a non-Metal graphics API logs an error and leaves the runtime uninitialized by design.
  • The AVProCompat layer intentionally covers only the AVPro features MediaStream consumes - it is poll-based and will need extending as new AVPro API surface is used.

Quality Checklist

  • Changes have been tested locally
  • Documentation has been updated (if required)
  • Performance impact has been considered
  • For SDK features: Test scene is included

Code Review Reference

Please review our Branch & PR Standards before submitting. It explains the automated review flow, QA/DEV approval requirements, and what each label does - especially useful for first-time contributors.

@NickKhalow NickKhalow added the force-build Used to trigger a build on draft PR label Jul 22, 2026
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

@NickKhalow NickKhalow self-assigned this Jul 22, 2026
@NickKhalow NickKhalow added the Windows Only Issue only happens on Windows builds label Jul 22, 2026
@NickKhalow NickKhalow removed the force-build Used to trigger a build on draft PR label Jul 23, 2026
@NickKhalow NickKhalow added force-build Used to trigger a build on draft PR and removed Windows Only Issue only happens on Windows builds labels Jul 24, 2026
@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Warnings not reduced: 14591 => 14683 — remove at least one warning to merge.

Warnings/errors in files changed by this PR (115)
Assets/DCL/SDKComponents/MediaStream/MediaPlayerCustomPool.cs:77  AccessToStaticMemberViaDerivedType  Access to a static member of a type via a derived type
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:215  CSharpWarnings::CS8600  Converting null literal or possible null value into non-nullable type
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:256  CSharpWarnings::CS8600  Converting null literal or possible null value into non-nullable type
Assets/DCL/SDKComponents/MediaStream/Systems/MediaPlayerPluginWrapper.cs:30  CSharpWarnings::CS8618  Non-nullable field 'frameTimeBudget' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:201  CSharpWarnings::CS8656  Call to non-readonly method 'IsAvProPlayer' from a 'readonly' member results in an implicit copy of 'this'
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:215  CSharpWarnings::CS8656  Call to non-readonly method 'IsAvProPlayer' from a 'readonly' member results in an implicit copy of 'this'
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:166  CSharpWarnings::CS8656  Call to non-readonly method 'Match<TCtx>' from a 'readonly' member results in an implicit copy of 'this'
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:194  CSharpWarnings::CS8656  Call to non-readonly method 'Match<TCtx>' from a 'readonly' member results in an implicit copy of 'this'
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:76  ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract  Expression is always true according to nullable reference types' annotations
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:87  ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract  Expression is always true according to nullable reference types' annotations
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/MediaPlayer.cs:51  ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract  Expression is always true according to nullable reference types' annotations
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:104  ConditionalAccessQualifierIsNonNullableAccordingToAPIContract  Conditional access qualifier expression is never null according to nullable reference types' annotations
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:108  ConditionalAccessQualifierIsNonNullableAccordingToAPIContract  Conditional access qualifier expression is never null according to nullable reference types' annotations
Assets/DCL/SDKComponents/MediaStream/MultiMediaPlayer.cs:112  ConditionalAccessQualifierIsNonNullableAccordingToAPIContract  Conditional access qualifier expression is never null according to nullable reference types' annotations
Assets/DCL/SDKComponents/MediaStream/MediaPlayerCustomPool.cs:87  FunctionNeverReturns  Function never returns
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:8  InconsistentNaming  Name 'AbsolutePathOrURL' does not match rule 'Enum members'. Suggested name is 'ABSOLUTE_PATH_OR_URL'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/UUAVBackend.cs:9  InconsistentNaming  Name 'Buffered' does not match rule 'static_readonly_should_be_capital_snake_case'. Suggested name is 'BUFFERED'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:31  InconsistentNaming  Name 'Closed' does not match rule 'Enum members'. Suggested name is 'CLOSED'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:25  InconsistentNaming  Name 'Debug' does not match rule 'Enum members'. Suggested name is 'DEBUG'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:22  InconsistentNaming  Name 'DecodeFailed' does not match rule 'Enum members'. Suggested name is 'DECODE_FAILED'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/UUAVRuntime.cs:20  InconsistentNaming  Name 'DefaultLogLevel' does not match rule 'constants_should_be_capital_snake_case'. Suggested name is 'DEFAULT_LOG_LEVEL'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:33  InconsistentNaming  Name 'DirectShow' does not match rule 'Enum members'. Suggested name is 'DIRECT_SHOW'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:36  InconsistentNaming  Name 'Ended' does not match rule 'Enum members'. Suggested name is 'ENDED'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:21  InconsistentNaming  Name 'Error' does not match rule 'Enum members'. Suggested name is 'ERROR'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:37  InconsistentNaming  Name 'Error' does not match rule 'Enum members'. Suggested name is 'ERROR'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:41  InconsistentNaming  Name 'FacebookAudio360' does not match rule 'Enum members'. Suggested name is 'FACEBOOK_AUDIO360'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/MediaPlayer.cs:19  InconsistentNaming  Name 'FacebookAudio360' does not match rule 'Enum members'. Suggested name is 'FACEBOOK_AUDIO360'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:20  InconsistentNaming  Name 'Fatal' does not match rule 'Enum members'. Suggested name is 'FATAL'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:23  InconsistentNaming  Name 'Info' does not match rule 'Enum members'. Suggested name is 'INFO'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:248  InconsistentNaming  Name 'Lib' does not match rule 'constants_should_be_capital_snake_case'. Suggested name is 'LIB'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:21  InconsistentNaming  Name 'LoadFailed' does not match rule 'Enum members'. Suggested name is 'LOAD_FAILED'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:32  InconsistentNaming  Name 'MediaFoundation' does not match rule 'Enum members'. Suggested name is 'MEDIA_FOUNDATION'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/UUAVPlayer.cs:19  InconsistentNaming  Name 'MediaInfo_M' does not match rule 'members_should_be_pascal_case'. Suggested name is 'MediaInfoM'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:105  InconsistentNaming  Name 'NameLen' does not match rule 'constants_should_be_capital_snake_case'. Suggested name is 'NAME_LEN'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:20  InconsistentNaming  Name 'None' does not match rule 'Enum members'. Suggested name is 'NONE'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:42  InconsistentNaming  Name 'None' does not match rule 'Enum members'. Suggested name is 'NONE'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/MediaPlayer.cs:20  InconsistentNaming  Name 'None' does not match rule 'Enum members'. Suggested name is 'NONE'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/UUAVBackend.cs:8  InconsistentNaming  Name 'NotBuffered' does not match rule 'static_readonly_should_be_capital_snake_case'. Suggested name is 'NOT_BUFFERED'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:32  InconsistentNaming  Name 'Opening' does not match rule 'Enum members'. Suggested name is 'OPENING'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:19  InconsistentNaming  Name 'Panic' does not match rule 'Enum members'. Suggested name is 'PANIC'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:35  InconsistentNaming  Name 'Paused' does not match rule 'Enum members'. Suggested name is 'PAUSED'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/MediaPlayer.cs:41  InconsistentNaming  Name 'PlatformOptions_macOS' does not match rule 'members_should_be_pascal_case'. Suggested name is 'PlatformOptionsMacOs'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:34  InconsistentNaming  Name 'Playing' does not match rule 'Enum members'. Suggested name is 'PLAYING'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:18  InconsistentNaming  Name 'Quiet' does not match rule 'Enum members'. Suggested name is 'QUIET'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:33  InconsistentNaming  Name 'Ready' does not match rule 'Enum members'. Suggested name is 'READY'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:11  InconsistentNaming  Name 'RelativeToDataFolder' does not match rule 'Enum members'. Suggested name is 'RELATIVE_TO_DATA_FOLDER'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:12  InconsistentNaming  Name 'RelativeToPersistentDataFolder' does not match rule 'Enum members'. Suggested name is 'RELATIVE_TO_PERSISTENT_DATA_FOLDER'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:9  InconsistentNaming  Name 'RelativeToProjectFolder' does not match rule 'Enum members'. Suggested name is 'RELATIVE_TO_PROJECT_FOLDER'.
Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs:10  InconsistentNaming  Name 'RelativeToStreamingAssetsFolder' does not match rule 'Enum members'. Suggested name is 'RELATIVE_TO_STREAMING_ASSETS_FOLDER'.
Assets/Plugins/UUAV/Packages/UUAV/Runtime/NativeMethods.cs:232  InconsistentNaming  Name 'ResultFFI' does not match rule 'members_should_be_pascal_case'. Suggested name is 'ResultFfi'.

…and 65 more (see the csharp-lint-reports artifact).

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Tests: 24314 passed, 2 failed

Failed tests (2)
  • [editmode] DCL.Tests.CodeConventionsTests.VerifyShouldNotUseApplicationQuitting
  • [editmode] DCL.Tests.Editor.ValidationTests.CheckForDebugUsage

NickKhalow and others added 2 commits July 24, 2026 13:45
…uuav

Resolved asmdef conflicts by unioning references: kept UUAV.AVProCompat
(branch) and added DCL.McpServer (dev) in DCL.Plugins and DCL.EditMode.Tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@NickKhalow
NickKhalow marked this pull request as ready for review July 24, 2026 11:21
@NickKhalow
NickKhalow requested review from a team as code owners July 24, 2026 11:21
@github-actions
github-actions Bot requested review from DafGreco, dalkia and popuz July 24, 2026 11:21
@decentraland-bot
decentraland-bot self-requested a review July 24, 2026 11:21
@claude

This comment has been minimized.

@decentraland-bot decentraland-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: feat: migrate video playback from AVPro to UUAV

STEP 2 — Root-cause check

This PR replaces a commercial video playback dependency (AVPro Video Ultra) with an embedded FFmpeg-based Rust/C# plugin (UUAV). This is a deliberate component swap, not a bug fix. The migration strategy — providing an AVProCompat facade in the same RenderHeads.Media.AVProVideo namespace so existing consumers compile unchanged — is a sound approach that minimizes integration risk.

Verdict: PASS — the change addresses a dependency swap at its root.

STEP 3 — Design & integration

Architecture: The UUAV plugin is structured in three layers:

  1. Native (Rust) — FFmpeg 8 demux/decode, D3D11VA/Metal HW accel, audio ring buffer. Ships as prebuilt uuav.dll/libuuav.dylib via LFS.
  2. Runtime (C#)UUAVPlayer (MonoBehaviour), UUAVRuntime (static lifecycle), NativeMethods (P/Invoke). Standalone, no DCL dependency.
  3. AVProCompat (C#) — Thin facade (MediaPlayer, IMediaControl, ITextureProducer, etc.) in RenderHeads.Media.AVProVideo namespace so DCL's MediaStream systems compile without changes.

Owner search: The MediaStream lifecycle is owned by MediaPlayerPluginWrapper (injection), MediaPlayerCustomPool (creation/pooling), and per-scene ECS systems (CreateMediaPlayerSystem, UpdateMediaPlayerSystem, CleanUpMediaPlayerSystem). The UUAV plugin does NOT duplicate these lifecycle owners — it replaces the underlying engine behind the same facade. The existing create/pool/release/cleanup paths remain unchanged.

Extension method compatibility verified: MediaPlayerExtensions.cs defines CloseCurrentStream, CrossfadeVolume, UpdatePlayback, UpdatePlaybackProperties as extension methods on MediaPlayer. All call only properties/methods that exist on the compat MediaPlayer (Stop(), CloseMedia(), Events, AudioVolume, MediaOpened, Control). Confirmed compatible.

Security review: Protocol whitelist (UNTRUSTED_STREAMING_PROTOCOLS) correctly restricts untrusted scene URLs to streaming protocols (https,http,tls,tcp,...). file: protocol is only added in UNITY_EDITOR builds. No credentials, secrets, or hardcoded tokens found. FFI boundary uses proper marshaling and string cleanup via uuav_string_free. No security issues identified.

STEP 5 — Line-level findings

See inline comments below for all findings with suggestion blocks.

Summary of findings:

# Severity File Issue
1 P1 DCL.Plugins.asmdef AV_PRO_PRESENT define likely not activated — package not registered with UPM
2 P2 UUAVBackend.cs Stop() only pauses, does not seek to 0 (diverges from AVPro semantics)
3 P2 MediaPlayer.cs Same Stop() issue on the compat MonoBehaviour
4 P2 UUAVPlayer.cs #region AI generated with TODO "recheck carefully" should not ship
5 P2 UUAVPlayer.cs Redundant P/Invoke uuav_player_state() calls in Update() — cache once
6 P2 package.json TODO placeholder values in description and keywords
7 P2 Enums.cs Typos in comment: "Effectivly" → "Effectively", "compatabilitty" → "compatibility"

STEP 6 — Complexity assessment

COMPLEX — Introduces an embedded native Rust/FFmpeg plugin with C# FFI bindings (P/Invoke, render-thread callbacks via GL.IssuePluginEvent, audio-thread callbacks via OnAudioFilterRead), an AVPro API compatibility layer, and modifies assembly definitions, package references, and the media playback pipeline.

STEP 7 — QA assessment

QA_REQUIRED: YES — This changes the entire video/audio playback engine. User-visible media playback (video screens, audio streams in scenes) must be tested on Windows. Audio sync, seeking, looping, pooling (scene transitions), and error handling all need manual verification.

STEP 8 — Non-blocking warnings

No warnings (Main scene not modified).

STEP 9 — Verdict

REVIEW_RESULT: FAIL ❌
COMPLEXITY: COMPLEX
COMPLEXITY_REASON: Introduces an embedded native Rust/FFmpeg plugin with C# P/Invoke bindings, AVPro API compat layer, audio/render thread callbacks, and modifies assembly definitions and package references across the media playback pipeline.
QA_REQUIRED: YES


Reviewed by Jarvis 🤖 · Requested by decentraland-bot via GitHub

},
{
"name": "com.renderheads.avpro.video-ultra",
"name": "com.nickkhalow.uuav",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] AV_PRO_PRESENT scripting define likely not activated. The versionDefines entry maps com.nickkhalow.uuavAV_PRO_PRESENT, but this package is not registered with Unity Package Manager — it is not listed in the project's root Explorer/Packages/manifest.json, nor is it embedded in the Packages/ directory. It lives in Assets/Plugins/UUAV/Packages/UUAV/ which Unity treats as regular project assets, NOT as an installed UPM package.

Without AV_PRO_PRESENT, all MediaStream systems are compiled out (#if AV_PRO_PRESENT in MediaPlayerPluginWrapper.InjectToWorld), silently disabling video playback in builds. The CI build/tests would pass since the gated code simply doesn't exist.

The PR description mentions adding AV_PRO_PRESENT to ProjectSettings scripting defines, but that change is not present in this diff.

Fix (choose one):

  1. Add "com.nickkhalow.uuav": "file:../Assets/Plugins/UUAV/Packages/UUAV" to Explorer/Packages/manifest.json so UPM discovers the package and the versionDefines triggers, OR
  2. Add AV_PRO_PRESENT to the Standalone scripting defines in ProjectSettings/ProjectSettings.asset, OR
  3. Move the UUAV package into Explorer/Packages/com.nickkhalow.uuav/ (standard embedded package location)

Please verify by checking the Console for the [MediaPlayerPluginWrapper] Inject log message after applying the fix — if you see Ignore Inject instead, the define is not active.

Comment thread Explorer/Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/UUAVBackend.cs Outdated
Comment thread Explorer/Assets/Plugins/UUAV/Packages/UUAV/Runtime/UUAVPlayer.cs Outdated
Comment thread Explorer/Assets/Plugins/UUAV/Packages/UUAV/Runtime/UUAVPlayer.cs
Comment thread Explorer/Assets/Plugins/UUAV/Packages/UUAV/package.json Outdated
Comment thread Explorer/Assets/Plugins/UUAV/Packages/UUAV/AVProCompat/Enums.cs Outdated
@claude

claude Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Security-Focused Dependency Review — PR #9463 (AVPro → UUAV) · re-run on synchronize

  • Re-inventory dependency & binary changes (PR updated since last review)
  • Re-check manifest / asmdef / AV_PRO_PRESENT gating
  • Re-check native binaries: LFS consistency, provenance, integrity
  • Re-check C# binding & compat layer (protocol whitelist, interop)
  • Classify risk & write verdict

View job run

NickKhalow and others added 3 commits July 24, 2026 14:45
Co-authored-by: Muna <44584806+decentraland-bot@users.noreply.github.com>
Signed-off-by: Nick Khalow <71646502+NickKhalow@users.noreply.github.com>
Co-authored-by: Muna <44584806+decentraland-bot@users.noreply.github.com>
Signed-off-by: Nick Khalow <71646502+NickKhalow@users.noreply.github.com>
@claude

claude Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Claude Code is working…

I'll analyze this and get back to you.

View job run

@claude

This comment has been minimized.

@claude

This comment has been minimized.

@claude

claude Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Claude finished @NickKhalow's task in 3m 2s —— View job


Security-Focused Dependency Review — PR #9463 (AVPro → UUAV) · re-run on synchronize

  • Re-inventory dependency & binary changes
  • Re-check AV_PRO_PRESENT gating (new "define fix" commits)
  • Re-check native binaries: LFS consistency, provenance, integrity
  • Re-check C# binding & compat layer (protocol whitelist, interop)
  • Classify risk & write verdict

Re-reviewed against the current tip (5c903fc12). Supply-chain posture unchanged and good. The two new commits since my last pass resolve the frameTimeBudget NRE blocker I flagged — but the way they did it leaves AV_PRO_PRESENT as a dead define, which silently disables a feature and all media tests.

✅ Fixed this round (verified on branch)

  • frameTimeBudget NRE risk — resolved. 5c903fc12 changed the field-init guard in MediaPlayerPluginWrapper.cs:46 from #if AV_PRO_PRESENT && !…LINUX to just #if !…LINUX, matching the InjectToWorld guard (:54). frameTimeBudget is now assigned on exactly the platforms where injection runs → no null at runtime.
  • AV_PRO_PRESENT versionDefine removed cleanly. The stale com.renderheads.avpro.video-ultra → AV_PRO_PRESENT entry is gone from DCL.Plugins.asmdef, and the compat assembly (UUAV.AVProCompat, GUID 4a0b2c8f…) is now referenced directly by ECS.Unity, DCL.Plugins, and DCL.EditMode.Tests. The runtime media path no longer depends on the define to compile — the earlier "systems compiled out" blocker is gone.

🟡 Non-blocking correctness — AV_PRO_PRESENT is now an orphan define (13 stale references)

The define is now set nowhere (removed from the asmdef, never added to ProjectSettings/manifest), but 13 #if AV_PRO_PRESENT sites remain and are permanently dead:

  • MediaPlayerPlugin.cs:53#if AV_PRO_PRESENT && !…LINUX guards placeholderSource = new AvatarPlaceHolderTextureSource(…). Now always false → placeholderSource stays null on every platform. It's null-safe by design (nullable field, ?.Dispose(), MediaFactory accepts null), so no crash — but the "camera-off placeholder texture" feature is silently disabled. Confirm that's intended.
  • 12 MediaStream test files (Tests/*Should.cs) open with #if AV_PRO_PRESENT → the entire migrated media path now has zero compiled test coverage.

Not a security issue and not a crash. But since the define is intentionally dead now, either drop the stale #if AV_PRO_PRESENT guards (and re-gate the tests on the compat assembly) or re-introduce the define — otherwise the placeholder feature and media tests are quietly off. Fix this →

Dependency inventory (confirmed on current branch)

Dependency / file Version Source Type Scope Risk Confidence
com.renderheads.avpro.video-ultra (removed) git (internal) managed+native runtime HIGH
uuav.dll / libuuav.dylib crate 0.x vendored Rust src (native/src) native binary runtime MEDIUM HIGH
12× FFmpeg Windows DLLs FFmpeg 8 (BtbN LGPL) prebuilt drop native binary runtime MEDIUM HIGH
8× FFmpeg macOS dylibs FFmpeg 8 (src build) prebuilt drop native binary runtime MEDIUM HIGH
Rust crate deps (ffmpeg-sys-next, windows, objc2*, dashmap, parking_lot, ringbuf, …) pinned via Cargo.lock crates.io source (transitive) build LOW MEDIUM

Positive controls — all still hold (re-verified):

  • ✅ Full native source vendored (native/src/*.rs) + Cargo.lock + Cargo.toml committed — reviewable/rebuildable.
  • No custom network/process primitives in Rust source — re-grepped native/src for reqwest/hyper/TcpStream/std::net/std::process/Command::new/libc::system/tokio::net0 hits. Network I/O goes only through FFmpeg's whitelisted protocol layer.
  • SSRF / local-file hardening intactUUAVRuntime.cs:15 UNTRUSTED_STREAMING_PROTOCOLS = "https,http,tls,tcp,crypto,data,udp,rtp,rtcp,rtsp"; file: appended only under #if UNITY_EDITOR (:73-77); concat/subfile deliberately omitted (comment :14).
  • ✅ macOS refuses to init on any non-Metal graphics API (UUAVRuntime.cs:58-64).
  • ✅ No auto-run install/build hooks; only editor auto-run is benign [RuntimeInitializeOnLoadMethod] init + Application.quitting teardown.

MEDIUM-risk items (human sign-off, unchanged)

M1 — FFmpeg binaries have no committed integrity attestation. Re-grepped both READMEs and native/scripts for sha256/checksum/gpg/signaturenone. FFmpeg decodes untrusted scene URLs in the shipped client. → commit upstream SHA-256s or verify in CI; name an owner for FFmpeg security bumps.

M2 — uuav.dll/libuuav.dylib not verifiably built from the vendored source. Nothing ties the committed binaries to the committed native/src. → build in CI from source, or document toolchain + producer.

M3 — LFS inconsistency persists (confirmed on disk). .gitattributes:16 has *.dll filter=lfs but no *.dylib rule. Verified via git cat-file -s: uuav.dll blob = 132 B (LFS pointer), but libuuav.dylib = 803 KB and libavcodec.62.dylib = ~13 MB stored raw in history. All 8 macOS dylibs bloat the repo permanently. → add *.dylib filter=lfs diff=lfs merge=lfs -text and migrate.

M4 — http/udp/rtp/rtsp enabled for untrusted URLs. Same SSRF reachability AVPro had (not a regression). → drop http/rtsp/udp if scenes only use HLS/DASH-over-HTTPS, or record as accepted risk.

Other non-security notes (from CI, unchanged)

  • Convention tests still failing: UUAVRuntime.cs:67 uses Application.quitting (VerifyShouldNotUseApplicationQuitting) and UUAV uses Debug.Log* vs ReportHub (CheckForDebugUsage). → allowlist the vendored UUAV assemblies in the convention tests, or route through ReportHub.
  • InconsistentNaming warning set on the vendored UUAV enums remains (cosmetic; vendored code).

Verdict

The frameTimeBudget NRE blocker from my last pass is fixed; the residual AV_PRO_PRESENT orphan-define issue is a non-blocking correctness/coverage concern (null-safe, no crash). Supply-chain custom-code provenance is good. Residual supply-chain gaps — M1 FFmpeg integrity, M2 unverifiable native artifacts, M3 LFS .dylib inconsistency — still need human sign-off; none is a clear high-severity exploit.

DEPENDENCY_REVIEW: NEEDS_ATTENTION
· feat/migrate-avpro-to-uuav

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

force-build Used to trigger a build on draft PR new-dependency

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants