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:
  解决本地依赖问题
  解决字幕无法显示的问题
  fix kingslay#624
  fix kingslay#528
  add log
  fix  kingslay#618
  fix  kingslay#618
  fix build
  fix kingslay#627
  add sponsor
  fix build
  fix kingslay#528

# Conflicts:
#	Sources/KSPlayer/MEPlayer/FFmpegAssetTrack.swift
#	Sources/KSPlayer/MEPlayer/FFmpegDecode.swift
#	Sources/KSPlayer/MEPlayer/MEPlayerItem.swift
  • Loading branch information
Mo7amedFouad committed Nov 12, 2023
2 parents 4292011 + e970749 commit c91af9a
Show file tree
Hide file tree
Showing 20 changed files with 335 additions and 227 deletions.
14 changes: 0 additions & 14 deletions Package.resolved

This file was deleted.

7 changes: 7 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,18 @@ let package = Package(
]
)
var ffmpegKitPath = FileManager.default.currentDirectoryPath + "/FFmpegKit"
if !FileManager.default.fileExists(atPath: ffmpegKitPath) {
ffmpegKitPath = FileManager.default.currentDirectoryPath + "/KSPlayer/FFmpegKit"
}

if !FileManager.default.fileExists(atPath: ffmpegKitPath), let url = URL(string: #file) {
let path = url.deletingLastPathComponent().path
// 解决用xcode引入spm的时候,依赖关系出错的问题
if !path.contains("/checkouts/") {
ffmpegKitPath = path + "/FFmpegKit"
if !FileManager.default.fileExists(atPath: ffmpegKitPath) {
ffmpegKitPath = path + "/KSPlayer/FFmpegKit"
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions Package@swift-5.9.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,20 @@ let package = Package(
),
]
)

var ffmpegKitPath = FileManager.default.currentDirectoryPath + "/FFmpegKit"
if !FileManager.default.fileExists(atPath: ffmpegKitPath) {
ffmpegKitPath = FileManager.default.currentDirectoryPath + "/KSPlayer/FFmpegKit"
}

if !FileManager.default.fileExists(atPath: ffmpegKitPath), let url = URL(string: #file) {
let path = url.deletingLastPathComponent().path
// 解决用xcode引入spm的时候,依赖关系出错的问题
if !path.contains("/checkouts/") {
ffmpegKitPath = path + "/FFmpegKit"
if !FileManager.default.fileExists(atPath: ffmpegKitPath) {
ffmpegKitPath = path + "/KSPlayer/FFmpegKit"
}
}
}

Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,16 @@ Any contributing and pull requests are warmly welcome. However, before you plan
Open-source projects cannot live long without your help. If you find KSPlayer to be useful, please consider supporting this
project by becoming a sponsor.

Thanks to [cdguy](https://github.com/cdguy) [UnknownCoder807](https://github.com/UnknownCoder807) [skrew](https://github.com/skrew) and LillyPlayer community for sponsoring a LG S95QR Sound Bar

Thanks to [skrew](https://github.com/skrew) and LillyPlayer community for sponsoring a 2022 Apple TV 4K

Become a sponsor through [GitHub Sponsors](https://github.com/sponsors/kingslay/). :heart:

Your user icon or company logo shows up this with a link to your home page.

[UnknownCoder807](https://github.com/UnknownCoder807) [skrew](https://github.com/skrew) [Kimentanm](https://github.com/Kimentanm) [nakiostudio](https://github.com/nakiostudio)
[UnknownCoder807](https://github.com/UnknownCoder807) [skrew](https://github.com/skrew) [Kimentanm](https://github.com/Kimentanm) [nakiostudio](https://github.com/nakiostudio) [byMohamedali](https://github.com/byMohamedali)


Thanks to [cdguy](https://github.com/cdguy) [UnknownCoder807](https://github.com/UnknownCoder807) [skrew](https://github.com/skrew) and LillyPlayer community for sponsoring a LG S95QR Sound Bar

Thanks to [skrew](https://github.com/skrew) and LillyPlayer community for sponsoring a 2022 Apple TV 4K

## Communication

Expand Down
4 changes: 1 addition & 3 deletions Sources/KSPlayer/AVPlayer/KSAVPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public class KSAVPlayer {
}

public var naturalSize: CGSize = .zero
public var metadata = [String: String]()
public let dynamicInfo: DynamicInfo? = nil
@available(macOS 12.0, iOS 15.0, tvOS 15.0, *)
public var playbackCoordinator: AVPlaybackCoordinator {
playerView.player.playbackCoordinator
Expand All @@ -126,8 +126,6 @@ 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
45 changes: 24 additions & 21 deletions Sources/KSPlayer/AVPlayer/KSOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ open class KSOptions {
AVSEEK_FLAG_ANY: 4
AVSEEK_FLAG_FRAME: 8
*/
public var seekFlags = Int32(0)
public var seekFlags = Int32(1)
// ffmpeg only cache http
public var cache = false
// record stream
Expand Down Expand Up @@ -224,12 +224,17 @@ open class KSOptions {
nil
}

open func videoFrameMaxCount(fps _: Float, naturalSize _: CGSize) -> Int {
16
open func videoFrameMaxCount(fps _: Float, naturalSize _: CGSize, isLive: Bool) -> UInt8 {
isLive ? 4 : 16
}

open func audioFrameMaxCount(fps: Float, channelCount _: Int) -> Int {
Int(fps) >> 2
open func audioFrameMaxCount(fps: Float, channelCount _: Int) -> UInt8 {
let count = Int(fps) >> 2
if count >= UInt8.max {
return UInt8.max
} else {
return UInt8(count)
}
}

/// customize dar
Expand Down Expand Up @@ -328,53 +333,51 @@ open class KSOptions {
}

// private var lastMediaTime = CACurrentMediaTime()
open func videoClockSync(main: KSClock, nextVideoTime: TimeInterval, fps: Float, frameCount: Int) -> ClockProcessType {
open func videoClockSync(main: KSClock, nextVideoTime: TimeInterval, fps: Float, frameCount: Int) -> (Double, ClockProcessType) {
var desire = main.getTime() - videoDelay
#if !os(macOS)
desire -= AVAudioSession.sharedInstance().outputLatency
#endif
let diff = nextVideoTime - desire
// print("[video] video diff \(diff) audio \(main.positionTime) interval \(CACurrentMediaTime() - main.lastMediaTime) render interval \(CACurrentMediaTime() - lastMediaTime)")
if diff > 10 || diff < -10 {
return .next
} else if diff > 1 / Double(fps * 2) {
if diff > 1 / Double(fps * 2) {
videoClockDelayCount = 0
return .remain
return (diff, .remain)
} else {
if diff < -4 / Double(fps) {
videoClockDelayCount += 1
let log = "[video] video delay=\(diff), clock=\(desire), delay count=\(videoClockDelayCount), frameCount=\(frameCount)"
if frameCount == 1 {
if diff < -1, videoClockDelayCount % 10 == 0 {
KSLog("\(log) drop gop Packet")
return .dropGOPPacket
return (diff, .dropGOPPacket)
} else if videoClockDelayCount % 5 == 0 {
KSLog("\(log) drop next frame")
return .dropNextFrame
return (diff, .dropNextFrame)
} else {
return .next
return (diff, .next)
}
} else {
if diff < -8, videoClockDelayCount % 100 == 0 {
KSLog("\(log) seek video track")
return .seek
return (diff, .seek)
}
if diff < -1, videoClockDelayCount % 10 == 0 {
KSLog("\(log) flush video track")
return .flush
return (diff, .flush)
}
if videoClockDelayCount % 2 == 0 {
KSLog("\(log) drop next frame")
return .dropNextFrame
return (diff, .dropNextFrame)
} else {
return .next
return (diff, .next)
}
}
} else {
videoClockDelayCount = 0
// print("[video] video interval \(CACurrentMediaTime() - lastMediaTime)")
// lastMediaTime = CACurrentMediaTime()
return .next
return (diff, .next)
}
}
}
Expand Down Expand Up @@ -502,16 +505,16 @@ public extension KSOptions {
// iOS 有空间音频功能,所以不用处理
#if os(tvOS) || targetEnvironment(simulator)
if !(isUseAudioRenderer && isSpatialAudioEnabled) {
// 不要用maxRouteChannelsCount来panduan,有可能会不准。导致多音道设备也返回2(一开始播放一个2声道,就容易出现)
// 不要用maxRouteChannelsCount来判断,有可能会不准。导致多音道设备也返回2(一开始播放一个2声道,就容易出现),也不能用outputNumberOfChannels来判断,有可能会返回2
// channelCount = AVAudioChannelCount(min(AVAudioSession.sharedInstance().outputNumberOfChannels, maxRouteChannelsCount))
channelCount = AVAudioChannelCount(AVAudioSession.sharedInstance().outputNumberOfChannels)
channelCount = minChannels
}
#endif
} else {
try? AVAudioSession.sharedInstance().setPreferredOutputNumberOfChannels(2)
channelCount = 2
}
KSLog("[audio] outputNumberOfChannels: \(AVAudioSession.sharedInstance().outputNumberOfChannels)")
KSLog("[audio] outputNumberOfChannels: \(AVAudioSession.sharedInstance().outputNumberOfChannels) output channelCount: \(channelCount)")
return channelCount
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions Sources/KSPlayer/AVPlayer/KSPlayerLayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -464,10 +464,10 @@ extension KSPlayerLayer {
} else {
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyPlaybackDuration] = player.duration
}
if MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyTitle] == nil, let title = player.metadata["title"] {
if MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyTitle] == nil, let title = player.dynamicInfo?.metadata["title"] {
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyTitle] = title
}
if MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyArtist] == nil, let artist = player.metadata["artist"] {
if MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyArtist] == nil, let artist = player.dynamicInfo?.metadata["artist"] {
MPNowPlayingInfoCenter.default().nowPlayingInfo?[MPMediaItemPropertyArtist] = artist
}
var current: [MPNowPlayingInfoLanguageOption] = []
Expand Down
107 changes: 70 additions & 37 deletions Sources/KSPlayer/AVPlayer/MediaPlayerProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,47 @@ import AppKit
public protocol MediaPlayback: AnyObject {
var duration: TimeInterval { get }
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()
func seek(time: TimeInterval, completion: @escaping ((Bool) -> Void))
}

public class DynamicInfo: ObservableObject {
private let metadataBlock: () -> [String: String]
private let bytesReadBlock: () -> Int64
private let audioBitrateBlock: () -> Int
private let videoBitrateBlock: () -> Int
public var metadata: [String: String] {
metadataBlock()
}

public var bytesRead: Int64 {
bytesReadBlock()
}

public var audioBitrate: Int {
audioBitrateBlock()
}

public var videoBitrate: Int {
videoBitrateBlock()
}

@Published
public var displayFPS = 0.0
public var audioVideoSyncDiff = 0.0
public var droppedVideoFrameCount = UInt32(0)
public var droppedVideoPacketCount = UInt32(0)
init(metadata: @escaping () -> [String: String], bytesRead: @escaping () -> Int64, audioBitrate: @escaping () -> Int, videoBitrate: @escaping () -> Int) {
metadataBlock = metadata
bytesReadBlock = bytesRead
audioBitrateBlock = audioBitrate
videoBitrateBlock = videoBitrate
}
}

public protocol MediaPlayerProtocol: MediaPlayback {
var delegate: MediaPlayerDelegate? { get set }
var view: UIView? { get }
Expand All @@ -48,6 +79,7 @@ public protocol MediaPlayerProtocol: MediaPlayback {
var playbackCoordinator: AVPlaybackCoordinator { get }
@available(tvOS 14.0, *)
var pipController: KSPictureInPictureController? { get }
var dynamicInfo: DynamicInfo? { get }
init(url: URL, options: KSOptions)
func replace(url: URL, options: KSOptions)
func play()
Expand Down Expand Up @@ -173,40 +205,7 @@ public extension MediaPlayerTrack {
}

var naturalSize: CGSize {
formatDescription.map { description in
let dimensions = description.dimensions
let aspectRatio = aspectRatio
return CGSize(width: Int(dimensions.width), height: Int(CGFloat(dimensions.height) * aspectRatio.height / aspectRatio.width))
} ?? .zero
}

var aspectRatio: CGSize {
if let formatDescription, let dictionary = CMFormatDescriptionGetExtensions(formatDescription) as NSDictionary? {
if let ratio = dictionary[kCVImageBufferPixelAspectRatioKey] as? NSDictionary,
let horizontal = (ratio[kCVImageBufferPixelAspectRatioHorizontalSpacingKey] as? NSNumber)?.intValue,
let vertical = (ratio[kCVImageBufferPixelAspectRatioVerticalSpacingKey] as? NSNumber)?.intValue,
horizontal > 0, vertical > 0
{
return CGSize(width: horizontal, height: vertical)
}
}
return CGSize(width: 1, height: 1)
}

var depth: Int32 {
if let formatDescription, let dictionary = CMFormatDescriptionGetExtensions(formatDescription) as NSDictionary? {
return dictionary[kCMFormatDescriptionExtension_Depth] as? Int32 ?? 24
} else {
return 24
}
}

var fullRangeVideo: Bool {
if let formatDescription, let dictionary = CMFormatDescriptionGetExtensions(formatDescription) as NSDictionary? {
return dictionary[kCMFormatDescriptionExtension_FullRangeVideo] as? Bool ?? false
} else {
return false
}
formatDescription?.naturalSize ?? .zero
}

var colorPrimaries: String? {
Expand Down Expand Up @@ -264,6 +263,40 @@ public extension CMFormatDescription {
return nil
}
}

var naturalSize: CGSize {
let aspectRatio = aspectRatio
return CGSize(width: Int(dimensions.width), height: Int(CGFloat(dimensions.height) * aspectRatio.height / aspectRatio.width))
}

var aspectRatio: CGSize {
if let dictionary = CMFormatDescriptionGetExtensions(self) as NSDictionary? {
if let ratio = dictionary[kCVImageBufferPixelAspectRatioKey] as? NSDictionary,
let horizontal = (ratio[kCVImageBufferPixelAspectRatioHorizontalSpacingKey] as? NSNumber)?.intValue,
let vertical = (ratio[kCVImageBufferPixelAspectRatioVerticalSpacingKey] as? NSNumber)?.intValue,
horizontal > 0, vertical > 0
{
return CGSize(width: horizontal, height: vertical)
}
}
return CGSize(width: 1, height: 1)
}

var depth: Int32 {
if let dictionary = CMFormatDescriptionGetExtensions(self) as NSDictionary? {
return dictionary[kCMFormatDescriptionExtension_Depth] as? Int32 ?? 24
} else {
return 24
}
}

var fullRangeVideo: Bool {
if let dictionary = CMFormatDescriptionGetExtensions(self) as NSDictionary? {
return dictionary[kCMFormatDescriptionExtension_FullRangeVideo] as? Bool ?? false
} else {
return false
}
}
}

func setHttpProxy() {
Expand Down
21 changes: 21 additions & 0 deletions Sources/KSPlayer/AVPlayer/PlayerDefines.swift
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,27 @@ public extension Int {
}
}

public extension FixedWidthInteger {
var kmFormatted: String {
Double(self).kmFormatted
}
}

public extension Double {
var kmFormatted: String {
// return .formatted(.number.notation(.compactName))
if self >= 1_000_000 {
return String(format: "%.1fM", locale: Locale.current, self / 1_000_000)
// .replacingOccurrences(of: ".0", with: "")
} else if self >= 10000, self <= 999_999 {
return String(format: "%.1fK", locale: Locale.current, self / 1000)
// .replacingOccurrences(of: ".0", with: "")
} else {
return String(format: "%.0f", locale: Locale.current, self)
}
}
}

extension TextAlignment: RawRepresentable {
public typealias RawValue = String
public init?(rawValue: RawValue) {
Expand Down
Loading

0 comments on commit c91af9a

Please sign in to comment.