video_player + insets: native playback backend + animated viewPadding
- video_player: ExoPlayer (Android) / AVPlayer (iOS/macOS) backend with PixelBufferSink, method-channel adapter, Dart-side XVideoPlayer + testing fake. - insets: XInsets singleton + XAnimatedInsets widget lerp the system viewPadding over 220ms so OS bar visibility toggles (immersiveSticky <-> edgeToEdge) slide bottom-/top-anchored UI into place instead of snapping by the nav-bar / status-bar height.
This commit is contained in:
55
ios/Classes/Video-shared/VideoPixelBufferSink.swift
Normal file
55
ios/Classes/Video-shared/VideoPixelBufferSink.swift
Normal file
@@ -0,0 +1,55 @@
|
||||
import CoreVideo
|
||||
import Foundation
|
||||
#if canImport(UIKit)
|
||||
import Flutter
|
||||
#else
|
||||
import FlutterMacOS
|
||||
#endif
|
||||
|
||||
/// Single-slot latest-pixel-buffer sink that feeds a `FlutterTexture`.
|
||||
/// Mirrors `PreviewSink` in `darwin/Camera/` — receiver writes, the
|
||||
/// engine reads via `copyPixelBuffer()`. We retain only the most
|
||||
/// recent buffer; older ones get released the moment a new frame
|
||||
/// arrives, bounding memory at one frame.
|
||||
final class UxVideoPixelBufferSink: NSObject, FlutterTexture {
|
||||
private weak var registry: FlutterTextureRegistry?
|
||||
private var textureId: Int64 = -1
|
||||
|
||||
private let bufferQueue = DispatchQueue(
|
||||
label: "ux.video.buffer",
|
||||
qos: .userInitiated
|
||||
)
|
||||
private var latestPixelBuffer: CVPixelBuffer?
|
||||
|
||||
func register(with registry: FlutterTextureRegistry) -> Int64 {
|
||||
self.registry = registry
|
||||
textureId = registry.register(self)
|
||||
return textureId
|
||||
}
|
||||
|
||||
func unregister() {
|
||||
registry?.unregisterTexture(textureId)
|
||||
bufferQueue.sync { latestPixelBuffer = nil }
|
||||
}
|
||||
|
||||
// MARK: - FlutterTexture
|
||||
|
||||
func copyPixelBuffer() -> Unmanaged<CVPixelBuffer>? {
|
||||
var pb: CVPixelBuffer?
|
||||
bufferQueue.sync {
|
||||
pb = latestPixelBuffer
|
||||
latestPixelBuffer = nil
|
||||
}
|
||||
if let pb = pb { return Unmanaged.passRetained(pb) }
|
||||
return nil
|
||||
}
|
||||
|
||||
/// Receives a new frame from the AVPlayerItemVideoOutput pump.
|
||||
/// Cheap — just swaps the pointer + notifies the registry.
|
||||
func deliver(pixelBuffer: CVPixelBuffer) {
|
||||
bufferQueue.sync { latestPixelBuffer = pixelBuffer }
|
||||
if let registry = registry {
|
||||
registry.textureFrameAvailable(textureId)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user