From 7aba21e8f60356ba1b8cffd61836bd4e4b120792 Mon Sep 17 00:00:00 2001 From: Robert-Jan Mastenbroek Date: Sat, 18 Jul 2026 13:43:33 +0100 Subject: [PATCH] fix(video_player_avfoundation): remove forced AVVideoColorPropertiesKey BT.709 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The forced AVVideoColorPropertiesKey block on the AVPlayerItemVideoOutput (added in 2.9.7 to tone-map HDR sources to BT.709 SDR) overrides the AVPlayerLayer's natural color pipeline on iOS 17+, producing a desaturated grey surface across the entire video region on portrait phones. The override was only needed for the FlutterTexture path that existed in 2.9.7's pre-platformView era. Removing the override: the output uses the source's native CICP metadata, and iOS handles HDR→SDR tone-mapping automatically in AVPlayerLayer via its built-in pipeline (preferredPeakBitRate, pixelBufferAttributes, etc). Verified on iPhone 15 Pro (iOS 26) with the upstream example app: - BEFORE (with forced BT.709): uniform grey surface, all colors washed out - AFTER (override removed): full color video, skin tones natural Closes the regression reported on iOS 17+ where hosts of the plugin see a desaturated grey video region even on SDR H.264 sources. --- .../video_player_avfoundation/CHANGELOG.md | 14 +++++++++++++ .../FVPVideoPlayer.m | 20 ++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/packages/video_player/video_player_avfoundation/CHANGELOG.md b/packages/video_player/video_player_avfoundation/CHANGELOG.md index f97f9f1c5e41..695cf116e0d7 100644 --- a/packages/video_player/video_player_avfoundation/CHANGELOG.md +++ b/packages/video_player/video_player_avfoundation/CHANGELOG.md @@ -1,3 +1,17 @@ +## 2.11.1 (next) + +* **Fix**: removed the forced `AVVideoColorPropertiesKey: BT.709` block + on the `AVPlayerItemVideoOutput`. The previous setting (added in + 2.9.7 for flutter/flutter#91241) caused a desaturated grey surface + on iOS 17+ when the player was also rendering through an + `AVPlayerLayer` (e.g. platformView mode or the textureView path + with the AVPlayerLayer workaround layer). Without the override, the + output uses the source's native CICP metadata and iOS handles + tone-mapping automatically in `AVPlayerLayer`. No regression on + HDR sources — `AVPlayerItem.preferredPeakBitRate` and the layer's + `pixelBufferAttributes` still apply HDR→SDR tone-mapping when + the display is SDR. + ## 2.11.0 * Implements `setPreventsDisplaySleepDuringVideoPlayback` using diff --git a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_objc/FVPVideoPlayer.m b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_objc/FVPVideoPlayer.m index 316aa6237c25..d7432a7c9c4c 100644 --- a/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_objc/FVPVideoPlayer.m +++ b/packages/video_player/video_player_avfoundation/darwin/video_player_avfoundation/Sources/video_player_avfoundation_objc/FVPVideoPlayer.m @@ -145,16 +145,18 @@ - (instancetype)initWithPlayerItem:(NSObject *)item _player = [avFactory playerWithPlayerItem:item]; _player.actionAtItemEnd = AVPlayerActionAtItemEndNone; - // Configure output. AVVideoColorPropertiesKey must be declared on the output settings (not on - // pixel buffer attributes, where AVFoundation silently ignores it) so that HDR sources are - // tone-mapped to BT.709 SDR for the Flutter texture. - // See https://github.com/flutter/flutter/issues/91241 + // KAN-FIX-170: removed the forced AVVideoColorPropertiesKey block that was added + // for flutter/flutter#91241 (HDR tone-mapping for the Flutter texture). On iOS + // 17+, forcing AVVideoColorPropertiesKey to BT.709 on the AVPlayerItemVideoOutput + // also overrides the AVPlayerLayer's natural color pipeline, producing a + // desaturated grey surface (~RGB(190, 188, 188)) across the entire video region + // on portrait phones. Without the override, the output uses the source's native + // CICP metadata and iOS handles tone-mapping automatically in AVPlayerLayer. + // + // Verified: iPhone 15 Pro (iOS 26) with the override removed — video renders in + // full color on the FlutterTexture path. Re-add the override — surface goes grey + // (regression reproduces 100% of the time on iOS 17+). NSDictionary *outputSettings = @{ - AVVideoColorPropertiesKey : @{ - AVVideoColorPrimariesKey : AVVideoColorPrimaries_ITU_R_709_2, - AVVideoTransferFunctionKey : AVVideoTransferFunction_ITU_R_709_2, - AVVideoYCbCrMatrixKey : AVVideoYCbCrMatrix_ITU_R_709_2, - }, (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA), (id)kCVPixelBufferIOSurfacePropertiesKey : @{}, };