Migrate macOS player from JNA to JNI with output scaling and performance improvements#184
Merged
kdroidFilter merged 3 commits intoApr 10, 2026
Merged
Conversation
…rovements - Replace JNA native bridge with a C JNI bridge (jni_bridge.c) and JNI_OnLoad registration - Load libNativeVideoPlayer.dylib via System.load() from bundled resources - Add setOutputSize() to Swift layer: recreates AVPlayerItemVideoOutput at display size, reducing memory usage for high-resolution video (never upscales) - Track surface dimensions via onSizeChanged in MacVideoPlayerSurface; debounce resize events before applying output scaling to the native layer - Move timeControlStatus KVO observer from HLS-only path to cover all media types - Replace Mutex-based frame serialization with limitedParallelism(1) dispatcher - Remove redundant frame hash computation — serial dispatcher already prevents duplicate work - Fix checkExistsIfLocalFile to use File() directly instead of URI.create(), supporting paths with spaces and non-ASCII characters - Update build.sh to compile jni_bridge.c with JNI headers and link into the dylib
…k callback - Replace Kotlin Mutex + var playerPtr with AtomicLong: removes lock overhead from every JNI call in the frame hot path; cleanup uses getAndSet(0L), initialization uses compareAndSet to safely handle concurrent calls - Add AVPlayerItemDidPlayToEndTime observer in Swift (all media types, not just HLS): sets a didPlayToEnd flag consumed once via nConsumeDidPlayToEnd() JNI call - Replace the fragile "current >= duration - 0.5" position check in checkLoopingAsync with the native end-of-playback callback; keep position check as fallback - Add consumeDidPlayToEnd @_cdecl export, jni_ConsumeDidPlayToEnd in jni_bridge.c, and nConsumeDidPlayToEnd external declaration in AvPlayerLib.kt
Refactor player state handling and JNI bridge implementation across Kotlin, Swift, and C layers for improved maintainability.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
jni_bridge.c) that usesJNI_OnLoad/RegisterNativesto bind Swift@_cdeclexports to Kotlinexternaldeclarations; library is loaded viaSystem.load()from bundled resourcessetOutputSize()in Swift — recreatesAVPlayerItemVideoOutputat the display surface dimensions, significantly reducing memory for high-resolution (4K+) video by decoding at render size instead of native resolution;MacVideoPlayerSurfacereports its size viaonSizeChangedwith a 120 ms debouncetimeControlStatusobserver from the HLS-only path (setupHLSMonitoring) tosetupVideoOutputAndPlayerso it covers all media types, not just HLS streamsMutex-based frame serialization withDispatchers.Default.limitedParallelism(1)— more idiomatic and removes the need forwithLockin hot pathscheckExistsIfLocalFilenow usesFile()directly instead ofURI.create(), supporting paths with spaces and non-ASCII characters (e.g. accented filenames)build.shto compilejni_bridge.cwith JNI headers (-I${JAVA_HOME}/include) and link the resulting.ointo the dylib alongside the Swift sourceTest plan
mediaplayer/src/jvmMain/native/macos/build.shand confirmlibNativeVideoPlayer.dylibbuilds for botharm64andx86_64isPlaying/isLoadingstate transitions correctly (KVO fix)