Skip to content

Commit

Permalink
fix #581
Browse files Browse the repository at this point in the history
  • Loading branch information
kingslay committed Oct 13, 2023
1 parent 07ed049 commit 4a3c63d
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 99 deletions.
40 changes: 24 additions & 16 deletions Demo/SwiftUI/Shared/MovieModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
import CoreData
import Foundation
import KSPlayer
#if canImport(UIKit)
import UIKit
#endif
class MEOptions: KSOptions {
static var isUseDisplayLayer = true
override init() {
Expand All @@ -22,28 +25,33 @@ class MEOptions: KSOptions {
videoFilters.append("yadif=mode=0:parity=-1:deint=1")
hardwareDecode = false
}
#if os(tvOS) || os(xrOS)
runInMainqueue { [weak self] in
guard let self else {
return
}
if let displayManager = UIApplication.shared.windows.first?.avDisplayManager,
displayManager.isDisplayCriteriaMatchingEnabled,
!displayManager.isDisplayModeSwitchInProgress
{
let refreshRate = assetTrack.nominalFrameRate
if KSOptions.displayCriteriaFormatDescriptionEnabled, let formatDescription = assetTrack.formatDescription, #available(tvOS 17.0, *) {
displayManager.preferredDisplayCriteria = AVDisplayCriteria(refreshRate: refreshRate, formatDescription: formatDescription)
} else {
if let dynamicRange = assetTrack.dynamicRange {
let videoDynamicRange = self.availableDynamicRange(dynamicRange) ?? dynamicRange
displayManager.preferredDisplayCriteria = AVDisplayCriteria(refreshRate: refreshRate, videoDynamicRange: videoDynamicRange.rawValue)
}
}
}
}
#endif
}
}

override func isUseDisplayLayer() -> Bool {
MEOptions.isUseDisplayLayer && display == .plane
}

#if os(tvOS) || os(xrOS)
override open func preferredDisplayCriteria(track: some MediaPlayerTrack) -> AVDisplayCriteria? {
let refreshRate = track.nominalFrameRate
if KSOptions.displayCriteriaFormatDescriptionEnabled, let formatDescription = track.formatDescription, #available(tvOS 17.0, *) {
return AVDisplayCriteria(refreshRate: refreshRate, formatDescription: formatDescription)
} else {
let videoDynamicRange = track.dynamicRange(self).rawValue
return AVDisplayCriteria(refreshRate: refreshRate, videoDynamicRange: videoDynamicRange)
}
}
#endif
}

extension CodingUserInfoKey {
static let managedObjectContext = CodingUserInfoKey(rawValue: "managedObjectContext")!
}

@objc(MovieModel)
Expand Down
37 changes: 21 additions & 16 deletions Demo/demo-iOS/demo-iOS/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,27 +98,32 @@ class MEOptions: KSOptions {
override func process(assetTrack: some MediaPlayerTrack) {
if assetTrack.mediaType == .video {
if [FFmpegFieldOrder.bb, .bt, .tt, .tb].contains(assetTrack.fieldOrder) {
videoFilters.append("yadif=mode=1:parity=-1:deint=1")
videoFilters.append("yadif=mode=0:parity=-1:deint=1")
hardwareDecode = false
}
}
}

#if os(tvOS) || os(xrOS)
override open func preferredDisplayCriteria(track: some MediaPlayerTrack) -> AVDisplayCriteria? {
let refreshRate = track.nominalFrameRate
if #available(tvOS 17.0, *) {
if let formatDescription = track.formatDescription {
return AVDisplayCriteria(refreshRate: refreshRate, formatDescription: formatDescription)
} else {
return nil
#if os(tvOS) || os(xrOS)
runInMainqueue { [weak self] in
guard let self else {
return
}
if let displayManager = UIApplication.shared.windows.first?.avDisplayManager,
displayManager.isDisplayCriteriaMatchingEnabled,
!displayManager.isDisplayModeSwitchInProgress
{
let refreshRate = assetTrack.nominalFrameRate
if KSOptions.displayCriteriaFormatDescriptionEnabled, let formatDescription = assetTrack.formatDescription, #available(tvOS 17.0, *) {
displayManager.preferredDisplayCriteria = AVDisplayCriteria(refreshRate: refreshRate, formatDescription: formatDescription)
} else {
if let dynamicRange = assetTrack.dynamicRange {
let videoDynamicRange = self.availableDynamicRange(dynamicRange) ?? dynamicRange
displayManager.preferredDisplayCriteria = AVDisplayCriteria(refreshRate: refreshRate, videoDynamicRange: videoDynamicRange.rawValue)
}
}
}
}
} else {
let videoDynamicRange = track.dynamicRange(self).rawValue
return AVDisplayCriteria(refreshRate: refreshRate, videoDynamicRange: videoDynamicRange)
#endif
}
}
#endif
}

