Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:kingslay/KSPlayer into develop
Browse files Browse the repository at this point in the history
* 'develop' of github.com:kingslay/KSPlayer:
  add videoBitrate and audioBitrate
  add Stream Type kingslay#528
  解决AirPods 的问题
  fix kingslay#609
  fix kingslay#602
  AudioUnitPlayer add mute
  add AudioUnitPlayer kingslay#607
  • Loading branch information
Mo7amedFouad committed Nov 5, 2023
2 parents 1aa667e + 6c24a94 commit 8d52767
Show file tree
Hide file tree
Showing 19 changed files with 467 additions and 245 deletions.
56 changes: 36 additions & 20 deletions Demo/SwiftUI/Shared/Defaults.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ import SwiftUI

public class Defaults: ObservableObject {
@AppStorage("showRecentPlayList") public var showRecentPlayList = false
@AppStorage("isUseAudioRenderer") public var isUseAudioRenderer = KSOptions.isUseAudioRenderer {
didSet {
KSOptions.isUseAudioRenderer = isUseAudioRenderer
}
}

@AppStorage("hardwareDecode")
public var hardwareDecode = KSOptions.hardwareDecode {
Expand All @@ -31,85 +26,99 @@ public class Defaults: ObservableObject {
}
}

@AppStorage("isUseDisplayLayer") public var isUseDisplayLayer = MEOptions.isUseDisplayLayer {
@AppStorage("isUseDisplayLayer")
public var isUseDisplayLayer = MEOptions.isUseDisplayLayer {
didSet {
MEOptions.isUseDisplayLayer = isUseDisplayLayer
}
}

@AppStorage("preferredForwardBufferDuration") public var preferredForwardBufferDuration = KSOptions.preferredForwardBufferDuration {
@AppStorage("preferredForwardBufferDuration")
public var preferredForwardBufferDuration = KSOptions.preferredForwardBufferDuration {
didSet {
KSOptions.preferredForwardBufferDuration = preferredForwardBufferDuration
}
}

@AppStorage("maxBufferDuration") public var maxBufferDuration = KSOptions.maxBufferDuration {
@AppStorage("maxBufferDuration")
public var maxBufferDuration = KSOptions.maxBufferDuration {
didSet {
KSOptions.maxBufferDuration = maxBufferDuration
}
}

@AppStorage("isLoopPlay") public var isLoopPlay = KSOptions.isLoopPlay {
@AppStorage("isLoopPlay")
public var isLoopPlay = KSOptions.isLoopPlay {
didSet {
KSOptions.isLoopPlay = isLoopPlay
}
}

@AppStorage("canBackgroundPlay") public var canBackgroundPlay = true {
@AppStorage("canBackgroundPlay")
public var canBackgroundPlay = true {
didSet {
KSOptions.canBackgroundPlay = canBackgroundPlay
}
}

@AppStorage("isAutoPlay") public var isAutoPlay = true {
@AppStorage("isAutoPlay")
public var isAutoPlay = true {
didSet {
KSOptions.isAutoPlay = isAutoPlay
}
}

@AppStorage("isSecondOpen") public var isSecondOpen = true {
@AppStorage("isSecondOpen")
public var isSecondOpen = true {
didSet {
KSOptions.isSecondOpen = isSecondOpen
}
}

@AppStorage("isAccurateSeek") public var isAccurateSeek = true {
@AppStorage("isAccurateSeek")
public var isAccurateSeek = true {
didSet {
KSOptions.isAccurateSeek = isAccurateSeek
}
}

@AppStorage("isPipPopViewController") public var isPipPopViewController = true {
@AppStorage("isPipPopViewController")
public var isPipPopViewController = true {
didSet {
KSOptions.isPipPopViewController = isPipPopViewController
}
}

@AppStorage("textFontSize") public var textFontSize = SubtitleModel.textFontSize {
@AppStorage("textFontSize")
public var textFontSize = SubtitleModel.textFontSize {
didSet {
SubtitleModel.textFontSize = textFontSize
}
}

@AppStorage("textBold") public var textBold = SubtitleModel.textBold {
@AppStorage("textBold")
public var textBold = SubtitleModel.textBold {
didSet {
SubtitleModel.textBold = textBold
}
}

@AppStorage("textItalic") public var textItalic = SubtitleModel.textItalic {
@AppStorage("textItalic")
public var textItalic = SubtitleModel.textItalic {
didSet {
SubtitleModel.textItalic = textItalic
}
}

@AppStorage("textColor") public var textColor = SubtitleModel.textColor {
@AppStorage("textColor")
public var textColor = SubtitleModel.textColor {
didSet {
SubtitleModel.textColor = textColor
}
}

@AppStorage("textBackgroundColor") public var textBackgroundColor = SubtitleModel.textBackgroundColor {
@AppStorage("textBackgroundColor")
public var textBackgroundColor = SubtitleModel.textBackgroundColor {
didSet {
SubtitleModel.textBackgroundColor = textBackgroundColor
}
Expand Down Expand Up @@ -164,9 +173,15 @@ public class Defaults: ObservableObject {
}
}

@AppStorage("audioPlayerType")
public var audioPlayerType = NSStringFromClass(KSOptions.audioPlayerType) {
didSet {
KSOptions.audioPlayerType = NSClassFromString(audioPlayerType) as! any AudioOutput.Type
}
}

public static let shared = Defaults()
private init() {
KSOptions.isUseAudioRenderer = isUseAudioRenderer
KSOptions.hardwareDecode = hardwareDecode
MEOptions.isUseDisplayLayer = isUseDisplayLayer
SubtitleModel.textFontSize = textFontSize
Expand All @@ -188,6 +203,7 @@ public class Defaults: ObservableObject {
KSOptions.isAccurateSeek = isAccurateSeek
KSOptions.isPipPopViewController = isPipPopViewController
MEOptions.yadifMode = yadifMode
KSOptions.audioPlayerType = NSClassFromString(audioPlayerType) as! any AudioOutput.Type
}
}

Expand Down
4 changes: 4 additions & 0 deletions Demo/SwiftUI/Shared/MovieModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import KSPlayer
import UIKit
#endif
class MEOptions: KSOptions {
#if os(iOS)
static var isUseDisplayLayer = true
#else
static var isUseDisplayLayer = false
#endif
static var yadifMode = 1
override init() {
super.init()
Expand Down
11 changes: 8 additions & 3 deletions Demo/SwiftUI/Shared/SettingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,17 @@ struct SettingGeneralView: View {
}

struct SettingAudioView: View {
@Default(\.isUseAudioRenderer)
private var isUseAudioRenderer
@Default(\.audioPlayerType)
private var audioPlayerType
init() {}
var body: some View {
Form {
Toggle("Use Audio Renderer", isOn: $isUseAudioRenderer)
Picker("audio Player Type", selection: $audioPlayerType) {
Text("AUGraph").tag(NSStringFromClass(AudioGraphPlayer.self))
Text("AudioUnit").tag(NSStringFromClass(AudioUnitPlayer.self))
Text("AVAudioEngine").tag(NSStringFromClass(AudioEnginePlayer.self))
Text("AVSampleBufferAudioRenderer").tag(NSStringFromClass(AudioRendererPlayer.self))
}
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions Demo/SwiftUI/Shared/TracyApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import UserNotifications
@main
struct TracyApp: App {
#if os(macOS)
@NSApplicationDelegateAdaptor private var appDelegate: AppDelegate
@NSApplicationDelegateAdaptor
#else
@UIApplicationDelegateAdaptor private var appDelegate: AppDelegate
@UIApplicationDelegateAdaptor
#endif
private var appDelegate: AppDelegate
private let appModel = APPModel()
init() {
let arguments = ProcessInfo.processInfo.arguments.dropFirst()
Expand Down
3 changes: 2 additions & 1 deletion Sources/KSPlayer/AVPlayer/KSAVPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ public class KSAVPlayer {
public private(set) var duration: TimeInterval = 0
public private(set) var fileSize: Double = 0
public private(set) var playableTime: TimeInterval = 0

public var audioBitrate: Int = 0
public var videoBitrate: Int = 0
public var playbackRate: Float = 1 {
didSet {
if playbackState == .playing {
Expand Down
31 changes: 17 additions & 14 deletions Sources/KSPlayer/AVPlayer/KSOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ open class KSOptions {
// audio
public var audioFilters = [String]()
public var syncDecodeAudio = false
/// true: AVSampleBufferAudioRenderer false: AVAudioEngine
public var isUseAudioRenderer = KSOptions.isUseAudioRenderer
// Locale(identifier: "en-US") Locale(identifier: "zh-CN")
public var audioLocale: Locale?
// sutile
Expand Down Expand Up @@ -244,7 +242,11 @@ open class KSOptions {
}

open func isUseDisplayLayer() -> Bool {
#if os(iOS)
display == .plane
#else
false
#endif
}

open func io(log: String) {
Expand Down Expand Up @@ -486,24 +488,24 @@ public extension KSOptions {
}

#if !os(macOS)
static func isSpatialAudioEnabled() -> Bool {
static func isSpatialAudioEnabled(channelCount: AVAudioChannelCount) -> Bool {
if #available(tvOS 15.0, iOS 15.0, *) {
let isSpatialAudioEnabled = AVAudioSession.sharedInstance().currentRoute.outputs.contains { $0.isSpatialAudioEnabled }
try? AVAudioSession.sharedInstance().setSupportsMultichannelContent(isSpatialAudioEnabled)
try? AVAudioSession.sharedInstance().setSupportsMultichannelContent(channelCount > 2)
return isSpatialAudioEnabled
} else {
return false
}
}

static func outputNumberOfChannels(channelCount: AVAudioChannelCount, isUseAudioRenderer: Bool) -> AVAudioChannelCount {
static func outputNumberOfChannels(channelCount: AVAudioChannelCount) -> AVAudioChannelCount {
let maximumOutputNumberOfChannels = AVAudioChannelCount(AVAudioSession.sharedInstance().maximumOutputNumberOfChannels)
let preferredOutputNumberOfChannels = AVAudioChannelCount(AVAudioSession.sharedInstance().preferredOutputNumberOfChannels)
KSLog("[audio] maximumOutputNumberOfChannels: \(maximumOutputNumberOfChannels)")
KSLog("[audio] preferredOutputNumberOfChannels: \(preferredOutputNumberOfChannels)")
setAudioSession()
let isSpatialAudioEnabled = isSpatialAudioEnabled()
let isSpatialAudioEnabled = isSpatialAudioEnabled(channelCount: channelCount)
KSLog("[audio] isSpatialAudioEnabled: \(isSpatialAudioEnabled)")
let isUseAudioRenderer = KSOptions.audioPlayerType == AudioRendererPlayer.self
KSLog("[audio] isUseAudioRenderer: \(isUseAudioRenderer)")
var channelCount = channelCount
if channelCount > 2 {
Expand All @@ -512,14 +514,15 @@ public extension KSOptions {
try? AVAudioSession.sharedInstance().setPreferredOutputNumberOfChannels(Int(minChannels))
KSLog("[audio] set preferredOutputNumberOfChannels: \(minChannels)")
}
// 不要从currentRoute获取maxRouteChannelsCount,有可能会不准。导致多音道设备也返回2(一开始播放一个2声道,就容易出现)
// if !(isUseAudioRenderer && isSpatialAudioEnabled) {
// let maxRouteChannelsCount = AVAudioSession.sharedInstance().currentRoute.outputs.compactMap {
// $0.channels?.count
// }.max() ?? 2
// KSLog("[audio] currentRoute max channels: \(maxRouteChannelsCount)")
if !(isUseAudioRenderer && isSpatialAudioEnabled) {
let maxRouteChannelsCount = AVAudioSession.sharedInstance().currentRoute.outputs.compactMap {
$0.channels?.count
}.max() ?? 2
KSLog("[audio] currentRoute max channels: \(maxRouteChannelsCount)")
// 不要用maxRouteChannelsCount来panduan,有可能会不准。导致多音道设备也返回2(一开始播放一个2声道,就容易出现)
// channelCount = AVAudioChannelCount(min(AVAudioSession.sharedInstance().outputNumberOfChannels, maxRouteChannelsCount))
// }
channelCount = AVAudioChannelCount(AVAudioSession.sharedInstance().outputNumberOfChannels)
}
} else {
channelCount = 2
}
Expand Down
19 changes: 19 additions & 0 deletions Sources/KSPlayer/AVPlayer/MediaPlayerProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public protocol MediaPlayback: AnyObject {
var fileSize: Double { get }
var metadata: [String: String] { get }
var naturalSize: CGSize { get }
var audioBitrate: Int { get }
var videoBitrate: Int { get }
var currentPlaybackTime: TimeInterval { get }
func prepareToPlay()
func shutdown()
Expand Down Expand Up @@ -127,6 +129,23 @@ public enum FFmpegFieldOrder: UInt8 {
case bt // < Bottom coded first, top displayed first
}

extension FFmpegFieldOrder: CustomStringConvertible {
public var description: String {
switch self {
case .unknown, .progressive:
return "progressive"
case .tt:
return "top first"
case .bb:
return "bottom first"
case .tb:
return "top coded first (swapped)"
case .bt:
return "bottom coded first (swapped)"
}
}
}

// swiftlint:enable identifier_name
public extension MediaPlayerTrack {
var codecType: FourCharCode {
Expand Down
4 changes: 4 additions & 0 deletions Sources/KSPlayer/MEPlayer/AVFoundationExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ extension AVAudioChannelLayout {
KSLog("[audio] out mask: \(outChannel.u.mask) nb_channels: \(outChannel.nb_channels)")
return outChannel
}

public var channelDescriptions: String {
"tag: \(layoutTag), channelDescriptions: \(layout.channelDescriptions)"
}
}

extension AVAudioFormat {
Expand Down
Loading

0 comments on commit 8d52767

Please sign in to comment.