@@ -91,10 +91,12 @@ public final class ChunkMediaPlayerV2: ChunkMediaPlayer {
9191 private let renderSynchronizer : AVSampleBufferRenderSynchronizer
9292 private var videoRenderer : AVSampleBufferDisplayLayer
9393 private var audioRenderer : AVSampleBufferAudioRenderer ?
94+ private weak var videoNode : MediaPlayerNode ?
9495
9596 private var partsState = ChunkMediaPlayerPartsState ( duration: nil , parts: [ ] )
9697 private var loadedParts : [ LoadedPart ] = [ ]
9798 private var loadedPartsMediaData : QueueLocalObject < LoadedPartsMediaData >
99+ private var reportedDidEnqueueVideo : Bool = false
98100 private var hasSound : Bool = false
99101
100102 private var statusValue : MediaPlayerStatus ? {
@@ -173,6 +175,7 @@ public final class ChunkMediaPlayerV2: ChunkMediaPlayer {
173175 assertionFailure ( )
174176 }
175177 self . videoRenderer = playerNode. videoLayer ?? AVSampleBufferDisplayLayer ( )
178+ self . videoNode = playerNode
176179
177180 self . updateTimer = Foundation . Timer. scheduledTimer ( withTimeInterval: 1.0 / 60.0 , repeats: true , block: { [ weak self] _ in
178181 guard let self else {
@@ -677,8 +680,8 @@ public final class ChunkMediaPlayerV2: ChunkMediaPlayer {
677680
678681 videoTarget. requestMediaDataWhenReady ( on: self . dataQueue. queue, using: { [ weak self] in
679682 if let loadedPartsMediaData = loadedPartsMediaData. unsafeGet ( ) {
680- let bufferIsReadyForMoreData = ChunkMediaPlayerV2 . fillRendererBuffer ( bufferTarget: videoTarget, loadedPartsMediaData: loadedPartsMediaData, isVideo: true )
681- if bufferIsReadyForMoreData {
683+ let fillResult = ChunkMediaPlayerV2 . fillRendererBuffer ( bufferTarget: videoTarget, loadedPartsMediaData: loadedPartsMediaData, isVideo: true )
684+ if fillResult . isReadyForMoreData {
682685 videoTarget. stopRequestingMediaData ( )
683686 Queue . mainQueue ( ) . async {
684687 guard let self else {
@@ -695,11 +698,12 @@ public final class ChunkMediaPlayerV2: ChunkMediaPlayer {
695698 if !self . audioIsRequestingMediaData, let audioRenderer = self . audioRenderer {
696699 self . audioIsRequestingMediaData = true
697700 let loadedPartsMediaData = self . loadedPartsMediaData
701+ let reportedDidEnqueueVideo = self . reportedDidEnqueueVideo
698702 let audioTarget = audioRenderer
699703 audioTarget. requestMediaDataWhenReady ( on: self . dataQueue. queue, using: { [ weak self] in
700704 if let loadedPartsMediaData = loadedPartsMediaData. unsafeGet ( ) {
701- let bufferIsReadyForMoreData = ChunkMediaPlayerV2 . fillRendererBuffer ( bufferTarget: audioTarget, loadedPartsMediaData: loadedPartsMediaData, isVideo: false )
702- if bufferIsReadyForMoreData {
705+ let fillResult = ChunkMediaPlayerV2 . fillRendererBuffer ( bufferTarget: audioTarget, loadedPartsMediaData: loadedPartsMediaData, isVideo: false )
706+ if fillResult . isReadyForMoreData {
703707 audioTarget. stopRequestingMediaData ( )
704708 Queue . mainQueue ( ) . async {
705709 guard let self else {
@@ -709,13 +713,28 @@ public final class ChunkMediaPlayerV2: ChunkMediaPlayer {
709713 self . updateInternalState ( )
710714 }
711715 }
716+ if fillResult. didEnqueue && !reportedDidEnqueueVideo {
717+ Queue . mainQueue ( ) . async {
718+ guard let self else {
719+ return
720+ }
721+ self . reportedDidEnqueueVideo = true
722+ if #available( iOS 17 . 4 , * ) {
723+ } else {
724+ if let videoNode = self . videoNode {
725+ videoNode. notifyHasSentFramesToDisplay ( )
726+ }
727+ }
728+ }
729+ }
712730 }
713731 } )
714732 }
715733 }
716734
717- private static func fillRendererBuffer( bufferTarget: AVQueuedSampleBufferRendering , loadedPartsMediaData: LoadedPartsMediaData , isVideo: Bool ) -> Bool {
735+ private static func fillRendererBuffer( bufferTarget: AVQueuedSampleBufferRendering , loadedPartsMediaData: LoadedPartsMediaData , isVideo: Bool ) -> ( isReadyForMoreData : Bool , didEnqueue : Bool ) {
718736 var bufferIsReadyForMoreData = true
737+ var didEnqeue = false
719738 outer: while true {
720739 if !bufferTarget. isReadyForMoreMediaData {
721740 bufferIsReadyForMoreData = false
@@ -755,9 +774,7 @@ public final class ChunkMediaPlayerV2: ChunkMediaPlayer {
755774 continue outer
756775 }
757776 }
758- /*if isVideo {
759- print("Enqueue \(isVideo ? "video" : "audio") at \(CMSampleBufferGetPresentationTimeStamp(sampleBuffer).seconds) \(CMSampleBufferGetPresentationTimeStamp(sampleBuffer).value)/\(CMSampleBufferGetPresentationTimeStamp(sampleBuffer).timescale) next \(CMSampleBufferGetPresentationTimeStamp(sampleBuffer).value + CMSampleBufferGetDuration(sampleBuffer).value)")
760- }*/
777+ didEnqeue = true
761778 bufferTarget. enqueue ( sampleBuffer)
762779 hasData = true
763780 continue outer
@@ -770,7 +787,7 @@ public final class ChunkMediaPlayerV2: ChunkMediaPlayer {
770787 }
771788 }
772789
773- return bufferIsReadyForMoreData
790+ return ( bufferIsReadyForMoreData, didEnqeue )
774791 }
775792}
776793
0 commit comments