diff --git a/CHANGELOG.md b/CHANGELOG.md index 80f9dd14..3cbf6622 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Fixed + +- SideloadedSubtitle + - Fixed a data race that could crash with `EXC_BAD_ACCESS` when playing a stream with side-loaded text tracks, caused by concurrent mutation of the internal request/subtitle collections from the playlist interception callbacks. + ## [11.0.4] - 2026-05-29 ### Changed diff --git a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/AVSubtitlesLoader.swift b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/AVSubtitlesLoader.swift index 6ae35533..92f09345 100644 --- a/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/AVSubtitlesLoader.swift +++ b/Code/Sideloaded-TextTracks/Sources/THEOplayerConnectorSideloadedSubtitle/AVSubtitlesLoader.swift @@ -17,12 +17,23 @@ class AVSubtitlesLoader: NSObject { } private let _subtitles: [TextTrackDescription] - private var subtitles: [TextTrackDescription] = [] private let transformer = SubtitlesTransformer() private let synchronizer: SubtitlesSynchronizer? private let _id: String private var variantTotalDuration: Double = 0 - private var requestMap: [URL: URLRequest] = [:] + + private let subtitlesLock = NSLock() + private var subtitlesStorage: [TextTrackDescription] = [] + private var subtitles: [TextTrackDescription] { + get { self.subtitlesLock.lock(); defer { self.subtitlesLock.unlock() }; return self.subtitlesStorage } + set { self.subtitlesLock.lock(); defer { self.subtitlesLock.unlock() }; self.subtitlesStorage = newValue } + } + private let requestMapLock = NSLock() + private var requestMapStorage: [URL: URLRequest] = [:] + private var requestMap: [URL: URLRequest] { + get { self.requestMapLock.lock(); defer { self.requestMapLock.unlock() }; return self.requestMapStorage } + set { self.requestMapLock.lock(); defer { self.requestMapLock.unlock() }; self.requestMapStorage = newValue } + } init(subtitles: [TextTrackDescription], id: String, player: THEOplayer? = nil) { self._subtitles = subtitles