var testObjects: [KSPlayerResource] = {
Expand Down
53 changes: 39 additions & 14 deletions Sources/KSPlayer/AVPlayer/KSOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

import AVFoundation
import OSLog

#if canImport(UIKit)
import UIKit
#endif
open class KSOptions {
/// 最低缓存视频时间
@Published
Expand Down Expand Up @@ -303,22 +305,45 @@ open class KSOptions {
}

/**
在创建解码器之前可以对KSOptions做一些处理。例如判断fieldOrder为tt或bb的话,那就自动加videofilters
在创建解码器之前可以对KSOptions和assetTrack做一些处理。例如判断fieldOrder为tt或bb的话,那就自动加videofilters
*/
open func process(assetTrack _: some MediaPlayerTrack) {}
open func process(assetTrack: some MediaPlayerTrack) {
if assetTrack.mediaType == .video {
#if os(tvOS) || os(xrOS)
runInMainqueue {
if let displayManager = UIApplication.shared.windows.first?.avDisplayManager,
displayManager.isDisplayCriteriaMatchingEnabled,
!displayManager.isDisplayModeSwitchInProgress
{
let refreshRate = assetTrack.nominalFrameRate
if KSOptions.displayCriteriaFormatDescriptionEnabled, let formatDescription = assetTrack.formatDescription, #available(tvOS 17.0, *) {
displayManager.preferredDisplayCriteria = AVDisplayCriteria(refreshRate: refreshRate, formatDescription: formatDescription)
} else {
// if let dynamicRange = assetTrack.dynamicRange {
// let videoDynamicRange = availableDynamicRange(dynamicRange) ?? dynamicRange
// displayManager.preferredDisplayCriteria = AVDisplayCriteria(refreshRate: refreshRate, videoDynamicRange: videoDynamicRange.rawValue)
// }
}
}
}

#if os(tvOS) || os(xrOS)
open func preferredDisplayCriteria(track: some MediaPlayerTrack) -> AVDisplayCriteria? {
let refreshRate = track.nominalFrameRate
if KSOptions.displayCriteriaFormatDescriptionEnabled, let formatDescription = track.formatDescription, #available(tvOS 17.0, *) {
return AVDisplayCriteria(refreshRate: refreshRate, formatDescription: formatDescription)
} else {
// let videoDynamicRange = track.dynamicRange(self).rawValue
// return AVDisplayCriteria(refreshRate: refreshRate, videoDynamicRange: videoDynamicRange)
return nil
#endif
}
}
#endif

open func updateVideo(refreshRate: Float, formatDescription: CMFormatDescription?) {
#if os(tvOS) || os(xrOS)
guard let displayManager = UIApplication.shared.windows.first?.avDisplayManager,
displayManager.isDisplayCriteriaMatchingEnabled,
!displayManager.isDisplayModeSwitchInProgress
else {
return
}
if KSOptions.displayCriteriaFormatDescriptionEnabled, let formatDescription, #available(tvOS 17.0, *) {
displayManager.preferredDisplayCriteria = AVDisplayCriteria(refreshRate: refreshRate, formatDescription: formatDescription)
}
#endif
}

// private var lastMediaTime = CACurrentMediaTime()
open func videoClockSync(main: KSClock, nextVideoTime: TimeInterval, fps: Float) -> ClockProcessType {
Expand Down Expand Up @@ -358,7 +383,7 @@ open class KSOptions {
}
}

func availableDynamicRange(_ cotentRange: DynamicRange?) -> DynamicRange? {
open func availableDynamicRange(_ cotentRange: DynamicRange?) -> DynamicRange? {
#if canImport(UIKit)
let availableHDRModes = AVPlayer.availableHDRModes
if let preferedDynamicRange = destinationDynamicRange {
Expand Down
19 changes: 0 additions & 19 deletions Sources/KSPlayer/AVPlayer/KSPlayerLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -339,11 +339,6 @@ extension KSPlayerLayer: MediaPlayerDelegate {
}
}
#endif
for track in player.tracks(mediaType: .video) where track.isEnabled {
#if os(tvOS) || os(xrOS)
setDisplayCriteria(track: track)
#endif
}
if isAutoPlay {
if shouldSeekTo > 0 {
seek(time: shouldSeekTo, autoPlay: true) { [weak self] _ in
Expand Down Expand Up @@ -441,20 +436,6 @@ extension KSPlayerLayer: AVPictureInPictureControllerDelegate {
// MARK: - private functions

extension KSPlayerLayer {
#if os(tvOS) || os(xrOS)
private func setDisplayCriteria(track: some MediaPlayerTrack) {
guard let displayManager = UIApplication.shared.windows.first?.avDisplayManager,
displayManager.isDisplayCriteriaMatchingEnabled,
!displayManager.isDisplayModeSwitchInProgress
else {
return
}
if let criteria = options.preferredDisplayCriteria(track: track) {
displayManager.preferredDisplayCriteria = criteria
}
}
#endif

private func prepareToPlay() {
startTime = CACurrentMediaTime()
bufferedCount = 0
Expand Down
53 changes: 39 additions & 14 deletions Sources/KSPlayer/AVPlayer/MediaPlayerProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,12 @@ public extension MediaPlayerTrack {
mediaSubType.rawValue
}

func dynamicRange(_ options: KSOptions) -> DynamicRange {
let cotentRange: DynamicRange
if dovi != nil || codecType.string == "dvhe" || codecType == kCMVideoCodecType_DolbyVisionHEVC {
cotentRange = .dolbyVision
} else if transferFunction == kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ as String { /// HDR
cotentRange = .hdr10
} else if transferFunction == kCVImageBufferTransferFunction_ITU_R_2100_HLG as String { /// HLG
cotentRange = .hlg
var dynamicRange: DynamicRange? {
if dovi != nil {
return .dolbyVision
} else {
cotentRange = .sdr
return formatDescription?.dynamicRange
}

return options.availableDynamicRange(cotentRange) ?? cotentRange
}

var colorSpace: CGColorSpace? {
Expand Down Expand Up @@ -198,23 +191,55 @@ public extension MediaPlayerTrack {
}

var colorPrimaries: String? {
if let formatDescription, let dictionary = CMFormatDescriptionGetExtensions(formatDescription) as NSDictionary? {
formatDescription?.colorPrimaries
}

var transferFunction: String? {
formatDescription?.transferFunction
}

var yCbCrMatrix: String? {
formatDescription?.yCbCrMatrix
}
}

extension CMFormatDescription {
var dynamicRange: DynamicRange {
let cotentRange: DynamicRange
if codecType.string == "dvhe" || codecType == kCMVideoCodecType_DolbyVisionHEVC {
cotentRange = .dolbyVision
} else if transferFunction == kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ as String { /// HDR
cotentRange = .hdr10
} else if transferFunction == kCVImageBufferTransferFunction_ITU_R_2100_HLG as String { /// HLG
cotentRange = .hlg
} else {
cotentRange = .sdr
}
return cotentRange
}

var codecType: FourCharCode {
mediaSubType.rawValue
}

var colorPrimaries: String? {
if let dictionary = CMFormatDescriptionGetExtensions(self) as NSDictionary? {
return dictionary[kCVImageBufferColorPrimariesKey] as? String
} else {
return nil
}
}

var transferFunction: String? {
if let formatDescription, let dictionary = CMFormatDescriptionGetExtensions(formatDescription) as NSDictionary? {
if let dictionary = CMFormatDescriptionGetExtensions(self) as NSDictionary? {
return dictionary[kCVImageBufferTransferFunctionKey] as? String
} else {
return nil
}
}

var yCbCrMatrix: String? {
if let formatDescription, let dictionary = CMFormatDescriptionGetExtensions(formatDescription) as NSDictionary? {
if let dictionary = CMFormatDescriptionGetExtensions(self) as NSDictionary? {
return dictionary[kCVImageBufferYCbCrMatrixKey] as? String
} else {
return nil
Expand Down
21 changes: 1 addition & 20 deletions Sources/KSPlayer/MEPlayer/MetalPlayView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ public protocol DisplayLayerDelegate: NSObjectProtocol {
public final class MetalPlayView: UIView {
private var formatDescription: CMFormatDescription? {
didSet {
#if os(tvOS) || os(xrOS)
if KSOptions.displayCriteriaFormatDescriptionEnabled, let formatDescription {
setDisplayCriteria(formatDescription: formatDescription)
}
#endif
options.updateVideo(refreshRate: fps, formatDescription: formatDescription)
}
}

Expand Down Expand Up @@ -220,21 +216,6 @@ extension MetalPlayView {
guard let formatDescription else { return }
displayView.enqueue(imageBuffer: pixelBuffer, formatDescription: formatDescription, time: time)
}

#if os(tvOS) || os(xrOS)
private func setDisplayCriteria(formatDescription: CMFormatDescription) {
guard let displayManager = UIApplication.shared.windows.first?.avDisplayManager,
displayManager.isDisplayCriteriaMatchingEnabled,
!displayManager.isDisplayModeSwitchInProgress
else {
return
}
if #available(tvOS 17.0, *) {
let criteria = AVDisplayCriteria(refreshRate: fps, formatDescription: formatDescription)
displayManager.preferredDisplayCriteria = criteria
}
}
#endif
}

class MetalView: UIView {
Expand Down

0 comments on commit 4a3c63d

Please sign in to comment.