@@ -52,10 +52,14 @@ class SharedVideoPlayer {
5252 private var frameBuffer : UnsafeMutablePointer < UInt32 > ?
5353 private var bufferCapacity : Int = 0
5454
55- // Frame dimensions
55+ // Frame dimensions (actual decoded pixel buffer size)
5656 private var frameWidth : Int = 0
5757 private var frameHeight : Int = 0
5858
59+ // Display dimensions (intended presentation size from naturalSize)
60+ private var displayWidth : Int = 0
61+ private var displayHeight : Int = 0
62+
5963 // Audio volume control (0.0 to 1.0)
6064 private var volume : Float = 1.0
6165
@@ -447,6 +451,8 @@ class SharedVideoPlayer {
447451 )
448452 // For HLS streams without video track info yet, use default dimensions
449453 if isHLSStream {
454+ displayWidth = 1920
455+ displayHeight = 1080
450456 frameWidth = 1920
451457 frameHeight = 1080
452458 setupFrameBuffer ( )
@@ -464,8 +470,10 @@ class SharedVideoPlayer {
464470 let transform = try await videoTrack. load ( . preferredTransform)
465471
466472 let effectiveSize = naturalSize. applying ( transform)
467- self . frameWidth = Int ( abs ( effectiveSize. width) )
468- self . frameHeight = Int ( abs ( effectiveSize. height) )
473+ self . displayWidth = Int ( abs ( effectiveSize. width) )
474+ self . displayHeight = Int ( abs ( effectiveSize. height) )
475+ self . frameWidth = self . displayWidth
476+ self . frameHeight = self . displayHeight
469477
470478 // Continue with buffer allocation and setup
471479 self . setupFrameBuffer ( )
@@ -474,6 +482,8 @@ class SharedVideoPlayer {
474482 print ( " Error loading video track properties: \( error. localizedDescription) " )
475483 // Use default dimensions for HLS if loading fails
476484 if self . isHLSStream {
485+ self . displayWidth = 1920
486+ self . displayHeight = 1080
477487 self . frameWidth = 1920
478488 self . frameHeight = 1080
479489 self . setupFrameBuffer ( )
@@ -487,8 +497,10 @@ class SharedVideoPlayer {
487497 let transform = videoTrack. preferredTransform
488498
489499 let effectiveSize = naturalSize. applying ( transform)
490- frameWidth = Int ( abs ( effectiveSize. width) )
491- frameHeight = Int ( abs ( effectiveSize. height) )
500+ displayWidth = Int ( abs ( effectiveSize. width) )
501+ displayHeight = Int ( abs ( effectiveSize. height) )
502+ frameWidth = displayWidth
503+ frameHeight = displayHeight
492504
493505 // Continue with buffer allocation and setup
494506 setupFrameBuffer ( )
@@ -516,8 +528,6 @@ class SharedVideoPlayer {
516528 // Create attributes for the CVPixelBuffer (BGRA format) with IOSurface for better performance
517529 let pixelBufferAttributes : [ String : Any ] = [
518530 kCVPixelBufferPixelFormatTypeKey as String : kCVPixelFormatType_32BGRA,
519- kCVPixelBufferWidthKey as String : frameWidth,
520- kCVPixelBufferHeightKey as String : frameHeight,
521531 kCVPixelBufferIOSurfacePropertiesKey as String : [ : ] ,
522532 ]
523533 videoOutput = AVPlayerItemVideoOutput ( pixelBufferAttributes: pixelBufferAttributes)
@@ -638,20 +648,15 @@ class SharedVideoPlayer {
638648 let height = CVPixelBufferGetHeight ( pixelBuffer)
639649 let srcBytesPerRow = CVPixelBufferGetBytesPerRow ( pixelBuffer)
640650
641- // For HLS, dimensions might change dynamically
642- if isHLSStream && ( width != frameWidth || height != frameHeight) {
643- print ( " HLS: Resolution changed from \( frameWidth) x \( frameHeight) to \( width) x \( height) " )
651+ // Adapt to actual decoded frame dimensions (handles letterboxing, HLS resolution changes, etc.)
652+ if width != frameWidth || height != frameHeight {
653+ print ( " Resolution adapted from \( frameWidth) x \( frameHeight) to \( width) x \( height) " )
644654 frameWidth = width
645655 frameHeight = height
646656 setupFrameBuffer ( )
647657 guard frameBuffer != nil else { return }
648658 }
649659
650- guard width == frameWidth, height == frameHeight else {
651- print ( " Unexpected dimensions: \( width) x \( height) " )
652- return
653- }
654-
655660 if srcBytesPerRow == width * 4 {
656661 memcpy ( destBuffer, srcBaseAddress, height * srcBytesPerRow)
657662 } else {
@@ -711,6 +716,12 @@ class SharedVideoPlayer {
711716 /// Returns the height of the video frame in pixels
712717 func getFrameHeight( ) -> Int { return frameHeight }
713718
719+ /// Returns the intended display width (from naturalSize)
720+ func getDisplayWidth( ) -> Int { return displayWidth }
721+
722+ /// Returns the intended display height (from naturalSize)
723+ func getDisplayHeight( ) -> Int { return displayHeight }
724+
714725 /// Returns the duration of the video in seconds.
715726 func getDuration( ) -> Double {
716727 guard let item = player? . currentItem else { return 0 }
@@ -953,6 +964,20 @@ public func getFrameHeight(_ context: UnsafeMutableRawPointer?) -> Int32 {
953964 return Int32 ( player. getFrameHeight ( ) )
954965}
955966
967+ @_cdecl ( " getDisplayWidth " )
968+ public func getDisplayWidth( _ context: UnsafeMutableRawPointer ? ) -> Int32 {
969+ guard let context = context else { return 0 }
970+ let player = Unmanaged < SharedVideoPlayer > . fromOpaque ( context) . takeUnretainedValue ( )
971+ return Int32 ( player. getDisplayWidth ( ) )
972+ }
973+
974+ @_cdecl ( " getDisplayHeight " )
975+ public func getDisplayHeight( _ context: UnsafeMutableRawPointer ? ) -> Int32 {
976+ guard let context = context else { return 0 }
977+ let player = Unmanaged < SharedVideoPlayer > . fromOpaque ( context) . takeUnretainedValue ( )
978+ return Int32 ( player. getDisplayHeight ( ) )
979+ }
980+
956981@_cdecl ( " getVideoDuration " )
957982public func getVideoDuration( _ context: UnsafeMutableRawPointer ? ) -> Double {
958983 guard let context = context else { return 0 }
0 commit comments