From 0591bc2bdffdd9e13ee902fbc842dadf2754c02e Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 6 Dec 2018 09:49:35 +0900 Subject: [PATCH 001/215] Screen scale optimization to support various resolutions. --- DLGPlayer/view/DLGPlayerView.m | 1 + 1 file changed, 1 insertion(+) diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index e261576..558a108 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -106,6 +106,7 @@ - (void)clear { - (BOOL)initVars { _eaglLayer = (CAEAGLLayer *)self.layer; _eaglLayer.opaque = YES; + _eaglLayer.contentsScale = [UIScreen mainScreen].scale; _eaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking : @(NO), kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8 }; From afcf75001aa95139dfa5f0462e70b9fd1016a4a2 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 6 Dec 2018 14:10:02 +0900 Subject: [PATCH 002/215] Update gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 6142941..6295fb5 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,7 @@ fastlane/screenshots # https://github.com/johnno1962/injectionforxcode iOSInjectionProject/ + +ffmpeg/ + +Example-Carthage/DLGPlayerDemo/Carthage/Build From e258c7b79de155dbca9e24c6580ea0efb00ad55c Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 6 Dec 2018 15:51:39 +0900 Subject: [PATCH 003/215] Add pre-build script file for carthage build. Add example project with cathage. --- DLGPlayer.xcodeproj/project.pbxproj | 719 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/DLGPlayer.xcscheme | 99 +++ Example-Carthage/DLGPlayerDemo/Cartfile | 2 + .../DLGPlayerDemo.xcodeproj/project.pbxproj | 340 +++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../DLGPlayerDemo/DLGPlayerDemo/AppDelegate.h | 17 + .../DLGPlayerDemo/DLGPlayerDemo/AppDelegate.m | 51 ++ .../AppIcon.appiconset/Contents.json | 98 +++ .../Assets.xcassets/Contents.json | 6 + .../Base.lproj/LaunchScreen.storyboard | 25 + .../DLGPlayerDemo/Base.lproj/Main.storyboard | 24 + .../DLGPlayerDemo/DLGPlayerDemo/Info.plist | 45 ++ .../DLGPlayerDemo/ViewController.h | 15 + .../DLGPlayerDemo/ViewController.m | 23 + .../DLGPlayerDemo/DLGPlayerDemo/main.m | 16 + .../DLGPlayerDemo/Scripts/carthage_xconfig.rb | 179 +++++ .../DLGPlayerDemo/Scripts/lib-update.sh | 33 + pre-build.sh | 37 + 21 files changed, 1759 insertions(+) create mode 100644 DLGPlayer.xcodeproj/project.pbxproj create mode 100644 DLGPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 DLGPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme create mode 100755 Example-Carthage/DLGPlayerDemo/Cartfile create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.pbxproj create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.h create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.m create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/Contents.json create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/Main.storyboard create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Info.plist create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.h create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.m create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/main.m create mode 100644 Example-Carthage/DLGPlayerDemo/Scripts/carthage_xconfig.rb create mode 100755 Example-Carthage/DLGPlayerDemo/Scripts/lib-update.sh create mode 100755 pre-build.sh diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj new file mode 100644 index 0000000..77e1cd0 --- /dev/null +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -0,0 +1,719 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 23DC26D821B80F5A0012243A /* DLGPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; }; + 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291421B810B40012243A /* DLGPlayerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 23DC293A21B810B50012243A /* DLGPlayerDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC291621B810B40012243A /* DLGPlayerDecoder.m */; }; + 23DC293B21B810B50012243A /* DLGPlayerAudioManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC291721B810B40012243A /* DLGPlayerAudioManager.m */; }; + 23DC293E21B810B50012243A /* DLGPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291A21B810B50012243A /* DLGPlayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 23DC293F21B810B50012243A /* DLGPlayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC291B21B810B50012243A /* DLGPlayerViewController.m */; }; + 23DC294021B810B50012243A /* DLGPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC291C21B810B50012243A /* DLGPlayer.m */; }; + 23DC294121B810B50012243A /* DLGPlayerStrings.strings in Resources */ = {isa = PBXBuildFile; fileRef = 23DC291E21B810B50012243A /* DLGPlayerStrings.strings */; }; + 23DC294221B810B50012243A /* DLGPlayerRotationScaleVertexShader.glsl in Resources */ = {isa = PBXBuildFile; fileRef = 23DC292121B810B50012243A /* DLGPlayerRotationScaleVertexShader.glsl */; }; + 23DC294321B810B50012243A /* DLGPlayerYUVFragmentShader.glsl in Resources */ = {isa = PBXBuildFile; fileRef = 23DC292221B810B50012243A /* DLGPlayerYUVFragmentShader.glsl */; }; + 23DC294421B810B50012243A /* DLGPlayerRGBFragmentShader.glsl in Resources */ = {isa = PBXBuildFile; fileRef = 23DC292321B810B50012243A /* DLGPlayerRGBFragmentShader.glsl */; }; + 23DC294521B810B50012243A /* DLGPlayerRotationVertexShader.glsl in Resources */ = {isa = PBXBuildFile; fileRef = 23DC292521B810B50012243A /* DLGPlayerRotationVertexShader.glsl */; }; + 23DC294621B810B50012243A /* DLGPlayerVertexShader.glsl in Resources */ = {isa = PBXBuildFile; fileRef = 23DC292621B810B50012243A /* DLGPlayerVertexShader.glsl */; }; + 23DC294921B810B50012243A /* DLGPlayerVideoRGBFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC292A21B810B50012243A /* DLGPlayerVideoRGBFrame.m */; }; + 23DC294A21B810B50012243A /* DLGPlayerAudioFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC292B21B810B50012243A /* DLGPlayerAudioFrame.m */; }; + 23DC294D21B810B50012243A /* DLGPlayerVideoFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC292E21B810B50012243A /* DLGPlayerVideoFrame.m */; }; + 23DC294E21B810B50012243A /* DLGPlayerVideoYUVFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC292F21B810B50012243A /* DLGPlayerVideoYUVFrame.m */; }; + 23DC295021B810B50012243A /* DLGPlayerFrame.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC293121B810B50012243A /* DLGPlayerFrame.m */; }; + 23DC295121B810B50012243A /* DLGPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC293321B810B50012243A /* DLGPlayerView.m */; }; + 23DC295521B810B50012243A /* DLGPlayerUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC293821B810B50012243A /* DLGPlayerUtils.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 23DC26D921B80F5A0012243A /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 23DC26C521B80F5A0012243A /* Project object */; + proxyType = 1; + remoteGlobalIDString = 23DC26CD21B80F5A0012243A; + remoteInfo = DLGPlayer; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DLGPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 23DC26D221B80F5A0012243A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 23DC26D721B80F5A0012243A /* DLGPlayerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DLGPlayerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 23DC291421B810B40012243A /* DLGPlayerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerViewController.h; sourceTree = ""; }; + 23DC291621B810B40012243A /* DLGPlayerDecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerDecoder.m; sourceTree = ""; }; + 23DC291721B810B40012243A /* DLGPlayerAudioManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerAudioManager.m; sourceTree = ""; }; + 23DC291821B810B40012243A /* DLGPlayerDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerDecoder.h; sourceTree = ""; }; + 23DC291921B810B40012243A /* DLGPlayerAudioManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerAudioManager.h; sourceTree = ""; }; + 23DC291A21B810B50012243A /* DLGPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayer.h; sourceTree = ""; }; + 23DC291B21B810B50012243A /* DLGPlayerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerViewController.m; sourceTree = ""; }; + 23DC291C21B810B50012243A /* DLGPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayer.m; sourceTree = ""; }; + 23DC291F21B810B50012243A /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/DLGPlayerStrings.strings"; sourceTree = ""; }; + 23DC292021B810B50012243A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/DLGPlayerStrings.strings; sourceTree = ""; }; + 23DC292121B810B50012243A /* DLGPlayerRotationScaleVertexShader.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DLGPlayerRotationScaleVertexShader.glsl; sourceTree = ""; }; + 23DC292221B810B50012243A /* DLGPlayerYUVFragmentShader.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DLGPlayerYUVFragmentShader.glsl; sourceTree = ""; }; + 23DC292321B810B50012243A /* DLGPlayerRGBFragmentShader.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DLGPlayerRGBFragmentShader.glsl; sourceTree = ""; }; + 23DC292421B810B50012243A /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/DLGPlayerStrings.strings; sourceTree = ""; }; + 23DC292521B810B50012243A /* DLGPlayerRotationVertexShader.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DLGPlayerRotationVertexShader.glsl; sourceTree = ""; }; + 23DC292621B810B50012243A /* DLGPlayerVertexShader.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DLGPlayerVertexShader.glsl; sourceTree = ""; }; + 23DC292821B810B50012243A /* DLGPlayerVideoYUVFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerVideoYUVFrame.h; sourceTree = ""; }; + 23DC292921B810B50012243A /* DLGPlayerVideoFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerVideoFrame.h; sourceTree = ""; }; + 23DC292A21B810B50012243A /* DLGPlayerVideoRGBFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerVideoRGBFrame.m; sourceTree = ""; }; + 23DC292B21B810B50012243A /* DLGPlayerAudioFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerAudioFrame.m; sourceTree = ""; }; + 23DC292C21B810B50012243A /* DLGPlayerFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerFrame.h; sourceTree = ""; }; + 23DC292D21B810B50012243A /* DLGPlayerVideoRGBFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerVideoRGBFrame.h; sourceTree = ""; }; + 23DC292E21B810B50012243A /* DLGPlayerVideoFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerVideoFrame.m; sourceTree = ""; }; + 23DC292F21B810B50012243A /* DLGPlayerVideoYUVFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerVideoYUVFrame.m; sourceTree = ""; }; + 23DC293021B810B50012243A /* DLGPlayerAudioFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerAudioFrame.h; sourceTree = ""; }; + 23DC293121B810B50012243A /* DLGPlayerFrame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerFrame.m; sourceTree = ""; }; + 23DC293321B810B50012243A /* DLGPlayerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerView.m; sourceTree = ""; }; + 23DC293421B810B50012243A /* DLGPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerView.h; sourceTree = ""; }; + 23DC293621B810B50012243A /* DLGPlayerDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerDef.h; sourceTree = ""; }; + 23DC293721B810B50012243A /* DLGPlayerUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerUtils.h; sourceTree = ""; }; + 23DC293821B810B50012243A /* DLGPlayerUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerUtils.m; sourceTree = ""; }; + 23DC295E21B814470012243A /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + 23DC296021B8144D0012243A /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; + 23DC296221B814520012243A /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + 23DC296421B814560012243A /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; + 23DC296621B8145B0012243A /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; + 23DC296821B8145F0012243A /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 23DC296A21B8146D0012243A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 23DC296C21B814730012243A /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; + 23DC296E21B8147A0012243A /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; }; + 23DC297021B814830012243A /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 23DC297221B8148B0012243A /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 23DC26CB21B80F5A0012243A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 23DC26D421B80F5A0012243A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 23DC26D821B80F5A0012243A /* DLGPlayer.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 23DC26C421B80F5A0012243A = { + isa = PBXGroup; + children = ( + 23DC26D021B80F5A0012243A /* DLGPlayer */, + 23DC26CF21B80F5A0012243A /* Products */, + 23DC295D21B814470012243A /* Frameworks */, + ); + sourceTree = ""; + }; + 23DC26CF21B80F5A0012243A /* Products */ = { + isa = PBXGroup; + children = ( + 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */, + 23DC26D721B80F5A0012243A /* DLGPlayerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 23DC26D021B80F5A0012243A /* DLGPlayer */ = { + isa = PBXGroup; + children = ( + 23DC291521B810B40012243A /* codec */, + 23DC293521B810B50012243A /* common */, + 23DC291A21B810B50012243A /* DLGPlayer.h */, + 23DC291C21B810B50012243A /* DLGPlayer.m */, + 23DC291421B810B40012243A /* DLGPlayerViewController.h */, + 23DC291B21B810B50012243A /* DLGPlayerViewController.m */, + 23DC292721B810B50012243A /* frame */, + 23DC291D21B810B50012243A /* resource */, + 23DC293221B810B50012243A /* view */, + 23DC26D221B80F5A0012243A /* Info.plist */, + ); + path = DLGPlayer; + sourceTree = ""; + }; + 23DC291521B810B40012243A /* codec */ = { + isa = PBXGroup; + children = ( + 23DC291621B810B40012243A /* DLGPlayerDecoder.m */, + 23DC291721B810B40012243A /* DLGPlayerAudioManager.m */, + 23DC291821B810B40012243A /* DLGPlayerDecoder.h */, + 23DC291921B810B40012243A /* DLGPlayerAudioManager.h */, + ); + path = codec; + sourceTree = ""; + }; + 23DC291D21B810B50012243A /* resource */ = { + isa = PBXGroup; + children = ( + 23DC291E21B810B50012243A /* DLGPlayerStrings.strings */, + 23DC292121B810B50012243A /* DLGPlayerRotationScaleVertexShader.glsl */, + 23DC292221B810B50012243A /* DLGPlayerYUVFragmentShader.glsl */, + 23DC292321B810B50012243A /* DLGPlayerRGBFragmentShader.glsl */, + 23DC292521B810B50012243A /* DLGPlayerRotationVertexShader.glsl */, + 23DC292621B810B50012243A /* DLGPlayerVertexShader.glsl */, + ); + path = resource; + sourceTree = ""; + }; + 23DC292721B810B50012243A /* frame */ = { + isa = PBXGroup; + children = ( + 23DC292821B810B50012243A /* DLGPlayerVideoYUVFrame.h */, + 23DC292921B810B50012243A /* DLGPlayerVideoFrame.h */, + 23DC292A21B810B50012243A /* DLGPlayerVideoRGBFrame.m */, + 23DC292B21B810B50012243A /* DLGPlayerAudioFrame.m */, + 23DC292C21B810B50012243A /* DLGPlayerFrame.h */, + 23DC292D21B810B50012243A /* DLGPlayerVideoRGBFrame.h */, + 23DC292E21B810B50012243A /* DLGPlayerVideoFrame.m */, + 23DC292F21B810B50012243A /* DLGPlayerVideoYUVFrame.m */, + 23DC293021B810B50012243A /* DLGPlayerAudioFrame.h */, + 23DC293121B810B50012243A /* DLGPlayerFrame.m */, + ); + path = frame; + sourceTree = ""; + }; + 23DC293221B810B50012243A /* view */ = { + isa = PBXGroup; + children = ( + 23DC293321B810B50012243A /* DLGPlayerView.m */, + 23DC293421B810B50012243A /* DLGPlayerView.h */, + ); + path = view; + sourceTree = ""; + }; + 23DC293521B810B50012243A /* common */ = { + isa = PBXGroup; + children = ( + 23DC293621B810B50012243A /* DLGPlayerDef.h */, + 23DC293721B810B50012243A /* DLGPlayerUtils.h */, + 23DC293821B810B50012243A /* DLGPlayerUtils.m */, + ); + path = common; + sourceTree = ""; + }; + 23DC295D21B814470012243A /* Frameworks */ = { + isa = PBXGroup; + children = ( + 23DC297221B8148B0012243A /* libiconv.tbd */, + 23DC297021B814830012243A /* libz.tbd */, + 23DC296E21B8147A0012243A /* libbz2.tbd */, + 23DC296C21B814730012243A /* CoreAudio.framework */, + 23DC296A21B8146D0012243A /* CoreGraphics.framework */, + 23DC296821B8145F0012243A /* AudioToolbox.framework */, + 23DC296621B8145B0012243A /* MediaPlayer.framework */, + 23DC296421B814560012243A /* CoreMedia.framework */, + 23DC296221B814520012243A /* QuartzCore.framework */, + 23DC296021B8144D0012243A /* OpenGLES.framework */, + 23DC295E21B814470012243A /* AVFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 23DC26C921B80F5A0012243A /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 23DC293E21B810B50012243A /* DLGPlayer.h in Headers */, + 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 23DC26CD21B80F5A0012243A /* DLGPlayer */ = { + isa = PBXNativeTarget; + buildConfigurationList = 23DC26E221B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayer" */; + buildPhases = ( + 236E380F21B8AA76009C6879 /* ShellScript */, + 23DC26C921B80F5A0012243A /* Headers */, + 23DC26CA21B80F5A0012243A /* Sources */, + 23DC26CB21B80F5A0012243A /* Frameworks */, + 23DC26CC21B80F5A0012243A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DLGPlayer; + productName = DLGPlayer; + productReference = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; + productType = "com.apple.product-type.framework"; + }; + 23DC26D621B80F5A0012243A /* DLGPlayerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 23DC26E521B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayerTests" */; + buildPhases = ( + 23DC26D321B80F5A0012243A /* Sources */, + 23DC26D421B80F5A0012243A /* Frameworks */, + 23DC26D521B80F5A0012243A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 23DC26DA21B80F5A0012243A /* PBXTargetDependency */, + ); + name = DLGPlayerTests; + productName = DLGPlayerTests; + productReference = 23DC26D721B80F5A0012243A /* DLGPlayerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 23DC26C521B80F5A0012243A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1010; + ORGANIZATIONNAME = "KWANG HYOUN KIM"; + TargetAttributes = { + 23DC26CD21B80F5A0012243A = { + CreatedOnToolsVersion = 10.1; + }; + 23DC26D621B80F5A0012243A = { + CreatedOnToolsVersion = 10.1; + }; + }; + }; + buildConfigurationList = 23DC26C821B80F5A0012243A /* Build configuration list for PBXProject "DLGPlayer" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + "zh-Hans", + Base, + ); + mainGroup = 23DC26C421B80F5A0012243A; + productRefGroup = 23DC26CF21B80F5A0012243A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 23DC26CD21B80F5A0012243A /* DLGPlayer */, + 23DC26D621B80F5A0012243A /* DLGPlayerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 23DC26CC21B80F5A0012243A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 23DC294221B810B50012243A /* DLGPlayerRotationScaleVertexShader.glsl in Resources */, + 23DC294521B810B50012243A /* DLGPlayerRotationVertexShader.glsl in Resources */, + 23DC294421B810B50012243A /* DLGPlayerRGBFragmentShader.glsl in Resources */, + 23DC294621B810B50012243A /* DLGPlayerVertexShader.glsl in Resources */, + 23DC294121B810B50012243A /* DLGPlayerStrings.strings in Resources */, + 23DC294321B810B50012243A /* DLGPlayerYUVFragmentShader.glsl in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 23DC26D521B80F5A0012243A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 236E380F21B8AA76009C6879 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 12; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/pre-build.sh\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 23DC26CA21B80F5A0012243A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 23DC293A21B810B50012243A /* DLGPlayerDecoder.m in Sources */, + 23DC293B21B810B50012243A /* DLGPlayerAudioManager.m in Sources */, + 23DC294021B810B50012243A /* DLGPlayer.m in Sources */, + 23DC294D21B810B50012243A /* DLGPlayerVideoFrame.m in Sources */, + 23DC295521B810B50012243A /* DLGPlayerUtils.m in Sources */, + 23DC295021B810B50012243A /* DLGPlayerFrame.m in Sources */, + 23DC294A21B810B50012243A /* DLGPlayerAudioFrame.m in Sources */, + 23DC294E21B810B50012243A /* DLGPlayerVideoYUVFrame.m in Sources */, + 23DC295121B810B50012243A /* DLGPlayerView.m in Sources */, + 23DC293F21B810B50012243A /* DLGPlayerViewController.m in Sources */, + 23DC294921B810B50012243A /* DLGPlayerVideoRGBFrame.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 23DC26D321B80F5A0012243A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 23DC26DA21B80F5A0012243A /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 23DC26CD21B80F5A0012243A /* DLGPlayer */; + targetProxy = 23DC26D921B80F5A0012243A /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 23DC291E21B810B50012243A /* DLGPlayerStrings.strings */ = { + isa = PBXVariantGroup; + children = ( + 23DC291F21B810B50012243A /* zh-Hans */, + 23DC292021B810B50012243A /* en */, + 23DC292421B810B50012243A /* Base */, + ); + name = DLGPlayerStrings.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 23DC26E021B80F5A0012243A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 23DC26E121B80F5A0012243A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 23DC26E321B80F5A0012243A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${SRCROOT}/ffmpeg/FFmpeg-iOS/include", + ); + INFOPLIST_FILE = DLGPlayer/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "${SRCROOT}/ffmpeg/lib", + "$(PROJECT_DIR)/ffmpeg/FFmpeg-iOS/lib", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-l\"avcodec\"", + "-l\"avdevice\"", + "-l\"avfilter\"", + "-l\"avformat\"", + "-l\"avutil\"", + "-l\"bz2\"", + "-l\"iconv\"", + "-l\"swresample\"", + "-l\"swscale\"", + "-l\"z\"", + "-framework", + "\"OpenGLES\"", + "-framework", + "\"AVFoundation\"", + "-framework", + "\"Accelerate\"", + "-framework", + "\"AudioToolbox\"", + "-framework", + "\"CoreAudio\"", + "-framework", + "\"CoreGraphics\"", + "-framework", + "\"CoreMedia\"", + "-framework", + "\"MediaPlayer\"", + "-framework", + "\"QuartzCore\"", + "-framework", + "\"VideoToolbox\"", + ); + PRODUCT_BUNDLE_IDENTIFIER = carthage.DLGPlayer; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 23DC26E421B80F5A0012243A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${SRCROOT}/ffmpeg/FFmpeg-iOS/include", + ); + INFOPLIST_FILE = DLGPlayer/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "${SRCROOT}/ffmpeg/lib", + "$(PROJECT_DIR)/ffmpeg/FFmpeg-iOS/lib", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-l\"avcodec\"", + "-l\"avdevice\"", + "-l\"avfilter\"", + "-l\"avformat\"", + "-l\"avutil\"", + "-l\"bz2\"", + "-l\"iconv\"", + "-l\"swresample\"", + "-l\"swscale\"", + "-l\"z\"", + "-framework", + "\"OpenGLES\"", + "-framework", + "\"AVFoundation\"", + "-framework", + "\"Accelerate\"", + "-framework", + "\"AudioToolbox\"", + "-framework", + "\"CoreAudio\"", + "-framework", + "\"CoreGraphics\"", + "-framework", + "\"CoreMedia\"", + "-framework", + "\"MediaPlayer\"", + "-framework", + "\"QuartzCore\"", + "-framework", + "\"VideoToolbox\"", + ); + PRODUCT_BUNDLE_IDENTIFIER = carthage.DLGPlayer; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 23DC26E621B80F5A0012243A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = DLGPlayerTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = pisces.libs.DLGPlayerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 23DC26E721B80F5A0012243A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = DLGPlayerTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = pisces.libs.DLGPlayerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 23DC26C821B80F5A0012243A /* Build configuration list for PBXProject "DLGPlayer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 23DC26E021B80F5A0012243A /* Debug */, + 23DC26E121B80F5A0012243A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 23DC26E221B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayer" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 23DC26E321B80F5A0012243A /* Debug */, + 23DC26E421B80F5A0012243A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 23DC26E521B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 23DC26E621B80F5A0012243A /* Debug */, + 23DC26E721B80F5A0012243A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 23DC26C521B80F5A0012243A /* Project object */; +} diff --git a/DLGPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/DLGPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..8392ea7 --- /dev/null +++ b/DLGPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/DLGPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/DLGPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/DLGPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme new file mode 100644 index 0000000..e48435b --- /dev/null +++ b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example-Carthage/DLGPlayerDemo/Cartfile b/Example-Carthage/DLGPlayerDemo/Cartfile new file mode 100755 index 0000000..0c597d2 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/Cartfile @@ -0,0 +1,2 @@ +github "Alamofire/Alamofire" ~> 4.5 +github "pisces/DLGPlayer" "master" diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.pbxproj b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..cae5561 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.pbxproj @@ -0,0 +1,340 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 23ACE06221B8CE3300805028 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 23ACE06121B8CE3300805028 /* AppDelegate.m */; }; + 23ACE06521B8CE3300805028 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 23ACE06421B8CE3300805028 /* ViewController.m */; }; + 23ACE06821B8CE3300805028 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 23ACE06621B8CE3300805028 /* Main.storyboard */; }; + 23ACE06A21B8CE3400805028 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23ACE06921B8CE3400805028 /* Assets.xcassets */; }; + 23ACE06D21B8CE3400805028 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 23ACE06B21B8CE3400805028 /* LaunchScreen.storyboard */; }; + 23ACE07021B8CE3400805028 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 23ACE06F21B8CE3400805028 /* main.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 23ACE05D21B8CE3300805028 /* DLGPlayerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DLGPlayerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 23ACE06021B8CE3300805028 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 23ACE06121B8CE3300805028 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 23ACE06321B8CE3300805028 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 23ACE06421B8CE3300805028 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 23ACE06721B8CE3300805028 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 23ACE06921B8CE3400805028 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 23ACE06C21B8CE3400805028 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 23ACE06E21B8CE3400805028 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 23ACE06F21B8CE3400805028 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 23ACE05A21B8CE3300805028 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 23ACE05421B8CE3300805028 = { + isa = PBXGroup; + children = ( + 23ACE05F21B8CE3300805028 /* DLGPlayerDemo */, + 23ACE05E21B8CE3300805028 /* Products */, + ); + sourceTree = ""; + }; + 23ACE05E21B8CE3300805028 /* Products */ = { + isa = PBXGroup; + children = ( + 23ACE05D21B8CE3300805028 /* DLGPlayerDemo.app */, + ); + name = Products; + sourceTree = ""; + }; + 23ACE05F21B8CE3300805028 /* DLGPlayerDemo */ = { + isa = PBXGroup; + children = ( + 23ACE06021B8CE3300805028 /* AppDelegate.h */, + 23ACE06121B8CE3300805028 /* AppDelegate.m */, + 23ACE06321B8CE3300805028 /* ViewController.h */, + 23ACE06421B8CE3300805028 /* ViewController.m */, + 23ACE06621B8CE3300805028 /* Main.storyboard */, + 23ACE06921B8CE3400805028 /* Assets.xcassets */, + 23ACE06B21B8CE3400805028 /* LaunchScreen.storyboard */, + 23ACE06E21B8CE3400805028 /* Info.plist */, + 23ACE06F21B8CE3400805028 /* main.m */, + ); + path = DLGPlayerDemo; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 23ACE05C21B8CE3300805028 /* DLGPlayerDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 23ACE07321B8CE3400805028 /* Build configuration list for PBXNativeTarget "DLGPlayerDemo" */; + buildPhases = ( + 23ACE05921B8CE3300805028 /* Sources */, + 23ACE05A21B8CE3300805028 /* Frameworks */, + 23ACE05B21B8CE3300805028 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DLGPlayerDemo; + productName = DLGPlayerDemo; + productReference = 23ACE05D21B8CE3300805028 /* DLGPlayerDemo.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 23ACE05521B8CE3300805028 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1010; + ORGANIZATIONNAME = "KWANG HYOUN KIM"; + TargetAttributes = { + 23ACE05C21B8CE3300805028 = { + CreatedOnToolsVersion = 10.1; + }; + }; + }; + buildConfigurationList = 23ACE05821B8CE3300805028 /* Build configuration list for PBXProject "DLGPlayerDemo" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 23ACE05421B8CE3300805028; + productRefGroup = 23ACE05E21B8CE3300805028 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 23ACE05C21B8CE3300805028 /* DLGPlayerDemo */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 23ACE05B21B8CE3300805028 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 23ACE06D21B8CE3400805028 /* LaunchScreen.storyboard in Resources */, + 23ACE06A21B8CE3400805028 /* Assets.xcassets in Resources */, + 23ACE06821B8CE3300805028 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 23ACE05921B8CE3300805028 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 23ACE06521B8CE3300805028 /* ViewController.m in Sources */, + 23ACE07021B8CE3400805028 /* main.m in Sources */, + 23ACE06221B8CE3300805028 /* AppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 23ACE06621B8CE3300805028 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 23ACE06721B8CE3300805028 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 23ACE06B21B8CE3400805028 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 23ACE06C21B8CE3400805028 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 23ACE07121B8CE3400805028 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 23ACE07221B8CE3400805028 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 23ACE07421B8CE3400805028 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = DLGPlayerDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 23ACE07521B8CE3400805028 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = DLGPlayerDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 23ACE05821B8CE3300805028 /* Build configuration list for PBXProject "DLGPlayerDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 23ACE07121B8CE3400805028 /* Debug */, + 23ACE07221B8CE3400805028 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 23ACE07321B8CE3400805028 /* Build configuration list for PBXNativeTarget "DLGPlayerDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 23ACE07421B8CE3400805028 /* Debug */, + 23ACE07521B8CE3400805028 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 23ACE05521B8CE3300805028 /* Project object */; +} diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..d849187 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.h b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.h new file mode 100644 index 0000000..ce66c54 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.h @@ -0,0 +1,17 @@ +// +// AppDelegate.h +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 06/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.m b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.m new file mode 100644 index 0000000..319ce72 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.m @@ -0,0 +1,51 @@ +// +// AppDelegate.m +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 06/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Override point for customization after application launch. + return YES; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + + +@end diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d8db8d6 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/Contents.json b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..bfa3612 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/Main.storyboard b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/Main.storyboard new file mode 100644 index 0000000..942f0bc --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Info.plist b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Info.plist new file mode 100644 index 0000000..16be3b6 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.h b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.h new file mode 100644 index 0000000..66c604d --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.h @@ -0,0 +1,15 @@ +// +// ViewController.h +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 06/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +#import + +@interface ViewController : UIViewController + + +@end + diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.m b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.m new file mode 100644 index 0000000..e4ab17c --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.m @@ -0,0 +1,23 @@ +// +// ViewController.m +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 06/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +#import "ViewController.h" + +@interface ViewController () + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view, typically from a nib. +} + + +@end diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/main.m b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/main.m new file mode 100644 index 0000000..4a4309f --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/main.m @@ -0,0 +1,16 @@ +// +// main.m +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 06/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/Example-Carthage/DLGPlayerDemo/Scripts/carthage_xconfig.rb b/Example-Carthage/DLGPlayerDemo/Scripts/carthage_xconfig.rb new file mode 100644 index 0000000..615e01a --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/Scripts/carthage_xconfig.rb @@ -0,0 +1,179 @@ +require 'xcodeproj' + +class String +def black; "\e[30m#{self}\e[0m" end +def red; "\e[31m#{self}\e[0m" end +def green; "\e[32m#{self}\e[0m" end +def brown; "\e[33m#{self}\e[0m" end +def blue; "\e[34m#{self}\e[0m" end +def magenta; "\e[35m#{self}\e[0m" end +def cyan; "\e[36m#{self}\e[0m" end +def gray; "\e[37m#{self}\e[0m" end + +def bg_black; "\e[40m#{self}\e[0m" end +def bg_red; "\e[41m#{self}\e[0m" end +def bg_green; "\e[42m#{self}\e[0m" end +def bg_brown; "\e[43m#{self}\e[0m" end +def bg_blue; "\e[44m#{self}\e[0m" end +def bg_magenta; "\e[45m#{self}\e[0m" end +def bg_cyan; "\e[46m#{self}\e[0m" end +def bg_gray; "\e[47m#{self}\e[0m" end + +def bold; "\e[1m#{self}\e[22m" end +def italic; "\e[3m#{self}\e[23m" end +def underline; "\e[4m#{self}\e[24m" end +def blink; "\e[5m#{self}\e[25m" end +def reverse_color; "\e[7m#{self}\e[27m" end +end + +# Constants +EMBED_CARTHAGE_FRAMEWORKS_NAME = "Embed Carthage Frameworks" +OTHER_LINKER_FLAGS = "$(inherited) -enable-bridging-pch" +OTHER_FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Libraries" +FRAMEWORK_SEARCH_PATHS = "$(inherited) $(PROJECT_DIR)/Carthage/Build/iOS ${OTHER_FRAMEWORK_SEARCH_PATHS}" +REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES = "Remove Unwanted Framework Architectures" +REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES_SCRIPT = ' +APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}" + +# This script loops through the frameworks embedded in the application and +# removes unused architectures. +find "$APP_PATH" -name \'*.framework\' -type d | while read -r FRAMEWORK +do +FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable) +FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME" +echo "Executable is $FRAMEWORK_EXECUTABLE_PATH" + +EXTRACTED_ARCHS=() + +for ARCH in $ARCHS +do +echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME" +lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH" +EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH") +done + +echo "Merging extracted architectures: ${ARCHS}" +lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}" +rm "${EXTRACTED_ARCHS[@]}" + +echo "Replacing original executable with thinned version" +rm "$FRAMEWORK_EXECUTABLE_PATH" +mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH" + +done' + +projectName = Dir["../*.xcodeproj"] + +if projectName.nil? + abort("Does not exist project to config!") +end + +puts "💎💎 Project Found -> #{projectName} 💎💎" + +# Variables +@project = Xcodeproj::Project.open(projectName) + +# Methods +def create_embed_frameworks_build_phase + build_phase = @project.new(Xcodeproj::Project::Object::PBXCopyFilesBuildPhase) + build_phase.name = EMBED_CARTHAGE_FRAMEWORKS_NAME + build_phase.symbol_dst_subfolder_spec = :frameworks + return build_phase +end + +def create_shell_script_build_phase(name) + build_phase = @project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) + build_phase.name = name + return build_phase +end + +def add_embedded_binaries(build_phase) + input_paths = [] + + Dir.entries('../Carthage/Build/iOS').each do |entry| + matched = /^(.*)\.framework$/.match(entry) + + if !matched.nil? + frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' } + framework_ref = frameworks_group.new_file("Carthage/Build/iOS/#{matched.string}") + build_file = build_phase.add_file_reference(framework_ref) + build_file.settings = { 'ATTRIBUTES' => ['CodeSignOnCopy', 'RemoveHeadersOnCopy'] } + input_paths.push("${SRCROOT}/Carthage/Build/iOS/#{matched.string}") + puts "framework_ref -> #{framework_ref}".gray + end + end +end + +def add_input_files(build_phase) + input_paths = [] + + Dir.entries('../Carthage/Build/iOS').each do |entry| + matched = /^(.*)\.framework$/.match(entry) + if !matched.nil? + input_paths.push("${SRCROOT}/Carthage/Build/iOS/#{matched.string}") + end + end + + build_phase.input_paths = input_paths + + puts "add input files to run script -> #{input_paths}".gray +end + +def write_xcodeproj + puts "🙏 Start xconfig..".green + + new_build_phase = nil + new_arch_build_phase = nil + + @project.targets.each do |target| + puts "👻 build target -> #{target.name}" + + exist_build_phase = target.build_phases.find { |build_phase| build_phase.class == Xcodeproj::Project::Object::PBXCopyFilesBuildPhase && build_phase.name == EMBED_CARTHAGE_FRAMEWORKS_NAME } + exist_arch_build_phase = target.build_phases.find { |build_phase| build_phase.class == Xcodeproj::Project::Object::PBXShellScriptBuildPhase && build_phase.name == REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES } + + if !exist_build_phase.nil? + puts "delete exist embed carthage framework".gray + exist_build_phase.files_references.each do |reference| + reference.remove_from_project + end + exist_build_phase.clear + target.build_phases.delete(exist_build_phase) + end + + if new_build_phase.nil? + new_build_phase = create_embed_frameworks_build_phase + add_embedded_binaries(new_build_phase) + puts "create new embed carthage framework -> #{new_build_phase}".gray + end + + if !exist_arch_build_phase.nil? + puts "delete exist remove unwanted framework architectures".gray + exist_arch_build_phase.clear + target.build_phases.delete(exist_arch_build_phase) + end + + if new_arch_build_phase.nil? + new_arch_build_phase = create_shell_script_build_phase(REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES) + new_arch_build_phase.shell_script = REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES_SCRIPT + # add_input_files(new_arch_build_phase) + puts "create new remove unwanted framework architectures -> #{new_arch_build_phase}".gray + end + + target.build_phases << new_build_phase + target.build_phases << new_arch_build_phase + + puts "#{target.build_configurations}" + + target.build_configurations.each do |config| + config.build_settings['FRAMEWORK_SEARCH_PATHS'] = FRAMEWORK_SEARCH_PATHS + puts "#{config}: set up FRAMEWORK_SEARCH_PATHS of build_settings to #{FRAMEWORK_SEARCH_PATHS}".gray + end + puts "\n" + end + + @project.save() + + puts "👌 Finish xconfig..".green +end + +write_xcodeproj() diff --git a/Example-Carthage/DLGPlayerDemo/Scripts/lib-update.sh b/Example-Carthage/DLGPlayerDemo/Scripts/lib-update.sh new file mode 100755 index 0000000..fb8fa73 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/Scripts/lib-update.sh @@ -0,0 +1,33 @@ +if ! gem spec xcodeproj > /dev/null 2>&1; then + sudo gem install xcodeproj +fi + +if ! brew ls --versions carthage > /dev/null 2>&1; then + brew install carthage +fi + +useclean=false + +for i in "$@" +do +case $i in + --use-clean) + useclean=true + ;; +esac +done + +cd .. + +if $useclean ; then + pod clean + rm -rf ./Carthage +fi + +pod install +# carthage update --no-use-binaries --platform iOS +carthage update --platform ios --no-use-binaries --use-ssh +# carthage update --no-checkout --no-build --no-use-binaries --platform iOS + +cd Scripts +ruby carthage_xconfig.rb diff --git a/pre-build.sh b/pre-build.sh new file mode 100755 index 0000000..5784920 --- /dev/null +++ b/pre-build.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +BUILD_FFMPEG_FILE="build-ffmpeg.sh" +FFMPEG_IOS_BUILD_FILE_URL="https://github.com/kewlbear/FFmpeg-iOS-build-script/raw/master/$BUILD_FFMPEG_FILE" +FFMPEG_OUTPUT_FOLDER="ffmpeg" + +function MakeFFmpegDir() { + if [ ! -d "$FFMPEG_OUTPUT_FOLDER" ] + then + mkdir $FFMPEG_OUTPUT_FOLDER + fi + cd $FFMPEG_OUTPUT_FOLDER +} +function DownloadFFmpegBuildScript() { + if [ -f "$BUILD_FFMPEG_FILE" ] + then + echo "Already exist file $BUILD_FFMPEG_FILE." + else + (curl --verbose -L "$FFMPEG_IOS_BUILD_FILE_URL" \ + -o ./$BUILD_FFMPEG_FILE \ + && chmod +x ./$BUILD_FFMPEG_FILE) \ + || exit 1 + fi +} + +function CompileFFmpeg() { + if [ -d "./FFmpeg-iOS" ] + then + echo "Already compiled ffmpeg-ios." + else + ./$BUILD_FFMPEG_FILE + fi +} + +MakeFFmpegDir +DownloadFFmpegBuildScript +CompileFFmpeg From 0df0e328b02223d4326ca979b967b38368bf74b4 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 6 Dec 2018 15:54:35 +0900 Subject: [PATCH 004/215] Change project directories for example with carthage --- Example-Carthage/{DLGPlayerDemo => }/Cartfile | 0 .../{DLGPlayerDemo => }/DLGPlayerDemo.xcodeproj/project.pbxproj | 0 .../project.xcworkspace/contents.xcworkspacedata | 0 .../project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist | 0 Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/AppDelegate.h | 0 Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/AppDelegate.m | 0 .../Assets.xcassets/AppIcon.appiconset/Contents.json | 0 .../{DLGPlayerDemo => }/Assets.xcassets/Contents.json | 0 .../{DLGPlayerDemo => }/Base.lproj/LaunchScreen.storyboard | 0 .../DLGPlayerDemo/{DLGPlayerDemo => }/Base.lproj/Main.storyboard | 0 Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/Info.plist | 0 .../DLGPlayerDemo/{DLGPlayerDemo => }/ViewController.h | 0 .../DLGPlayerDemo/{DLGPlayerDemo => }/ViewController.m | 0 Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/main.m | 0 Example-Carthage/{DLGPlayerDemo => }/Scripts/carthage_xconfig.rb | 0 Example-Carthage/{DLGPlayerDemo => }/Scripts/lib-update.sh | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename Example-Carthage/{DLGPlayerDemo => }/Cartfile (100%) rename Example-Carthage/{DLGPlayerDemo => }/DLGPlayerDemo.xcodeproj/project.pbxproj (100%) rename Example-Carthage/{DLGPlayerDemo => }/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename Example-Carthage/{DLGPlayerDemo => }/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/AppDelegate.h (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/AppDelegate.m (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/Assets.xcassets/Contents.json (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/Base.lproj/LaunchScreen.storyboard (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/Base.lproj/Main.storyboard (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/Info.plist (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/ViewController.h (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/ViewController.m (100%) rename Example-Carthage/DLGPlayerDemo/{DLGPlayerDemo => }/main.m (100%) rename Example-Carthage/{DLGPlayerDemo => }/Scripts/carthage_xconfig.rb (100%) rename Example-Carthage/{DLGPlayerDemo => }/Scripts/lib-update.sh (100%) diff --git a/Example-Carthage/DLGPlayerDemo/Cartfile b/Example-Carthage/Cartfile similarity index 100% rename from Example-Carthage/DLGPlayerDemo/Cartfile rename to Example-Carthage/Cartfile diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.pbxproj b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.pbxproj rename to Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.h b/Example-Carthage/DLGPlayerDemo/AppDelegate.h similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.h rename to Example-Carthage/DLGPlayerDemo/AppDelegate.h diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.m b/Example-Carthage/DLGPlayerDemo/AppDelegate.m similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/AppDelegate.m rename to Example-Carthage/DLGPlayerDemo/AppDelegate.m diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/Contents.json b/Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Assets.xcassets/Contents.json rename to Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard b/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard rename to Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/Main.storyboard b/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Base.lproj/Main.storyboard rename to Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Info.plist b/Example-Carthage/DLGPlayerDemo/Info.plist similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/Info.plist rename to Example-Carthage/DLGPlayerDemo/Info.plist diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.h b/Example-Carthage/DLGPlayerDemo/ViewController.h similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.h rename to Example-Carthage/DLGPlayerDemo/ViewController.h diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.m b/Example-Carthage/DLGPlayerDemo/ViewController.m similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/ViewController.m rename to Example-Carthage/DLGPlayerDemo/ViewController.m diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/main.m b/Example-Carthage/DLGPlayerDemo/main.m similarity index 100% rename from Example-Carthage/DLGPlayerDemo/DLGPlayerDemo/main.m rename to Example-Carthage/DLGPlayerDemo/main.m diff --git a/Example-Carthage/DLGPlayerDemo/Scripts/carthage_xconfig.rb b/Example-Carthage/Scripts/carthage_xconfig.rb similarity index 100% rename from Example-Carthage/DLGPlayerDemo/Scripts/carthage_xconfig.rb rename to Example-Carthage/Scripts/carthage_xconfig.rb diff --git a/Example-Carthage/DLGPlayerDemo/Scripts/lib-update.sh b/Example-Carthage/Scripts/lib-update.sh similarity index 100% rename from Example-Carthage/DLGPlayerDemo/Scripts/lib-update.sh rename to Example-Carthage/Scripts/lib-update.sh From 4675014dbe42264bfa415d8194f85bc404a19c90 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 6 Dec 2018 16:01:30 +0900 Subject: [PATCH 005/215] Update Cartfile in example. Add "Info.plist" file to support carthage. --- DLGPlayer/Info.plist | 22 ++++++++++++++++++++++ Example-Carthage/Cartfile | 1 - 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 DLGPlayer/Info.plist diff --git a/DLGPlayer/Info.plist b/DLGPlayer/Info.plist new file mode 100644 index 0000000..e1fe4cf --- /dev/null +++ b/DLGPlayer/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/Example-Carthage/Cartfile b/Example-Carthage/Cartfile index 0c597d2..7e7f062 100755 --- a/Example-Carthage/Cartfile +++ b/Example-Carthage/Cartfile @@ -1,2 +1 @@ -github "Alamofire/Alamofire" ~> 4.5 github "pisces/DLGPlayer" "master" From 087e63c229cc8df110a9b557327a42c75eee87c9 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 6 Dec 2018 16:42:34 +0900 Subject: [PATCH 006/215] Update project setting. --- DLGPlayer.xcodeproj/project.pbxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index 77e1cd0..2c4727c 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -610,6 +610,7 @@ "${SRCROOT}/ffmpeg/lib", "$(PROJECT_DIR)/ffmpeg/FFmpeg-iOS/lib", ); + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", From 7839f6bc7addefe57066fe208a242fd2a5a03e85 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 6 Dec 2018 16:49:46 +0900 Subject: [PATCH 007/215] Remove example for carthage --- Example-Carthage/Cartfile | 1 - .../DLGPlayerDemo.xcodeproj/project.pbxproj | 340 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - Example-Carthage/DLGPlayerDemo/AppDelegate.h | 17 - Example-Carthage/DLGPlayerDemo/AppDelegate.m | 51 --- .../AppIcon.appiconset/Contents.json | 98 ----- .../Assets.xcassets/Contents.json | 6 - .../Base.lproj/LaunchScreen.storyboard | 25 -- .../DLGPlayerDemo/Base.lproj/Main.storyboard | 24 -- Example-Carthage/DLGPlayerDemo/Info.plist | 45 --- .../DLGPlayerDemo/ViewController.h | 15 - .../DLGPlayerDemo/ViewController.m | 23 -- Example-Carthage/DLGPlayerDemo/main.m | 16 - Example-Carthage/Scripts/carthage_xconfig.rb | 179 --------- Example-Carthage/Scripts/lib-update.sh | 33 -- 16 files changed, 888 deletions(-) delete mode 100755 Example-Carthage/Cartfile delete mode 100644 Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj delete mode 100644 Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 Example-Carthage/DLGPlayerDemo/AppDelegate.h delete mode 100644 Example-Carthage/DLGPlayerDemo/AppDelegate.m delete mode 100644 Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json delete mode 100644 Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard delete mode 100644 Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard delete mode 100644 Example-Carthage/DLGPlayerDemo/Info.plist delete mode 100644 Example-Carthage/DLGPlayerDemo/ViewController.h delete mode 100644 Example-Carthage/DLGPlayerDemo/ViewController.m delete mode 100644 Example-Carthage/DLGPlayerDemo/main.m delete mode 100644 Example-Carthage/Scripts/carthage_xconfig.rb delete mode 100755 Example-Carthage/Scripts/lib-update.sh diff --git a/Example-Carthage/Cartfile b/Example-Carthage/Cartfile deleted file mode 100755 index 7e7f062..0000000 --- a/Example-Carthage/Cartfile +++ /dev/null @@ -1 +0,0 @@ -github "pisces/DLGPlayer" "master" diff --git a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj deleted file mode 100644 index cae5561..0000000 --- a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,340 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 50; - objects = { - -/* Begin PBXBuildFile section */ - 23ACE06221B8CE3300805028 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 23ACE06121B8CE3300805028 /* AppDelegate.m */; }; - 23ACE06521B8CE3300805028 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 23ACE06421B8CE3300805028 /* ViewController.m */; }; - 23ACE06821B8CE3300805028 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 23ACE06621B8CE3300805028 /* Main.storyboard */; }; - 23ACE06A21B8CE3400805028 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 23ACE06921B8CE3400805028 /* Assets.xcassets */; }; - 23ACE06D21B8CE3400805028 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 23ACE06B21B8CE3400805028 /* LaunchScreen.storyboard */; }; - 23ACE07021B8CE3400805028 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 23ACE06F21B8CE3400805028 /* main.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 23ACE05D21B8CE3300805028 /* DLGPlayerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DLGPlayerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 23ACE06021B8CE3300805028 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - 23ACE06121B8CE3300805028 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 23ACE06321B8CE3300805028 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - 23ACE06421B8CE3300805028 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; - 23ACE06721B8CE3300805028 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 23ACE06921B8CE3400805028 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 23ACE06C21B8CE3400805028 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 23ACE06E21B8CE3400805028 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 23ACE06F21B8CE3400805028 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 23ACE05A21B8CE3300805028 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 23ACE05421B8CE3300805028 = { - isa = PBXGroup; - children = ( - 23ACE05F21B8CE3300805028 /* DLGPlayerDemo */, - 23ACE05E21B8CE3300805028 /* Products */, - ); - sourceTree = ""; - }; - 23ACE05E21B8CE3300805028 /* Products */ = { - isa = PBXGroup; - children = ( - 23ACE05D21B8CE3300805028 /* DLGPlayerDemo.app */, - ); - name = Products; - sourceTree = ""; - }; - 23ACE05F21B8CE3300805028 /* DLGPlayerDemo */ = { - isa = PBXGroup; - children = ( - 23ACE06021B8CE3300805028 /* AppDelegate.h */, - 23ACE06121B8CE3300805028 /* AppDelegate.m */, - 23ACE06321B8CE3300805028 /* ViewController.h */, - 23ACE06421B8CE3300805028 /* ViewController.m */, - 23ACE06621B8CE3300805028 /* Main.storyboard */, - 23ACE06921B8CE3400805028 /* Assets.xcassets */, - 23ACE06B21B8CE3400805028 /* LaunchScreen.storyboard */, - 23ACE06E21B8CE3400805028 /* Info.plist */, - 23ACE06F21B8CE3400805028 /* main.m */, - ); - path = DLGPlayerDemo; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 23ACE05C21B8CE3300805028 /* DLGPlayerDemo */ = { - isa = PBXNativeTarget; - buildConfigurationList = 23ACE07321B8CE3400805028 /* Build configuration list for PBXNativeTarget "DLGPlayerDemo" */; - buildPhases = ( - 23ACE05921B8CE3300805028 /* Sources */, - 23ACE05A21B8CE3300805028 /* Frameworks */, - 23ACE05B21B8CE3300805028 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = DLGPlayerDemo; - productName = DLGPlayerDemo; - productReference = 23ACE05D21B8CE3300805028 /* DLGPlayerDemo.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 23ACE05521B8CE3300805028 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1010; - ORGANIZATIONNAME = "KWANG HYOUN KIM"; - TargetAttributes = { - 23ACE05C21B8CE3300805028 = { - CreatedOnToolsVersion = 10.1; - }; - }; - }; - buildConfigurationList = 23ACE05821B8CE3300805028 /* Build configuration list for PBXProject "DLGPlayerDemo" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 23ACE05421B8CE3300805028; - productRefGroup = 23ACE05E21B8CE3300805028 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 23ACE05C21B8CE3300805028 /* DLGPlayerDemo */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 23ACE05B21B8CE3300805028 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 23ACE06D21B8CE3400805028 /* LaunchScreen.storyboard in Resources */, - 23ACE06A21B8CE3400805028 /* Assets.xcassets in Resources */, - 23ACE06821B8CE3300805028 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 23ACE05921B8CE3300805028 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 23ACE06521B8CE3300805028 /* ViewController.m in Sources */, - 23ACE07021B8CE3400805028 /* main.m in Sources */, - 23ACE06221B8CE3300805028 /* AppDelegate.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 23ACE06621B8CE3300805028 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 23ACE06721B8CE3300805028 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 23ACE06B21B8CE3400805028 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 23ACE06C21B8CE3400805028 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 23ACE07121B8CE3400805028 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 23ACE07221B8CE3400805028 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 23ACE07421B8CE3400805028 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = DLGPlayerDemo/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemo; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 23ACE07521B8CE3400805028 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = DLGPlayerDemo/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemo; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 23ACE05821B8CE3300805028 /* Build configuration list for PBXProject "DLGPlayerDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 23ACE07121B8CE3400805028 /* Debug */, - 23ACE07221B8CE3400805028 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 23ACE07321B8CE3400805028 /* Build configuration list for PBXNativeTarget "DLGPlayerDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 23ACE07421B8CE3400805028 /* Debug */, - 23ACE07521B8CE3400805028 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 23ACE05521B8CE3300805028 /* Project object */; -} diff --git a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index d849187..0000000 --- a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Example-Carthage/DLGPlayerDemo/AppDelegate.h b/Example-Carthage/DLGPlayerDemo/AppDelegate.h deleted file mode 100644 index ce66c54..0000000 --- a/Example-Carthage/DLGPlayerDemo/AppDelegate.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// AppDelegate.h -// DLGPlayerDemo -// -// Created by KWANG HYOUN KIM on 06/12/2018. -// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. -// - -#import - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - - -@end - diff --git a/Example-Carthage/DLGPlayerDemo/AppDelegate.m b/Example-Carthage/DLGPlayerDemo/AppDelegate.m deleted file mode 100644 index 319ce72..0000000 --- a/Example-Carthage/DLGPlayerDemo/AppDelegate.m +++ /dev/null @@ -1,51 +0,0 @@ -// -// AppDelegate.m -// DLGPlayerDemo -// -// Created by KWANG HYOUN KIM on 06/12/2018. -// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. -// - -#import "AppDelegate.h" - -@interface AppDelegate () - -@end - -@implementation AppDelegate - - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Override point for customization after application launch. - return YES; -} - - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. -} - - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. -} - - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - - -@end diff --git a/Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d8db8d6..0000000 --- a/Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - }, - { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json b/Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json deleted file mode 100644 index da4a164..0000000 --- a/Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard b/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index bfa3612..0000000 --- a/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard b/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard deleted file mode 100644 index 942f0bc..0000000 --- a/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example-Carthage/DLGPlayerDemo/Info.plist b/Example-Carthage/DLGPlayerDemo/Info.plist deleted file mode 100644 index 16be3b6..0000000 --- a/Example-Carthage/DLGPlayerDemo/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/Example-Carthage/DLGPlayerDemo/ViewController.h b/Example-Carthage/DLGPlayerDemo/ViewController.h deleted file mode 100644 index 66c604d..0000000 --- a/Example-Carthage/DLGPlayerDemo/ViewController.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// ViewController.h -// DLGPlayerDemo -// -// Created by KWANG HYOUN KIM on 06/12/2018. -// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. -// - -#import - -@interface ViewController : UIViewController - - -@end - diff --git a/Example-Carthage/DLGPlayerDemo/ViewController.m b/Example-Carthage/DLGPlayerDemo/ViewController.m deleted file mode 100644 index e4ab17c..0000000 --- a/Example-Carthage/DLGPlayerDemo/ViewController.m +++ /dev/null @@ -1,23 +0,0 @@ -// -// ViewController.m -// DLGPlayerDemo -// -// Created by KWANG HYOUN KIM on 06/12/2018. -// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. -// - -#import "ViewController.h" - -@interface ViewController () - -@end - -@implementation ViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view, typically from a nib. -} - - -@end diff --git a/Example-Carthage/DLGPlayerDemo/main.m b/Example-Carthage/DLGPlayerDemo/main.m deleted file mode 100644 index 4a4309f..0000000 --- a/Example-Carthage/DLGPlayerDemo/main.m +++ /dev/null @@ -1,16 +0,0 @@ -// -// main.m -// DLGPlayerDemo -// -// Created by KWANG HYOUN KIM on 06/12/2018. -// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. -// - -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) { - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/Example-Carthage/Scripts/carthage_xconfig.rb b/Example-Carthage/Scripts/carthage_xconfig.rb deleted file mode 100644 index 615e01a..0000000 --- a/Example-Carthage/Scripts/carthage_xconfig.rb +++ /dev/null @@ -1,179 +0,0 @@ -require 'xcodeproj' - -class String -def black; "\e[30m#{self}\e[0m" end -def red; "\e[31m#{self}\e[0m" end -def green; "\e[32m#{self}\e[0m" end -def brown; "\e[33m#{self}\e[0m" end -def blue; "\e[34m#{self}\e[0m" end -def magenta; "\e[35m#{self}\e[0m" end -def cyan; "\e[36m#{self}\e[0m" end -def gray; "\e[37m#{self}\e[0m" end - -def bg_black; "\e[40m#{self}\e[0m" end -def bg_red; "\e[41m#{self}\e[0m" end -def bg_green; "\e[42m#{self}\e[0m" end -def bg_brown; "\e[43m#{self}\e[0m" end -def bg_blue; "\e[44m#{self}\e[0m" end -def bg_magenta; "\e[45m#{self}\e[0m" end -def bg_cyan; "\e[46m#{self}\e[0m" end -def bg_gray; "\e[47m#{self}\e[0m" end - -def bold; "\e[1m#{self}\e[22m" end -def italic; "\e[3m#{self}\e[23m" end -def underline; "\e[4m#{self}\e[24m" end -def blink; "\e[5m#{self}\e[25m" end -def reverse_color; "\e[7m#{self}\e[27m" end -end - -# Constants -EMBED_CARTHAGE_FRAMEWORKS_NAME = "Embed Carthage Frameworks" -OTHER_LINKER_FLAGS = "$(inherited) -enable-bridging-pch" -OTHER_FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Libraries" -FRAMEWORK_SEARCH_PATHS = "$(inherited) $(PROJECT_DIR)/Carthage/Build/iOS ${OTHER_FRAMEWORK_SEARCH_PATHS}" -REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES = "Remove Unwanted Framework Architectures" -REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES_SCRIPT = ' -APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}" - -# This script loops through the frameworks embedded in the application and -# removes unused architectures. -find "$APP_PATH" -name \'*.framework\' -type d | while read -r FRAMEWORK -do -FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable) -FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME" -echo "Executable is $FRAMEWORK_EXECUTABLE_PATH" - -EXTRACTED_ARCHS=() - -for ARCH in $ARCHS -do -echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME" -lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH" -EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH") -done - -echo "Merging extracted architectures: ${ARCHS}" -lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}" -rm "${EXTRACTED_ARCHS[@]}" - -echo "Replacing original executable with thinned version" -rm "$FRAMEWORK_EXECUTABLE_PATH" -mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH" - -done' - -projectName = Dir["../*.xcodeproj"] - -if projectName.nil? - abort("Does not exist project to config!") -end - -puts "💎💎 Project Found -> #{projectName} 💎💎" - -# Variables -@project = Xcodeproj::Project.open(projectName) - -# Methods -def create_embed_frameworks_build_phase - build_phase = @project.new(Xcodeproj::Project::Object::PBXCopyFilesBuildPhase) - build_phase.name = EMBED_CARTHAGE_FRAMEWORKS_NAME - build_phase.symbol_dst_subfolder_spec = :frameworks - return build_phase -end - -def create_shell_script_build_phase(name) - build_phase = @project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) - build_phase.name = name - return build_phase -end - -def add_embedded_binaries(build_phase) - input_paths = [] - - Dir.entries('../Carthage/Build/iOS').each do |entry| - matched = /^(.*)\.framework$/.match(entry) - - if !matched.nil? - frameworks_group = @project.groups.find { |group| group.display_name == 'Frameworks' } - framework_ref = frameworks_group.new_file("Carthage/Build/iOS/#{matched.string}") - build_file = build_phase.add_file_reference(framework_ref) - build_file.settings = { 'ATTRIBUTES' => ['CodeSignOnCopy', 'RemoveHeadersOnCopy'] } - input_paths.push("${SRCROOT}/Carthage/Build/iOS/#{matched.string}") - puts "framework_ref -> #{framework_ref}".gray - end - end -end - -def add_input_files(build_phase) - input_paths = [] - - Dir.entries('../Carthage/Build/iOS').each do |entry| - matched = /^(.*)\.framework$/.match(entry) - if !matched.nil? - input_paths.push("${SRCROOT}/Carthage/Build/iOS/#{matched.string}") - end - end - - build_phase.input_paths = input_paths - - puts "add input files to run script -> #{input_paths}".gray -end - -def write_xcodeproj - puts "🙏 Start xconfig..".green - - new_build_phase = nil - new_arch_build_phase = nil - - @project.targets.each do |target| - puts "👻 build target -> #{target.name}" - - exist_build_phase = target.build_phases.find { |build_phase| build_phase.class == Xcodeproj::Project::Object::PBXCopyFilesBuildPhase && build_phase.name == EMBED_CARTHAGE_FRAMEWORKS_NAME } - exist_arch_build_phase = target.build_phases.find { |build_phase| build_phase.class == Xcodeproj::Project::Object::PBXShellScriptBuildPhase && build_phase.name == REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES } - - if !exist_build_phase.nil? - puts "delete exist embed carthage framework".gray - exist_build_phase.files_references.each do |reference| - reference.remove_from_project - end - exist_build_phase.clear - target.build_phases.delete(exist_build_phase) - end - - if new_build_phase.nil? - new_build_phase = create_embed_frameworks_build_phase - add_embedded_binaries(new_build_phase) - puts "create new embed carthage framework -> #{new_build_phase}".gray - end - - if !exist_arch_build_phase.nil? - puts "delete exist remove unwanted framework architectures".gray - exist_arch_build_phase.clear - target.build_phases.delete(exist_arch_build_phase) - end - - if new_arch_build_phase.nil? - new_arch_build_phase = create_shell_script_build_phase(REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES) - new_arch_build_phase.shell_script = REMOVE_UNWANTED_FRAMEWORK_ARCHITECTURES_SCRIPT - # add_input_files(new_arch_build_phase) - puts "create new remove unwanted framework architectures -> #{new_arch_build_phase}".gray - end - - target.build_phases << new_build_phase - target.build_phases << new_arch_build_phase - - puts "#{target.build_configurations}" - - target.build_configurations.each do |config| - config.build_settings['FRAMEWORK_SEARCH_PATHS'] = FRAMEWORK_SEARCH_PATHS - puts "#{config}: set up FRAMEWORK_SEARCH_PATHS of build_settings to #{FRAMEWORK_SEARCH_PATHS}".gray - end - puts "\n" - end - - @project.save() - - puts "👌 Finish xconfig..".green -end - -write_xcodeproj() diff --git a/Example-Carthage/Scripts/lib-update.sh b/Example-Carthage/Scripts/lib-update.sh deleted file mode 100755 index fb8fa73..0000000 --- a/Example-Carthage/Scripts/lib-update.sh +++ /dev/null @@ -1,33 +0,0 @@ -if ! gem spec xcodeproj > /dev/null 2>&1; then - sudo gem install xcodeproj -fi - -if ! brew ls --versions carthage > /dev/null 2>&1; then - brew install carthage -fi - -useclean=false - -for i in "$@" -do -case $i in - --use-clean) - useclean=true - ;; -esac -done - -cd .. - -if $useclean ; then - pod clean - rm -rf ./Carthage -fi - -pod install -# carthage update --no-use-binaries --platform iOS -carthage update --platform ios --no-use-binaries --use-ssh -# carthage update --no-checkout --no-build --no-use-binaries --platform iOS - -cd Scripts -ruby carthage_xconfig.rb From 69c2bab2cb6869d8726ae33ebd2db897716aeb5d Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 10:18:17 +0900 Subject: [PATCH 008/215] Update project settings. Add xcconfig file to build carthage. --- Carthage.xcconfig | 1 + DLGPlayer.xcodeproj/project.pbxproj | 6 ++++-- Example/DLGPlayer.xcodeproj/project.pbxproj | 2 +- .../Assets.xcassets/AppIcon.appiconset/Contents.json | 5 +++++ 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 Carthage.xcconfig diff --git a/Carthage.xcconfig b/Carthage.xcconfig new file mode 100644 index 0000000..812885a --- /dev/null +++ b/Carthage.xcconfig @@ -0,0 +1 @@ +ONLY_ACTIVE_ARCH = YES diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index 2c4727c..cf27cc6 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -238,7 +238,7 @@ isa = PBXNativeTarget; buildConfigurationList = 23DC26E221B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayer" */; buildPhases = ( - 236E380F21B8AA76009C6879 /* ShellScript */, + 236E380F21B8AA76009C6879 /* Run Script */, 23DC26C921B80F5A0012243A /* Headers */, 23DC26CA21B80F5A0012243A /* Sources */, 23DC26CB21B80F5A0012243A /* Frameworks */, @@ -332,7 +332,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 236E380F21B8AA76009C6879 /* ShellScript */ = { + 236E380F21B8AA76009C6879 /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 12; files = ( @@ -341,6 +341,7 @@ ); inputPaths = ( ); + name = "Run Script"; outputFileListPaths = ( ); outputPaths = ( @@ -512,6 +513,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; diff --git a/Example/DLGPlayer.xcodeproj/project.pbxproj b/Example/DLGPlayer.xcodeproj/project.pbxproj index 18be8a4..f7db0f5 100644 --- a/Example/DLGPlayer.xcodeproj/project.pbxproj +++ b/Example/DLGPlayer.xcodeproj/project.pbxproj @@ -1116,7 +1116,7 @@ "$(PROJECT_DIR)/DLGPlayer/Externals/ffmpeg/lib", "$(PROJECT_DIR)/DLGPlayer/Externals/openssl/lib", ); - ONLY_ACTIVE_ARCH = YES; + ONLY_ACTIVE_ARCH = NO; PRODUCT_BUNDLE_IDENTIFIER = cn.devileo.DLGPlayer; PRODUCT_NAME = "$(TARGET_NAME)"; VALID_ARCHS = "arm64 armv7 armv7s"; diff --git a/Example/DLGPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example/DLGPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json index 1d060ed..d8db8d6 100644 --- a/Example/DLGPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Example/DLGPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -84,6 +84,11 @@ "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { From fecb6471e9b2c77e3ff71bd1d49e765396e4f1e9 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 10:24:49 +0900 Subject: [PATCH 009/215] Update README --- README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4dce2f0..78e8959 100644 --- a/README.md +++ b/README.md @@ -144,5 +144,26 @@ See ***DLGPlayerViewController*** class for more usage details. Thank you all! -## 7. License +## 7. Installation + +### Carthage + +[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. + +You can install Carthage with [Homebrew](http://brew.sh/) using the following command: + +```bash +$ brew update +$ brew install carthage +``` + +To integrate DLGPlayer into your Xcode project using Carthage, specify it in your `Cartfile`: + +```ogdl +github "DeviLeo/DLGPlayer" "master" +``` + +Run `XCODE_XCCONFIG_FILE="Carthage.xcconfig" carthage update` to build the framework and drag the built `DLGPlayer.framework` into your Xcode project. + +## 8. License See [LICENSE](https://github.com/DeviLeo/DLGPlayer/blob/master/LICENSE "LGPL-3.0"). From 370b2b465465ce9e17d27fd875421cb9883ebec6 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 10:35:27 +0900 Subject: [PATCH 010/215] Update project setting. --- DLGPlayer.xcodeproj/project.pbxproj | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index cf27cc6..b4331d1 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -7,6 +7,16 @@ objects = { /* Begin PBXBuildFile section */ + 235409B421BA05A100533B9B /* DLGPlayerDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291821B810B40012243A /* DLGPlayerDecoder.h */; }; + 235409B521BA05A400533B9B /* DLGPlayerAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291921B810B40012243A /* DLGPlayerAudioManager.h */; }; + 235409B621BA05A900533B9B /* DLGPlayerDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293621B810B50012243A /* DLGPlayerDef.h */; }; + 235409B721BA05A900533B9B /* DLGPlayerUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293721B810B50012243A /* DLGPlayerUtils.h */; }; + 235409B821BA05B500533B9B /* DLGPlayerVideoYUVFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292821B810B50012243A /* DLGPlayerVideoYUVFrame.h */; }; + 235409B921BA05B500533B9B /* DLGPlayerVideoFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292921B810B50012243A /* DLGPlayerVideoFrame.h */; }; + 235409BA21BA05B500533B9B /* DLGPlayerFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292C21B810B50012243A /* DLGPlayerFrame.h */; }; + 235409BB21BA05B500533B9B /* DLGPlayerVideoRGBFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292D21B810B50012243A /* DLGPlayerVideoRGBFrame.h */; }; + 235409BC21BA05B500533B9B /* DLGPlayerAudioFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293021B810B50012243A /* DLGPlayerAudioFrame.h */; }; + 235409BD21BA05BC00533B9B /* DLGPlayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293421B810B50012243A /* DLGPlayerView.h */; }; 23DC26D821B80F5A0012243A /* DLGPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; }; 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291421B810B40012243A /* DLGPlayerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23DC293A21B810B50012243A /* DLGPlayerDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC291621B810B40012243A /* DLGPlayerDecoder.m */; }; @@ -226,8 +236,18 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 235409BA21BA05B500533B9B /* DLGPlayerFrame.h in Headers */, 23DC293E21B810B50012243A /* DLGPlayer.h in Headers */, + 235409BC21BA05B500533B9B /* DLGPlayerAudioFrame.h in Headers */, + 235409B921BA05B500533B9B /* DLGPlayerVideoFrame.h in Headers */, + 235409B821BA05B500533B9B /* DLGPlayerVideoYUVFrame.h in Headers */, 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */, + 235409B521BA05A400533B9B /* DLGPlayerAudioManager.h in Headers */, + 235409B421BA05A100533B9B /* DLGPlayerDecoder.h in Headers */, + 235409BD21BA05BC00533B9B /* DLGPlayerView.h in Headers */, + 235409B621BA05A900533B9B /* DLGPlayerDef.h in Headers */, + 235409B721BA05A900533B9B /* DLGPlayerUtils.h in Headers */, + 235409BB21BA05B500533B9B /* DLGPlayerVideoRGBFrame.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; From b13898bf67229afd9b9802f1ccb5aa90e23fabd3 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 10:37:45 +0900 Subject: [PATCH 011/215] Update project setting. --- DLGPlayer.xcodeproj/project.pbxproj | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index b4331d1..31ff481 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -7,16 +7,16 @@ objects = { /* Begin PBXBuildFile section */ - 235409B421BA05A100533B9B /* DLGPlayerDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291821B810B40012243A /* DLGPlayerDecoder.h */; }; - 235409B521BA05A400533B9B /* DLGPlayerAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291921B810B40012243A /* DLGPlayerAudioManager.h */; }; - 235409B621BA05A900533B9B /* DLGPlayerDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293621B810B50012243A /* DLGPlayerDef.h */; }; - 235409B721BA05A900533B9B /* DLGPlayerUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293721B810B50012243A /* DLGPlayerUtils.h */; }; - 235409B821BA05B500533B9B /* DLGPlayerVideoYUVFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292821B810B50012243A /* DLGPlayerVideoYUVFrame.h */; }; - 235409B921BA05B500533B9B /* DLGPlayerVideoFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292921B810B50012243A /* DLGPlayerVideoFrame.h */; }; - 235409BA21BA05B500533B9B /* DLGPlayerFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292C21B810B50012243A /* DLGPlayerFrame.h */; }; - 235409BB21BA05B500533B9B /* DLGPlayerVideoRGBFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292D21B810B50012243A /* DLGPlayerVideoRGBFrame.h */; }; - 235409BC21BA05B500533B9B /* DLGPlayerAudioFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293021B810B50012243A /* DLGPlayerAudioFrame.h */; }; - 235409BD21BA05BC00533B9B /* DLGPlayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293421B810B50012243A /* DLGPlayerView.h */; }; + 235409B421BA05A100533B9B /* DLGPlayerDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291821B810B40012243A /* DLGPlayerDecoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409B521BA05A400533B9B /* DLGPlayerAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291921B810B40012243A /* DLGPlayerAudioManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409B621BA05A900533B9B /* DLGPlayerDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293621B810B50012243A /* DLGPlayerDef.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409B721BA05A900533B9B /* DLGPlayerUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293721B810B50012243A /* DLGPlayerUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409B821BA05B500533B9B /* DLGPlayerVideoYUVFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292821B810B50012243A /* DLGPlayerVideoYUVFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409B921BA05B500533B9B /* DLGPlayerVideoFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292921B810B50012243A /* DLGPlayerVideoFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409BA21BA05B500533B9B /* DLGPlayerFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292C21B810B50012243A /* DLGPlayerFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409BB21BA05B500533B9B /* DLGPlayerVideoRGBFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292D21B810B50012243A /* DLGPlayerVideoRGBFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409BC21BA05B500533B9B /* DLGPlayerAudioFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293021B810B50012243A /* DLGPlayerAudioFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409BD21BA05BC00533B9B /* DLGPlayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293421B810B50012243A /* DLGPlayerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23DC26D821B80F5A0012243A /* DLGPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; }; 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291421B810B40012243A /* DLGPlayerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23DC293A21B810B50012243A /* DLGPlayerDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC291621B810B40012243A /* DLGPlayerDecoder.m */; }; @@ -236,18 +236,18 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 235409BA21BA05B500533B9B /* DLGPlayerFrame.h in Headers */, 23DC293E21B810B50012243A /* DLGPlayer.h in Headers */, + 235409BA21BA05B500533B9B /* DLGPlayerFrame.h in Headers */, 235409BC21BA05B500533B9B /* DLGPlayerAudioFrame.h in Headers */, 235409B921BA05B500533B9B /* DLGPlayerVideoFrame.h in Headers */, 235409B821BA05B500533B9B /* DLGPlayerVideoYUVFrame.h in Headers */, - 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */, 235409B521BA05A400533B9B /* DLGPlayerAudioManager.h in Headers */, 235409B421BA05A100533B9B /* DLGPlayerDecoder.h in Headers */, 235409BD21BA05BC00533B9B /* DLGPlayerView.h in Headers */, 235409B621BA05A900533B9B /* DLGPlayerDef.h in Headers */, 235409B721BA05A900533B9B /* DLGPlayerUtils.h in Headers */, 235409BB21BA05B500533B9B /* DLGPlayerVideoRGBFrame.h in Headers */, + 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; From f21cfdf7a9ac16c6fed73c20fc1333ca1681afb5 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 10:46:18 +0900 Subject: [PATCH 012/215] Update import to build carthage. --- DLGPlayer/DLGPlayer.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index d89d502..0521276 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -8,6 +8,15 @@ #import #import "DLGPlayerDef.h" +#import "DLGPlayerDecoder.h" +#import "DLGPlayerFrame.h" +#import "DLGPlayerAudioFrame.h" +#import "DLGPlayerVideoFrame.h" +#import "DLGPlayerVideoRGBFrame.h" +#import "DLGPlayerVideoYUVFrame.h" +#import "DLGPlayerView.h" +#import "DLGPlayerViewController.h" +#import "DLGPlayerUtils.h" typedef void (^onPauseComplete)(void); From 009ff059e0779c31ecf925e2aaaf22707c482c02 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 11:34:22 +0900 Subject: [PATCH 013/215] Change resource bundle for framework. --- DLGPlayer/common/DLGPlayerUtils.m | 2 +- DLGPlayer/view/DLGPlayerView.m | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/common/DLGPlayerUtils.m b/DLGPlayer/common/DLGPlayerUtils.m index eba9925..0f98822 100644 --- a/DLGPlayer/common/DLGPlayerUtils.m +++ b/DLGPlayer/common/DLGPlayerUtils.m @@ -33,7 +33,7 @@ + (BOOL)createError:(NSError **)error withDomain:(NSString *)domain andCode:(NSI } + (NSString *)localizedString:(NSString *)name { - return NSLocalizedStringFromTable(name, DLGPlayerLocalizedStringTable, nil); + return [[NSBundle bundleForClass:[self class]] localizedStringForKey:name value:nil table:DLGPlayerLocalizedStringTable]; } + (NSString *)durationStringFromSeconds:(int)seconds { diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index 558a108..2136eaf 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -173,7 +173,7 @@ - (void)createGLProgram { } // Load shaders - NSBundle *bundle = [NSBundle mainBundle]; + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; NSString *vertexShaderFilename = @"DLGPlayerVertexShader"; if (_shouldScale) vertexShaderFilename = @"DLGPlayerRotationScaleVertexShader"; else if (_shouldRotate) vertexShaderFilename = @"DLGPlayerRotationVertexShader"; From a858730678293caef8933e683ba8ba829fa39719 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 12:24:27 +0900 Subject: [PATCH 014/215] [Refactoring] Extract DLGPlayerStatus of enum to DLGPlayerDef.h [Added new class] DLGSimplePlayerViewController to exclude control UI. --- DLGPlayer.xcodeproj/project.pbxproj | 8 + DLGPlayer/DLGPlayerViewController.h | 12 -- DLGPlayer/DLGSimplePlayerViewController.h | 36 ++++ DLGPlayer/DLGSimplePlayerViewController.m | 252 ++++++++++++++++++++++ DLGPlayer/common/DLGPlayerDef.h | 12 ++ 5 files changed, 308 insertions(+), 12 deletions(-) create mode 100644 DLGPlayer/DLGSimplePlayerViewController.h create mode 100644 DLGPlayer/DLGSimplePlayerViewController.m diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index 31ff481..1e55000 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -17,6 +17,8 @@ 235409BB21BA05B500533B9B /* DLGPlayerVideoRGBFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292D21B810B50012243A /* DLGPlayerVideoRGBFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; 235409BC21BA05B500533B9B /* DLGPlayerAudioFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293021B810B50012243A /* DLGPlayerAudioFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; 235409BD21BA05BC00533B9B /* DLGPlayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293421B810B50012243A /* DLGPlayerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 235409C621BA177A00533B9B /* DLGSimplePlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */; }; + 235409C721BA177A00533B9B /* DLGSimplePlayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */; }; 23DC26D821B80F5A0012243A /* DLGPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; }; 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291421B810B40012243A /* DLGPlayerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23DC293A21B810B50012243A /* DLGPlayerDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC291621B810B40012243A /* DLGPlayerDecoder.m */; }; @@ -50,6 +52,8 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DLGSimplePlayerViewController.h; sourceTree = ""; }; + 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DLGSimplePlayerViewController.m; sourceTree = ""; }; 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DLGPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 23DC26D221B80F5A0012243A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 23DC26D721B80F5A0012243A /* DLGPlayerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DLGPlayerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -140,6 +144,8 @@ 23DC291521B810B40012243A /* codec */, 23DC293521B810B50012243A /* common */, 23DC291A21B810B50012243A /* DLGPlayer.h */, + 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */, + 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */, 23DC291C21B810B50012243A /* DLGPlayer.m */, 23DC291421B810B40012243A /* DLGPlayerViewController.h */, 23DC291B21B810B50012243A /* DLGPlayerViewController.m */, @@ -237,6 +243,7 @@ buildActionMask = 2147483647; files = ( 23DC293E21B810B50012243A /* DLGPlayer.h in Headers */, + 235409C621BA177A00533B9B /* DLGSimplePlayerViewController.h in Headers */, 235409BA21BA05B500533B9B /* DLGPlayerFrame.h in Headers */, 235409BC21BA05B500533B9B /* DLGPlayerAudioFrame.h in Headers */, 235409B921BA05B500533B9B /* DLGPlayerVideoFrame.h in Headers */, @@ -380,6 +387,7 @@ 23DC293A21B810B50012243A /* DLGPlayerDecoder.m in Sources */, 23DC293B21B810B50012243A /* DLGPlayerAudioManager.m in Sources */, 23DC294021B810B50012243A /* DLGPlayer.m in Sources */, + 235409C721BA177A00533B9B /* DLGSimplePlayerViewController.m in Sources */, 23DC294D21B810B50012243A /* DLGPlayerVideoFrame.m in Sources */, 23DC295521B810B50012243A /* DLGPlayerUtils.m in Sources */, 23DC295021B810B50012243A /* DLGPlayerFrame.m in Sources */, diff --git a/DLGPlayer/DLGPlayerViewController.h b/DLGPlayer/DLGPlayerViewController.h index a553c13..4d20576 100644 --- a/DLGPlayer/DLGPlayerViewController.h +++ b/DLGPlayer/DLGPlayerViewController.h @@ -9,18 +9,6 @@ #import #import "DLGPlayer.h" -typedef enum : NSUInteger { - DLGPlayerStatusNone, - DLGPlayerStatusOpening, - DLGPlayerStatusOpened, - DLGPlayerStatusPlaying, - DLGPlayerStatusBuffering, - DLGPlayerStatusPaused, - DLGPlayerStatusEOF, - DLGPlayerStatusClosing, - DLGPlayerStatusClosed, -} DLGPlayerStatus; - @interface DLGPlayerViewController : UIViewController @property (nonatomic, copy) NSString *url; diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h new file mode 100644 index 0000000..7eacf45 --- /dev/null +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -0,0 +1,36 @@ +// +// DLGSimplePlayerViewController.h +// DLGPlayer +// +// Created by KWANG HYOUN KIM on 07/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +#import +#import "DLGPlayer.h" + +NS_ASSUME_NONNULL_BEGIN + +@class DLGSimplePlayerViewController; + +@protocol DLGSimplePlayerViewControllerDelegate +- (void)viewController:(DLGSimplePlayerViewController *)viewController didChangeStatus:(DLGPlayerStatus)status; +- (void)viewController:(DLGSimplePlayerViewController *)viewController didReceiveError:(NSError *)error; +@end + +@interface DLGSimplePlayerViewController : UIViewController +@property (nonatomic, copy) NSString *url; +@property (nonatomic) BOOL autoplay; +@property (nonatomic) BOOL repeat; +@property (nonatomic) BOOL preventFromScreenLock; +@property (nonatomic) BOOL restorePlayAfterAppEnterForeground; +@property (nonatomic, readonly) DLGPlayerStatus status; +@property (nonatomic, readonly) DLGPlayer *player; +@property (nonatomic, weak) id delegate; +- (void)open; +- (void)close; +- (void)play; +- (void)pause; +@end + +NS_ASSUME_NONNULL_END diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m new file mode 100644 index 0000000..8320e09 --- /dev/null +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -0,0 +1,252 @@ +// +// DLGSimplePlayerViewController.m +// DLGPlayer +// +// Created by KWANG HYOUN KIM on 07/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +#import "DLGSimplePlayerViewController.h" +#import "DLGPlayerUtils.h" + +typedef enum : NSUInteger { + DLGPlayerOperationNone, + DLGPlayerOperationOpen, + DLGPlayerOperationPlay, + DLGPlayerOperationPause, + DLGPlayerOperationClose, +} DLGPlayerOperation; + +@interface DLGSimplePlayerViewController () { + BOOL restorePlay; +} + +@property (nonatomic, strong) DLGPlayer *player; +@property (nonatomic, readwrite) DLGPlayerStatus status; +@property (nonatomic) DLGPlayerOperation nextOperation; +@end + +@implementation DLGSimplePlayerViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self initAll]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + [self registerNotification]; +} + +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + [self unregisterNotification]; +} + +- (void)registerNotification { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self selector:@selector(notifyAppDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification object:nil]; + [nc addObserver:self selector:@selector(notifyAppWillEnterForeground:) + name:UIApplicationWillEnterForegroundNotification object:nil]; + [nc addObserver:self selector:@selector(notifyPlayerOpened:) name:DLGPlayerNotificationOpened object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerClosed:) name:DLGPlayerNotificationClosed object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerEOF:) name:DLGPlayerNotificationEOF object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerBufferStateChanged:) name:DLGPlayerNotificationBufferStateChanged object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerError:) name:DLGPlayerNotificationError object:_player]; +} + +- (void)unregisterNotification { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)setStatus:(DLGPlayerStatus)status { + if ([_delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { + [_delegate viewController:self didChangeStatus:status]; + } +} + +#pragma mark - Init +- (void)initAll { + [self initPlayer]; + + _status = DLGPlayerStatusNone; + self.nextOperation = DLGPlayerOperationNone; +} + +- (void)open { + if (_status == DLGPlayerStatusClosing) { + self.nextOperation = DLGPlayerOperationOpen; + return; + } + if (_status != DLGPlayerStatusNone && + _status != DLGPlayerStatusClosed) { + return; + } + self.status = DLGPlayerStatusOpening; + [_player open:self.url]; +} + +- (void)close { + if (_status == DLGPlayerStatusOpening) { + self.nextOperation = DLGPlayerOperationClose; + return; + } + self.status = DLGPlayerStatusClosing; + [UIApplication sharedApplication].idleTimerDisabled = NO; + [_player close]; +} + +- (void)play { + if (_status == DLGPlayerStatusNone || + _status == DLGPlayerStatusClosed) { + [self open]; + self.nextOperation = DLGPlayerOperationPlay; + } + if (_status != DLGPlayerStatusOpened && + _status != DLGPlayerStatusPaused && + _status != DLGPlayerStatusEOF) { + return; + } + self.status = DLGPlayerStatusPlaying; + [UIApplication sharedApplication].idleTimerDisabled = self.preventFromScreenLock; + [_player play]; +} + +- (void)replay { + _player.position = 0; + [self play]; +} + +- (void)pause { + if (_status != DLGPlayerStatusOpened && + _status != DLGPlayerStatusPlaying && + _status != DLGPlayerStatusEOF) { + return; + } + self.status = DLGPlayerStatusPaused; + [UIApplication sharedApplication].idleTimerDisabled = NO; + [_player pause]; +} + +- (BOOL)doNextOperation { + if (self.nextOperation == DLGPlayerOperationNone) return NO; + switch (self.nextOperation) { + case DLGPlayerOperationOpen: + [self open]; + break; + case DLGPlayerOperationPlay: + [self play]; + break; + case DLGPlayerOperationPause: + [self pause]; + break; + case DLGPlayerOperationClose: + [self close]; + break; + default: + break; + } + self.nextOperation = DLGPlayerOperationNone; + return YES; +} + + +#pragma mark - UI +- (void)initPlayer { + _player = [[DLGPlayer alloc] init]; + UIView *v = _player.playerView; + v.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:v]; + + // Add constraints + NSDictionary *views = NSDictionaryOfVariableBindings(v); + NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:ch]; + NSArray *cv = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:cv]; +} + +#pragma mark - Notifications +- (void)notifyAppDidEnterBackground:(NSNotification *)notif { + if (_player.playing) { + [self pause]; + if (self.restorePlayAfterAppEnterForeground) restorePlay = YES; + } +} + +- (void)notifyAppWillEnterForeground:(NSNotification *)notif { + if (restorePlay) { + restorePlay = NO; + [self play]; + } +} + +- (void)notifyPlayerEOF:(NSNotification *)notif { + self.status = DLGPlayerStatusEOF; + if (self.repeat) [self replay]; + else [self close]; +} + +- (void)notifyPlayerClosed:(NSNotification *)notif { + self.status = DLGPlayerStatusClosed; + + [self doNextOperation]; +} + +- (void)notifyPlayerOpened:(NSNotification *)notif { + self.status = DLGPlayerStatusOpened; + + if (![self doNextOperation]) { + if (self.autoplay) [self play]; + } +} + +- (void)notifyPlayerBufferStateChanged:(NSNotification *)notif { + NSDictionary *userInfo = notif.userInfo; + BOOL state = [userInfo[DLGPlayerNotificationBufferStateKey] boolValue]; + if (state) { + self.status = DLGPlayerStatusBuffering; + } else { + self.status = DLGPlayerStatusPlaying; + } +} + +- (void)notifyPlayerError:(NSNotification *)notif { + NSDictionary *userInfo = notif.userInfo; + NSError *error = userInfo[DLGPlayerNotificationErrorKey]; + + if ([error.domain isEqualToString:DLGPlayerErrorDomainDecoder]) { + __weak typeof(self)weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + if (!strongSelf) { + return; + } + + strongSelf.status = DLGPlayerStatusNone; + strongSelf.nextOperation = DLGPlayerOperationNone; + }); + + NSLog(@"Player decoder error: %@", error); + } else if ([error.domain isEqualToString:DLGPlayerErrorDomainAudioManager]) { + NSLog(@"Player audio error: %@", error); + } + + if ([_delegate respondsToSelector:@selector(viewController:didReceiveError:)]) { + [_delegate viewController:self didReceiveError:error]; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:self userInfo:notif.userInfo]; +} + +@end diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index d67ed97..e727621 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -51,4 +51,16 @@ #define DLGPlayerNotificationErrorKey @"DLGPlayerNotificationErrorKey" #define DLGPlayerNotificationRawErrorKey @"DLGPlayerNotificationRawErrorKey" +typedef enum : NSUInteger { + DLGPlayerStatusNone, + DLGPlayerStatusOpening, + DLGPlayerStatusOpened, + DLGPlayerStatusPlaying, + DLGPlayerStatusBuffering, + DLGPlayerStatusPaused, + DLGPlayerStatusEOF, + DLGPlayerStatusClosing, + DLGPlayerStatusClosed, +} DLGPlayerStatus; + #endif /* DLGPlayerDef_h */ From 36cc87377efc298bf574c0a7161edec0c2b3ae59 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 12:26:06 +0900 Subject: [PATCH 015/215] Update import to use as framework. --- DLGPlayer.xcodeproj/project.pbxproj | 4 ++-- DLGPlayer/DLGPlayer.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index 1e55000..7eee518 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -17,7 +17,7 @@ 235409BB21BA05B500533B9B /* DLGPlayerVideoRGBFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC292D21B810B50012243A /* DLGPlayerVideoRGBFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; 235409BC21BA05B500533B9B /* DLGPlayerAudioFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293021B810B50012243A /* DLGPlayerAudioFrame.h */; settings = {ATTRIBUTES = (Public, ); }; }; 235409BD21BA05BC00533B9B /* DLGPlayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293421B810B50012243A /* DLGPlayerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 235409C621BA177A00533B9B /* DLGSimplePlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */; }; + 235409C621BA177A00533B9B /* DLGSimplePlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 235409C721BA177A00533B9B /* DLGSimplePlayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */; }; 23DC26D821B80F5A0012243A /* DLGPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; }; 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291421B810B40012243A /* DLGPlayerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -243,7 +243,6 @@ buildActionMask = 2147483647; files = ( 23DC293E21B810B50012243A /* DLGPlayer.h in Headers */, - 235409C621BA177A00533B9B /* DLGSimplePlayerViewController.h in Headers */, 235409BA21BA05B500533B9B /* DLGPlayerFrame.h in Headers */, 235409BC21BA05B500533B9B /* DLGPlayerAudioFrame.h in Headers */, 235409B921BA05B500533B9B /* DLGPlayerVideoFrame.h in Headers */, @@ -253,6 +252,7 @@ 235409BD21BA05BC00533B9B /* DLGPlayerView.h in Headers */, 235409B621BA05A900533B9B /* DLGPlayerDef.h in Headers */, 235409B721BA05A900533B9B /* DLGPlayerUtils.h in Headers */, + 235409C621BA177A00533B9B /* DLGSimplePlayerViewController.h in Headers */, 235409BB21BA05B500533B9B /* DLGPlayerVideoRGBFrame.h in Headers */, 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */, ); diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 0521276..1695dcc 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -17,6 +17,7 @@ #import "DLGPlayerView.h" #import "DLGPlayerViewController.h" #import "DLGPlayerUtils.h" +#import "DLGSimplePlayerViewController.h" typedef void (^onPauseComplete)(void); From d99c760c8eca14bb212323f53acd0c9c9c44a797 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 13:33:36 +0900 Subject: [PATCH 016/215] Bug fix: Change import to @class --- DLGPlayer/DLGPlayer.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 1695dcc..1a28c7b 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -17,7 +17,8 @@ #import "DLGPlayerView.h" #import "DLGPlayerViewController.h" #import "DLGPlayerUtils.h" -#import "DLGSimplePlayerViewController.h" + +@class DLGSimplePlayerViewController; typedef void (^onPauseComplete)(void); From 76f22743c432e172652f1fd0b279f46ef1b62d20 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 13:35:50 +0900 Subject: [PATCH 017/215] Revert "Bug fix: Change import to @class" This reverts commit d99c760c8eca14bb212323f53acd0c9c9c44a797. --- DLGPlayer/DLGPlayer.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 1a28c7b..1695dcc 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -17,8 +17,7 @@ #import "DLGPlayerView.h" #import "DLGPlayerViewController.h" #import "DLGPlayerUtils.h" - -@class DLGSimplePlayerViewController; +#import "DLGSimplePlayerViewController.h" typedef void (^onPauseComplete)(void); From b116fd446c596c67225ddd7d8e5fdb2f351b364b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 13:42:28 +0900 Subject: [PATCH 018/215] Bug fix: avoid compile error. --- DLGPlayer/DLGSimplePlayerViewController.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index 7eacf45..16ffc05 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -9,6 +9,8 @@ #import #import "DLGPlayer.h" +@class DLGPlayer; + NS_ASSUME_NONNULL_BEGIN @class DLGSimplePlayerViewController; From a614e22f104c64adcd433b1c13510e3d0987e43b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 14:08:07 +0900 Subject: [PATCH 019/215] Bug fix --- DLGPlayer/DLGSimplePlayerViewController.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 8320e09..1b8194b 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -21,7 +21,7 @@ @interface DLGSimplePlayerViewController () { BOOL restorePlay; } -@property (nonatomic, strong) DLGPlayer *player; +@property (nonatomic, readwrite) DLGPlayer *player; @property (nonatomic, readwrite) DLGPlayerStatus status; @property (nonatomic) DLGPlayerOperation nextOperation; @end @@ -64,6 +64,8 @@ - (void)unregisterNotification { } - (void)setStatus:(DLGPlayerStatus)status { + _status = status; + if ([_delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { [_delegate viewController:self didChangeStatus:status]; } @@ -87,7 +89,7 @@ - (void)open { return; } self.status = DLGPlayerStatusOpening; - [_player open:self.url]; + [_player open:_url]; } - (void)close { @@ -112,7 +114,7 @@ - (void)play { return; } self.status = DLGPlayerStatusPlaying; - [UIApplication sharedApplication].idleTimerDisabled = self.preventFromScreenLock; + [UIApplication sharedApplication].idleTimerDisabled = _preventFromScreenLock; [_player play]; } @@ -180,7 +182,7 @@ - (void)initPlayer { - (void)notifyAppDidEnterBackground:(NSNotification *)notif { if (_player.playing) { [self pause]; - if (self.restorePlayAfterAppEnterForeground) restorePlay = YES; + if (_restorePlayAfterAppEnterForeground) restorePlay = YES; } } @@ -193,7 +195,7 @@ - (void)notifyAppWillEnterForeground:(NSNotification *)notif { - (void)notifyPlayerEOF:(NSNotification *)notif { self.status = DLGPlayerStatusEOF; - if (self.repeat) [self replay]; + if (_repeat) [self replay]; else [self close]; } @@ -207,7 +209,7 @@ - (void)notifyPlayerOpened:(NSNotification *)notif { self.status = DLGPlayerStatusOpened; if (![self doNextOperation]) { - if (self.autoplay) [self play]; + if (_autoplay) [self play]; } } From ab2d0d6c999d85791706c282f35a43e38aa6bdd7 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 14:27:17 +0900 Subject: [PATCH 020/215] Change definition enum to NS_ENUM for using on swift. --- DLGPlayer/common/DLGPlayerDef.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index e727621..74e9626 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -51,7 +51,7 @@ #define DLGPlayerNotificationErrorKey @"DLGPlayerNotificationErrorKey" #define DLGPlayerNotificationRawErrorKey @"DLGPlayerNotificationRawErrorKey" -typedef enum : NSUInteger { +typedef NS_ENUM(NSUInteger, DLGPlayerStatus) { DLGPlayerStatusNone, DLGPlayerStatusOpening, DLGPlayerStatusOpened, @@ -60,7 +60,7 @@ typedef enum : NSUInteger { DLGPlayerStatusPaused, DLGPlayerStatusEOF, DLGPlayerStatusClosing, - DLGPlayerStatusClosed, -} DLGPlayerStatus; + DLGPlayerStatusClosed +}; #endif /* DLGPlayerDef_h */ From 57c78ce32ea1b4e434479265f32c069984c04926 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 14:36:24 +0900 Subject: [PATCH 021/215] Add demo project with carthage. --- .gitignore | 2 +- Example-Carthage/Cartfile | 2 + Example-Carthage/Cartfile.resolved | 1 + .../DLGPlayerDemo.xcodeproj/project.pbxproj | 505 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../DLGPlayerDemo/AppDelegate.swift | 46 ++ .../AppIcon.appiconset/Contents.json | 98 ++++ .../Assets.xcassets/Contents.json | 6 + .../Base.lproj/LaunchScreen.storyboard | 25 + .../DLGPlayerDemo/Base.lproj/Main.storyboard | 58 ++ .../DLGPlayerDemo-Bridging-Header.h | 14 + Example-Carthage/DLGPlayerDemo/Info.plist | 45 ++ .../DLGPlayerDemo/ViewController.swift | 66 +++ .../DLGPlayerDemoTests.swift | 34 ++ .../DLGPlayerDemoTests/Info.plist | 22 + 16 files changed, 938 insertions(+), 1 deletion(-) create mode 100755 Example-Carthage/Cartfile create mode 100644 Example-Carthage/Cartfile.resolved create mode 100644 Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj create mode 100644 Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Example-Carthage/DLGPlayerDemo/AppDelegate.swift create mode 100644 Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json create mode 100644 Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard create mode 100644 Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard create mode 100644 Example-Carthage/DLGPlayerDemo/DLGPlayerDemo-Bridging-Header.h create mode 100644 Example-Carthage/DLGPlayerDemo/Info.plist create mode 100644 Example-Carthage/DLGPlayerDemo/ViewController.swift create mode 100644 Example-Carthage/DLGPlayerDemoTests/DLGPlayerDemoTests.swift create mode 100644 Example-Carthage/DLGPlayerDemoTests/Info.plist diff --git a/.gitignore b/.gitignore index 6295fb5..7c3b1c8 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,4 @@ iOSInjectionProject/ ffmpeg/ -Example-Carthage/DLGPlayerDemo/Carthage/Build +Example-Carthage/Carthage/ diff --git a/Example-Carthage/Cartfile b/Example-Carthage/Cartfile new file mode 100755 index 0000000..f029f25 --- /dev/null +++ b/Example-Carthage/Cartfile @@ -0,0 +1,2 @@ + +github "pisces/DLGPlayer" "master" diff --git a/Example-Carthage/Cartfile.resolved b/Example-Carthage/Cartfile.resolved new file mode 100644 index 0000000..4e0d208 --- /dev/null +++ b/Example-Carthage/Cartfile.resolved @@ -0,0 +1 @@ +github "pisces/DLGPlayer" "ab2d0d6c999d85791706c282f35a43e38aa6bdd7" diff --git a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e76680b --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj @@ -0,0 +1,505 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 2354099121BA044100533B9B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2354099021BA044100533B9B /* AppDelegate.swift */; }; + 2354099321BA044100533B9B /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2354099221BA044100533B9B /* ViewController.swift */; }; + 2354099621BA044100533B9B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2354099421BA044100533B9B /* Main.storyboard */; }; + 2354099821BA044200533B9B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2354099721BA044200533B9B /* Assets.xcassets */; }; + 2354099B21BA044200533B9B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2354099921BA044200533B9B /* LaunchScreen.storyboard */; }; + 235409A621BA044300533B9B /* DLGPlayerDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 235409A521BA044300533B9B /* DLGPlayerDemoTests.swift */; }; + 235409B221BA04B800533B9B /* DLGPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 235409B121BA04B800533B9B /* DLGPlayer.framework */; }; + 235409BF21BA0A2D00533B9B /* DLGPlayer.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 235409B121BA04B800533B9B /* DLGPlayer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 235409A221BA044300533B9B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2354098521BA044100533B9B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2354098C21BA044100533B9B; + remoteInfo = DLGPlayerDemo; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 235409BE21BA0A2100533B9B /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 235409BF21BA0A2D00533B9B /* DLGPlayer.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2354098D21BA044100533B9B /* DLGPlayerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DLGPlayerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2354099021BA044100533B9B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 2354099221BA044100533B9B /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 2354099521BA044100533B9B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 2354099721BA044200533B9B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 2354099A21BA044200533B9B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 2354099C21BA044200533B9B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 235409A121BA044200533B9B /* DLGPlayerDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DLGPlayerDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 235409A521BA044300533B9B /* DLGPlayerDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DLGPlayerDemoTests.swift; sourceTree = ""; }; + 235409A721BA044300533B9B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 235409B121BA04B800533B9B /* DLGPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DLGPlayer.framework; path = Carthage/Build/iOS/DLGPlayer.framework; sourceTree = ""; }; + 235409B321BA04FA00533B9B /* DLGPlayerDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DLGPlayerDemo-Bridging-Header.h"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2354098A21BA044100533B9B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 235409B221BA04B800533B9B /* DLGPlayer.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2354099E21BA044200533B9B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2354098421BA044100533B9B = { + isa = PBXGroup; + children = ( + 2354098F21BA044100533B9B /* DLGPlayerDemo */, + 235409A421BA044300533B9B /* DLGPlayerDemoTests */, + 2354098E21BA044100533B9B /* Products */, + 235409B021BA04B700533B9B /* Frameworks */, + ); + sourceTree = ""; + }; + 2354098E21BA044100533B9B /* Products */ = { + isa = PBXGroup; + children = ( + 2354098D21BA044100533B9B /* DLGPlayerDemo.app */, + 235409A121BA044200533B9B /* DLGPlayerDemoTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 2354098F21BA044100533B9B /* DLGPlayerDemo */ = { + isa = PBXGroup; + children = ( + 2354099021BA044100533B9B /* AppDelegate.swift */, + 2354099221BA044100533B9B /* ViewController.swift */, + 2354099421BA044100533B9B /* Main.storyboard */, + 2354099721BA044200533B9B /* Assets.xcassets */, + 2354099921BA044200533B9B /* LaunchScreen.storyboard */, + 2354099C21BA044200533B9B /* Info.plist */, + 235409B321BA04FA00533B9B /* DLGPlayerDemo-Bridging-Header.h */, + ); + path = DLGPlayerDemo; + sourceTree = ""; + }; + 235409A421BA044300533B9B /* DLGPlayerDemoTests */ = { + isa = PBXGroup; + children = ( + 235409A521BA044300533B9B /* DLGPlayerDemoTests.swift */, + 235409A721BA044300533B9B /* Info.plist */, + ); + path = DLGPlayerDemoTests; + sourceTree = ""; + }; + 235409B021BA04B700533B9B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 235409B121BA04B800533B9B /* DLGPlayer.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2354098C21BA044100533B9B /* DLGPlayerDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 235409AA21BA044300533B9B /* Build configuration list for PBXNativeTarget "DLGPlayerDemo" */; + buildPhases = ( + 2354098921BA044100533B9B /* Sources */, + 2354098A21BA044100533B9B /* Frameworks */, + 2354098B21BA044100533B9B /* Resources */, + 235409BE21BA0A2100533B9B /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DLGPlayerDemo; + productName = DLGPlayerDemo; + productReference = 2354098D21BA044100533B9B /* DLGPlayerDemo.app */; + productType = "com.apple.product-type.application"; + }; + 235409A021BA044200533B9B /* DLGPlayerDemoTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 235409AD21BA044300533B9B /* Build configuration list for PBXNativeTarget "DLGPlayerDemoTests" */; + buildPhases = ( + 2354099D21BA044200533B9B /* Sources */, + 2354099E21BA044200533B9B /* Frameworks */, + 2354099F21BA044200533B9B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 235409A321BA044300533B9B /* PBXTargetDependency */, + ); + name = DLGPlayerDemoTests; + productName = DLGPlayerDemoTests; + productReference = 235409A121BA044200533B9B /* DLGPlayerDemoTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2354098521BA044100533B9B /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1010; + LastUpgradeCheck = 1010; + ORGANIZATIONNAME = "KWANG HYOUN KIM"; + TargetAttributes = { + 2354098C21BA044100533B9B = { + CreatedOnToolsVersion = 10.1; + }; + 235409A021BA044200533B9B = { + CreatedOnToolsVersion = 10.1; + TestTargetID = 2354098C21BA044100533B9B; + }; + }; + }; + buildConfigurationList = 2354098821BA044100533B9B /* Build configuration list for PBXProject "DLGPlayerDemo" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 2354098421BA044100533B9B; + productRefGroup = 2354098E21BA044100533B9B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2354098C21BA044100533B9B /* DLGPlayerDemo */, + 235409A021BA044200533B9B /* DLGPlayerDemoTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 2354098B21BA044100533B9B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2354099B21BA044200533B9B /* LaunchScreen.storyboard in Resources */, + 2354099821BA044200533B9B /* Assets.xcassets in Resources */, + 2354099621BA044100533B9B /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2354099F21BA044200533B9B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2354098921BA044100533B9B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2354099321BA044100533B9B /* ViewController.swift in Sources */, + 2354099121BA044100533B9B /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 2354099D21BA044200533B9B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 235409A621BA044300533B9B /* DLGPlayerDemoTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 235409A321BA044300533B9B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2354098C21BA044100533B9B /* DLGPlayerDemo */; + targetProxy = 235409A221BA044300533B9B /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 2354099421BA044100533B9B /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2354099521BA044100533B9B /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 2354099921BA044200533B9B /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 2354099A21BA044200533B9B /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 235409A821BA044300533B9B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 235409A921BA044300533B9B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 235409AB21BA044300533B9B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = DLGPlayerDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "${PROJECT_NAME}/DLGPlayerDemo-Bridging-Header.h"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 235409AC21BA044300533B9B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = DLGPlayerDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "${PROJECT_NAME}/DLGPlayerDemo-Bridging-Header.h"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 235409AE21BA044300533B9B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = DLGPlayerDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DLGPlayerDemo.app/DLGPlayerDemo"; + }; + name = Debug; + }; + 235409AF21BA044300533B9B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = DLGPlayerDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DLGPlayerDemo.app/DLGPlayerDemo"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2354098821BA044100533B9B /* Build configuration list for PBXProject "DLGPlayerDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 235409A821BA044300533B9B /* Debug */, + 235409A921BA044300533B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 235409AA21BA044300533B9B /* Build configuration list for PBXNativeTarget "DLGPlayerDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 235409AB21BA044300533B9B /* Debug */, + 235409AC21BA044300533B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 235409AD21BA044300533B9B /* Build configuration list for PBXNativeTarget "DLGPlayerDemoTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 235409AE21BA044300533B9B /* Debug */, + 235409AF21BA044300533B9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2354098521BA044100533B9B /* Project object */; +} diff --git a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..d849187 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example-Carthage/DLGPlayerDemo/AppDelegate.swift b/Example-Carthage/DLGPlayerDemo/AppDelegate.swift new file mode 100644 index 0000000..449ec9b --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 07/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d8db8d6 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json b/Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard b/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..bfa3612 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard b/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard new file mode 100644 index 0000000..b3ce660 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo-Bridging-Header.h b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo-Bridging-Header.h new file mode 100644 index 0000000..34781b4 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/DLGPlayerDemo-Bridging-Header.h @@ -0,0 +1,14 @@ +// +// DLGPlayerDemo-Bridging-Header.h +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 07/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +#ifndef DLGPlayerDemo_Bridging_Header_h +#define DLGPlayerDemo_Bridging_Header_h + +@import DLGPlayer; + +#endif /* DLGPlayerDemo_Bridging_Header_h */ diff --git a/Example-Carthage/DLGPlayerDemo/Info.plist b/Example-Carthage/DLGPlayerDemo/Info.plist new file mode 100644 index 0000000..16be3b6 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Example-Carthage/DLGPlayerDemo/ViewController.swift b/Example-Carthage/DLGPlayerDemo/ViewController.swift new file mode 100644 index 0000000..a5a5472 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemo/ViewController.swift @@ -0,0 +1,66 @@ +// +// ViewController.swift +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 07/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController { + private var timer: Timer? + private var playerViewController: DLGSimplePlayerViewController! { + didSet { + playerViewController.delegate = self + playerViewController.autoplay = true + playerViewController.repeat = true + playerViewController.preventFromScreenLock = true + playerViewController.restorePlayAfterAppEnterForeground = true + } + } + + override func viewDidLoad() { + super.viewDidLoad() + + playerViewController.url = "/path/to/video" + playerViewController.open() + } + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + switch segue.destination { + case let vc as DLGSimplePlayerViewController: + playerViewController = vc + default: () + } + } + + private func startTimer() { + stopTimer() + timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerCompletion), userInfo: nil, repeats: true) + } + private func stopTimer() { + timer?.invalidate() + timer = nil + } + + @objc private func timerCompletion() { + print("player.position", playerViewController.player.position) + } +} + +extension ViewController: DLGSimplePlayerViewControllerDelegate { + func viewController(_ viewController: DLGSimplePlayerViewController, didReceiveError error: Error) { + print("didReceiveError", error) + } + func viewController(_ viewController: DLGSimplePlayerViewController, didChange status: DLGPlayerStatus) { + print("didChange", status) + + switch status { + case .opened: + startTimer() + case .closed: + stopTimer() + default: () + } + } +} diff --git a/Example-Carthage/DLGPlayerDemoTests/DLGPlayerDemoTests.swift b/Example-Carthage/DLGPlayerDemoTests/DLGPlayerDemoTests.swift new file mode 100644 index 0000000..db500b1 --- /dev/null +++ b/Example-Carthage/DLGPlayerDemoTests/DLGPlayerDemoTests.swift @@ -0,0 +1,34 @@ +// +// DLGPlayerDemoTests.swift +// DLGPlayerDemoTests +// +// Created by KWANG HYOUN KIM on 07/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +import XCTest +@testable import DLGPlayerDemo + +class DLGPlayerDemoTests: XCTestCase { + + override func setUp() { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/Example-Carthage/DLGPlayerDemoTests/Info.plist b/Example-Carthage/DLGPlayerDemoTests/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/Example-Carthage/DLGPlayerDemoTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + From d27b3ca8238a81f4db93e524ee04aaf70966c51b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 14:58:29 +0900 Subject: [PATCH 022/215] Add property audio as public readonly. --- DLGPlayer/DLGPlayer.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 1695dcc..13dd990 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -19,6 +19,8 @@ #import "DLGPlayerUtils.h" #import "DLGSimplePlayerViewController.h" +@class DLGPlayerAudioManager; + typedef void (^onPauseComplete)(void); @interface DLGPlayer : NSObject @@ -33,6 +35,7 @@ typedef void (^onPauseComplete)(void); @property (nonatomic) BOOL playing; @property (nonatomic) BOOL buffering; @property (nonatomic, strong) NSDictionary *metadata; +@property (nonatomic, readonly) DLGPlayerAudioManager *audio; - (void)open:(NSString *)url; - (void)close; From e1fd0aae33d771dd6b88883edc5676d4a1eae309 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 7 Dec 2018 15:15:16 +0900 Subject: [PATCH 023/215] Update imports. --- DLGPlayer/DLGPlayer.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 13dd990..6173f5e 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -7,10 +7,11 @@ // #import +#import "DLGPlayerAudioFrame.h" +#import "DLGPlayerAudioManager.h" #import "DLGPlayerDef.h" #import "DLGPlayerDecoder.h" #import "DLGPlayerFrame.h" -#import "DLGPlayerAudioFrame.h" #import "DLGPlayerVideoFrame.h" #import "DLGPlayerVideoRGBFrame.h" #import "DLGPlayerVideoYUVFrame.h" @@ -19,8 +20,6 @@ #import "DLGPlayerUtils.h" #import "DLGSimplePlayerViewController.h" -@class DLGPlayerAudioManager; - typedef void (^onPauseComplete)(void); @interface DLGPlayer : NSObject From dfe51a7e44cdf8333396c1f61e33befbd4953e8b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 12 Dec 2018 14:18:52 +0900 Subject: [PATCH 024/215] Big modification: Add new script files to build ffmpeg with speex. --- .gitignore | 3 +- DLGPlayer.xcodeproj/project.pbxproj | 16 +- Example-Carthage/Cartfile.resolved | 2 +- .../DLGPlayerDemo.xcodeproj/project.pbxproj | 6 +- .../DLGPlayerDemo/ViewController.swift | 5 +- Example-Carthage/carthage_build.sh | 1 + Example-Carthage/carthage_update.sh | 1 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/DLGPlayer.xcscheme | 91 ++++++++ Example/DLGPlayer/Base.lproj/Main.storyboard | 28 +-- Example/DLGPlayer/Externals/ffmpeg/.gitignore | 0 README.md | 2 +- pre-build.sh | 37 ---- sh/build-ffmpeg.sh | 143 ++++++++++++ sh/build-ogg.sh | 104 +++++++++ sh/build-speex.sh | 105 +++++++++ sh/build.sh | 57 +++++ sh/pull-ogg.sh | 42 ++++ sh/pull-speex.sh | 42 ++++ sh/tools/do-compile-ogg.sh | 187 ++++++++++++++++ sh/tools/do-compile-speex.sh | 204 ++++++++++++++++++ sh/tools/pull-repo-base.sh | 15 ++ sh/tools/pull-repo-ref.sh | 17 ++ sh/tools/setup-as-commiter.sh | 7 + sh/tools/sync-mirrors.sh | 7 + 25 files changed, 1066 insertions(+), 64 deletions(-) create mode 100644 Example-Carthage/carthage_build.sh create mode 100644 Example-Carthage/carthage_update.sh create mode 100644 Example/DLGPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Example/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme delete mode 100644 Example/DLGPlayer/Externals/ffmpeg/.gitignore delete mode 100755 pre-build.sh create mode 100755 sh/build-ffmpeg.sh create mode 100755 sh/build-ogg.sh create mode 100755 sh/build-speex.sh create mode 100755 sh/build.sh create mode 100755 sh/pull-ogg.sh create mode 100755 sh/pull-speex.sh create mode 100755 sh/tools/do-compile-ogg.sh create mode 100755 sh/tools/do-compile-speex.sh create mode 100755 sh/tools/pull-repo-base.sh create mode 100755 sh/tools/pull-repo-ref.sh create mode 100755 sh/tools/setup-as-commiter.sh create mode 100755 sh/tools/sync-mirrors.sh diff --git a/.gitignore b/.gitignore index 7c3b1c8..bc61d34 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ fastlane/screenshots iOSInjectionProject/ -ffmpeg/ +libs/ +sh/build/ Example-Carthage/Carthage/ diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index 7eee518..eb84b33 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -375,7 +375,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "${SRCROOT}/pre-build.sh\n"; + shellScript = "${SRCROOT}/sh/build.sh\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -560,7 +560,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; HEADER_SEARCH_PATHS = ( "$(inherited)", - "${SRCROOT}/ffmpeg/FFmpeg-iOS/include", + "${SRCROOT}/libs/include", ); INFOPLIST_FILE = DLGPlayer/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -571,12 +571,13 @@ ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "${SRCROOT}/ffmpeg/lib", - "$(PROJECT_DIR)/ffmpeg/FFmpeg-iOS/lib", + "$(PROJECT_DIR)/libs/lib", ); OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", + "-l\"ogg\"", + "-l\"speex\"", "-l\"avcodec\"", "-l\"avdevice\"", "-l\"avfilter\"", @@ -626,7 +627,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; HEADER_SEARCH_PATHS = ( "$(inherited)", - "${SRCROOT}/ffmpeg/FFmpeg-iOS/include", + "${SRCROOT}/libs/include", ); INFOPLIST_FILE = DLGPlayer/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -637,13 +638,14 @@ ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "${SRCROOT}/ffmpeg/lib", - "$(PROJECT_DIR)/ffmpeg/FFmpeg-iOS/lib", + "$(PROJECT_DIR)/libs/lib", ); ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", + "-l\"ogg\"", + "-l\"speex\"", "-l\"avcodec\"", "-l\"avdevice\"", "-l\"avfilter\"", diff --git a/Example-Carthage/Cartfile.resolved b/Example-Carthage/Cartfile.resolved index 4e0d208..26ff205 100644 --- a/Example-Carthage/Cartfile.resolved +++ b/Example-Carthage/Cartfile.resolved @@ -1 +1 @@ -github "pisces/DLGPlayer" "ab2d0d6c999d85791706c282f35a43e38aa6bdd7" +github "pisces/DLGPlayer" "e1fd0aae33d771dd6b88883edc5676d4a1eae309" diff --git a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj index e76680b..4a9da0f 100644 --- a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj +++ b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj @@ -320,7 +320,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -375,7 +375,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; @@ -390,6 +390,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = F5NU2PA3PK; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", @@ -412,6 +413,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = F5NU2PA3PK; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", diff --git a/Example-Carthage/DLGPlayerDemo/ViewController.swift b/Example-Carthage/DLGPlayerDemo/ViewController.swift index a5a5472..0e3185c 100644 --- a/Example-Carthage/DLGPlayerDemo/ViewController.swift +++ b/Example-Carthage/DLGPlayerDemo/ViewController.swift @@ -23,7 +23,8 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - playerViewController.url = "/path/to/video" + playerViewController.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" + playerViewController.player.minBufferDuration = 1 playerViewController.open() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { @@ -60,6 +61,8 @@ extension ViewController: DLGSimplePlayerViewControllerDelegate { startTimer() case .closed: stopTimer() + case .playing: + print("player.audio.volume", playerViewController.player.audio.volume) default: () } } diff --git a/Example-Carthage/carthage_build.sh b/Example-Carthage/carthage_build.sh new file mode 100644 index 0000000..b8c5ef3 --- /dev/null +++ b/Example-Carthage/carthage_build.sh @@ -0,0 +1 @@ +XCODE_XCCONFIG_FILE="Carthage.xcconfig" carthage build diff --git a/Example-Carthage/carthage_update.sh b/Example-Carthage/carthage_update.sh new file mode 100644 index 0000000..58986b5 --- /dev/null +++ b/Example-Carthage/carthage_update.sh @@ -0,0 +1 @@ +XCODE_XCCONFIG_FILE="Carthage.xcconfig" carthage update diff --git a/Example/DLGPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/DLGPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example/DLGPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme b/Example/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme new file mode 100644 index 0000000..fe5f5f9 --- /dev/null +++ b/Example/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/DLGPlayer/Base.lproj/Main.storyboard b/Example/DLGPlayer/Base.lproj/Main.storyboard index 728cac6..948f346 100644 --- a/Example/DLGPlayer/Base.lproj/Main.storyboard +++ b/Example/DLGPlayer/Base.lproj/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -61,11 +61,11 @@ - + - + @@ -85,7 +85,7 @@ - + @@ -94,17 +94,17 @@ - + - + - + diff --git a/Example/DLGPlayer/Externals/ffmpeg/.gitignore b/Example/DLGPlayer/Externals/ffmpeg/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/README.md b/README.md index 78e8959..101549e 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,7 @@ $ brew install carthage To integrate DLGPlayer into your Xcode project using Carthage, specify it in your `Cartfile`: ```ogdl -github "DeviLeo/DLGPlayer" "master" +github "pisces/DLGPlayer" "master" ``` Run `XCODE_XCCONFIG_FILE="Carthage.xcconfig" carthage update` to build the framework and drag the built `DLGPlayer.framework` into your Xcode project. diff --git a/pre-build.sh b/pre-build.sh deleted file mode 100755 index 5784920..0000000 --- a/pre-build.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -BUILD_FFMPEG_FILE="build-ffmpeg.sh" -FFMPEG_IOS_BUILD_FILE_URL="https://github.com/kewlbear/FFmpeg-iOS-build-script/raw/master/$BUILD_FFMPEG_FILE" -FFMPEG_OUTPUT_FOLDER="ffmpeg" - -function MakeFFmpegDir() { - if [ ! -d "$FFMPEG_OUTPUT_FOLDER" ] - then - mkdir $FFMPEG_OUTPUT_FOLDER - fi - cd $FFMPEG_OUTPUT_FOLDER -} -function DownloadFFmpegBuildScript() { - if [ -f "$BUILD_FFMPEG_FILE" ] - then - echo "Already exist file $BUILD_FFMPEG_FILE." - else - (curl --verbose -L "$FFMPEG_IOS_BUILD_FILE_URL" \ - -o ./$BUILD_FFMPEG_FILE \ - && chmod +x ./$BUILD_FFMPEG_FILE) \ - || exit 1 - fi -} - -function CompileFFmpeg() { - if [ -d "./FFmpeg-iOS" ] - then - echo "Already compiled ffmpeg-ios." - else - ./$BUILD_FFMPEG_FILE - fi -} - -MakeFFmpegDir -DownloadFFmpegBuildScript -CompileFFmpeg diff --git a/sh/build-ffmpeg.sh b/sh/build-ffmpeg.sh new file mode 100755 index 0000000..47f2404 --- /dev/null +++ b/sh/build-ffmpeg.sh @@ -0,0 +1,143 @@ +#!/bin/sh + +# directories +FF_VERSION="4.1" +#FF_VERSION="snapshot-git" +if [[ $FFMPEG_VERSION != "" ]]; then + FF_VERSION=$FFMPEG_VERSION +fi +SOURCE=`pwd`/"build/src/ffmpeg" +FAT=`pwd`/"../libs" +THIN=`pwd`/"build/thin/ffmpeg" + +CONFIGURE_FLAGS="--enable-cross-compile --disable-debug --disable-programs \ + --disable-doc --enable-pic" + +ARCHS="armv7 arm64 i386 x86_64" + +COMPILE="y" +LIPO="y" + +DEPLOYMENT_TARGET="8.0" + +if [ "$*" ] +then + if [ "$*" = "lipo" ] + then + # skip compile + COMPILE= + else + ARCHS="$*" + if [ $# -eq 1 ] + then + # skip lipo + LIPO= + fi + fi +fi + +if [ "$COMPILE" ] +then + if [ ! `which yasm` ] + then + echo 'Yasm not found' + if [ ! `which brew` ] + then + echo 'Homebrew not found. Trying to install...' + ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" \ + || exit 1 + fi + echo 'Trying to install Yasm...' + brew install yasm || exit 1 + fi + if [ ! `which gas-preprocessor.pl` ] + then + echo 'gas-preprocessor.pl not found. Trying to install...' + (curl -L https://github.com/libav/gas-preprocessor/raw/master/gas-preprocessor.pl \ + -o /usr/local/bin/gas-preprocessor.pl \ + && chmod +x /usr/local/bin/gas-preprocessor.pl) \ + || exit 1 + fi + + if [ ! -r $SOURCE ] + then + mkdir -p "$SOURCE" + cd $SOURCE + echo 'FFmpeg source not found. Trying to download...' + curl http://www.ffmpeg.org/releases/ffmpeg-$FF_VERSION.tar.bz2 | tar xj \ + || exit 1 + cd - + fi + + CWD=`pwd` + for ARCH in $ARCHS + do + echo "building $ARCH..." + mkdir -p "$SOURCE/$ARCH" + cd "$SOURCE/$ARCH" + + CFLAGS="-arch $ARCH" + if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64" ] + then + PLATFORM="iPhoneSimulator" + CFLAGS="$CFLAGS -mios-simulator-version-min=$DEPLOYMENT_TARGET" + else + PLATFORM="iPhoneOS" + CFLAGS="$CFLAGS -mios-version-min=$DEPLOYMENT_TARGET -fembed-bitcode" + if [ "$ARCH" = "arm64" ] + then + EXPORT="GASPP_FIX_XCODE5=1" + fi + fi + + XCRUN_SDK=`echo $PLATFORM | tr '[:upper:]' '[:lower:]'` + CC="xcrun -sdk $XCRUN_SDK clang" + + # force "configure" to use "gas-preprocessor.pl" (FFmpeg 3.3) + if [ "$ARCH" = "arm64" ] + then + AS="gas-preprocessor.pl -arch aarch64 -- $CC" + else + AS="gas-preprocessor.pl -- $CC" + fi + + CXXFLAGS="$CFLAGS" + LDFLAGS="$CFLAGS" + + echo "configure $ARCH -> $SOURCE/ffmpeg-$FF_VERSION" + + TMPDIR=${TMPDIR/%\/} $SOURCE/ffmpeg-$FF_VERSION/configure \ + --target-os=darwin \ + --arch=$ARCH \ + --cc="$CC" \ + --as="$AS" \ + $CONFIGURE_FLAGS \ + --extra-cflags="$CFLAGS" \ + --extra-ldflags="$LDFLAGS" \ + --prefix="$THIN/$ARCH" \ + || exit 1 + + make -j3 install $EXPORT || exit 1 + cd $CWD + done +fi + +if [ "$LIPO" ] +then + echo "building fat binaries..." + mkdir -p $FAT/lib + set - $ARCHS + CWD=`pwd` + cd $THIN/$1/lib + for LIB in *.a + do + cd $CWD + echo lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB 1>&2 + lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB || exit 1 + done + + cd $CWD + cp -rf $THIN/$1/include $FAT +fi + +echo Done diff --git a/sh/build-ogg.sh b/sh/build-ogg.sh new file mode 100755 index 0000000..fde8ba0 --- /dev/null +++ b/sh/build-ogg.sh @@ -0,0 +1,104 @@ +#! /usr/bin/env bash +# +# Copyright (C) 2013-2014 Zhang Rui +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +#---------- +# modify for your build tool + +FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386" +FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64" +FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64" + +FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS8_SDK + +#---------- +UNI_BUILD_ROOT=`pwd` +LIBS="$UNI_BUILD_ROOT/../libs" +UNI_TMP="$UNI_BUILD_ROOT/tmp" +UNI_TMP_LLVM_VER_FILE="$UNI_TMP/llvm.ver.txt" +FF_TARGET=$1 +set -e + +#---------- +FF_LIBS="libogg" + +#---------- +echo_archs() { + echo "====================" + echo "[*] check xcode version" + echo "====================" + echo "FF_ALL_ARCHS = $FF_ALL_ARCHS" +} + +do_lipo () { + LIB_FILE=$1 + LIPO_FLAGS= + for ARCH in $FF_ALL_ARCHS + do + LIPO_FLAGS="$LIPO_FLAGS $UNI_BUILD_ROOT/build/thin/ogg/$ARCH/lib/$LIB_FILE" + done + + xcrun lipo -create $LIPO_FLAGS -output $LIBS/lib/$LIB_FILE + xcrun lipo -info $LIBS/lib/$LIB_FILE +} + +do_lipo_all () { + mkdir -p $LIBS/lib + echo "lipo archs: $FF_ALL_ARCHS" + for FF_LIB in $FF_LIBS + do + do_lipo "$FF_LIB.a"; + done + + cp -R $UNI_BUILD_ROOT/build/thin/ogg/armv7/include $LIBS/ +} + +#---------- +if [ "$FF_TARGET" = "armv7" -o "$FF_TARGET" = "armv7s" -o "$FF_TARGET" = "arm64" ]; then + echo_archs + sh tools/do-compile-ogg.sh $FF_TARGET +elif [ "$FF_TARGET" = "i386" -o "$FF_TARGET" = "x86_64" ]; then + echo_archs + sh tools/do-compile-ogg.sh $FF_TARGET +elif [ "$FF_TARGET" = "lipo" ]; then + echo_archs + do_lipo_all +elif [ "$FF_TARGET" = "all" ]; then + echo_archs + for ARCH in $FF_ALL_ARCHS + do + sh tools/do-compile-ogg.sh $ARCH + done + + do_lipo_all +elif [ "$FF_TARGET" = "check" ]; then + echo_archs +elif [ "$FF_TARGET" = "clean" ]; then + echo_archs + for ARCH in $FF_ALL_ARCHS + do + cd ogg-$ARCH && git clean -xdf && cd - + done +else + echo "Usage:" + echo " compile-ogg.sh armv7|arm64|i386|x86_64" + echo " compile-ogg.sh armv7s (obselete)" + echo " compile-ogg.sh lipo" + echo " compile-ogg.sh all" + echo " compile-ogg.sh clean" + echo " compile-ogg.sh check" + exit 1 +fi diff --git a/sh/build-speex.sh b/sh/build-speex.sh new file mode 100755 index 0000000..0175796 --- /dev/null +++ b/sh/build-speex.sh @@ -0,0 +1,105 @@ +#! /usr/bin/env bash +# +# Copyright (C) 2013-2014 Zhang Rui +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +#---------- +# modify for your build tool + +FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386" +FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64" +FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64" + +FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS8_SDK + +#---------- +UNI_BUILD_ROOT=`pwd` +LIBS="$UNI_BUILD_ROOT/../libs" +UNI_TMP="$UNI_BUILD_ROOT/tmp" +UNI_TMP_LLVM_VER_FILE="$UNI_TMP/llvm.ver.txt" +FF_TARGET=$1 +set -e + +#---------- +FF_LIBS="libspeex" +OGG_LIBS="libogg" + +#---------- +echo_archs() { + echo "====================" + echo "[*] check xcode version" + echo "====================" + echo "FF_ALL_ARCHS = $FF_ALL_ARCHS" +} + +do_lipo () { + LIB_FILE=$1 + LIPO_FLAGS= + for ARCH in $FF_ALL_ARCHS + do + LIPO_FLAGS="$LIPO_FLAGS $UNI_BUILD_ROOT/build/thin/speex/$ARCH/lib/$LIB_FILE" + done + + xcrun lipo -create $LIPO_FLAGS -output $LIBS/lib/$LIB_FILE + xcrun lipo -info $LIBS/lib/$LIB_FILE +} + +do_lipo_all () { + mkdir -p $LIBS/lib + echo "lipo archs: $FF_ALL_ARCHS" + for FF_LIB in $FF_LIBS + do + do_lipo "$FF_LIB.a"; + done + + cp -R $UNI_BUILD_ROOT/build/thin/speex/armv7/include $LIBS +} + +#---------- +if [ "$FF_TARGET" = "armv7" -o "$FF_TARGET" = "armv7s" -o "$FF_TARGET" = "arm64" ]; then + echo_archs + sh tools/do-compile-speex.sh $FF_TARGET +elif [ "$FF_TARGET" = "i386" -o "$FF_TARGET" = "x86_64" ]; then + echo_archs + sh tools/do-compile-speex.sh $FF_TARGET +elif [ "$FF_TARGET" = "lipo" ]; then + echo_archs + do_lipo_all +elif [ "$FF_TARGET" = "all" ]; then + echo_archs + for ARCH in $FF_ALL_ARCHS + do + sh tools/do-compile-speex.sh $ARCH + done + + do_lipo_all +elif [ "$FF_TARGET" = "check" ]; then + echo_archs +elif [ "$FF_TARGET" = "clean" ]; then + echo_archs + for ARCH in $FF_ALL_ARCHS + do + cd speex-$ARCH && git clean -xdf && cd - + done +else + echo "Usage:" + echo " compile-speex.sh armv7|arm64|i386|x86_64" + echo " compile-speex.sh armv7s (obselete)" + echo " compile-speex.sh lipo" + echo " compile-speex.sh all" + echo " compile-speex.sh clean" + echo " compile-speex.sh check" + exit 1 +fi diff --git a/sh/build.sh b/sh/build.sh new file mode 100755 index 0000000..1221109 --- /dev/null +++ b/sh/build.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +TARGETS=$1 +LIBS=`pwd`"/libs" + +function buildLib() { + echo "include: ${LIBS}/include/$1, lib: ${LIBS}/lib/lib$1.a" + if [ -d "${LIBS}/include/$1" ] && [ -f "${LIBS}/lib/lib$1.a" ] + then + echo "Already compiled $1." + else + sh pull-$1.sh "all" + sh build-$1.sh "all" + fi +} + +function buildFFmpeg() { + if [ -d "${LIBS}/include/libavcodec" ] && + [ -d "${LIBS}/include/libavdevice" ] && + [ -d "${LIBS}/include/libavfilter" ] && + [ -d "${LIBS}/include/libavformat" ] && + [ -d "${LIBS}/include/libavutil" ] && + [ -d "${LIBS}/include/libswresample" ] && + [ -d "${LIBS}/include/libswscale" ] && + [ -f "${LIBS}/lib/libavcodec.a" ] && + [ -f "${LIBS}/lib/libavdevice.a" ] && + [ -f "${LIBS}/lib/libavfilter.a" ] && + [ -f "${LIBS}/lib/libavformat.a" ] && + [ -f "${LIBS}/lib/libavutil.a" ] && + [ -f "${LIBS}/lib/libswresample.a" ] && + [ -f "${LIBS}/lib/libswscale.a" ] + then + echo "Already compiled ffmpeg." + else + sh build-ffmpeg.sh + fi +} + +function buildTargets() { + for TARGET in $1 + do + if [ $TARGET = "ffmpeg" ]; then + buildFFmpeg + else + buildLib $TARGET + fi + done +} + +cd `pwd`/"sh" + +if [ ! $TARGETS ] +then + buildTargets "ogg speex ffmpeg" +else + buildTargets $TARGETS +fi diff --git a/sh/pull-ogg.sh b/sh/pull-ogg.sh new file mode 100755 index 0000000..6aef5bf --- /dev/null +++ b/sh/pull-ogg.sh @@ -0,0 +1,42 @@ +#! /usr/bin/env bash +# +# Copyright (C) 2013-2015 Zhang Rui +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +IJK_OGG_UPSTREAM=https://github.com/xiph/ogg.git +IJK_OGG_FORK=https://github.com/xiph/ogg.git +IJK_OGG_COMMIT=v1.3.3 +IJK_OGG_LOCAL_REPO=build/src/ogg/ogg-${IJK_OGG_COMMIT} + +set -e +TOOLS=tools + +echo "== pull ogg base ==" +sh $TOOLS/pull-repo-base.sh $IJK_OGG_UPSTREAM $IJK_OGG_LOCAL_REPO + +function pull_fork() +{ + echo "== pull ogg fork $1 ==" + sh $TOOLS/pull-repo-ref.sh $IJK_OGG_FORK build/src/ogg/$1 ${IJK_OGG_LOCAL_REPO} + cd build/src/ogg/$1 + git checkout ${IJK_OGG_COMMIT} -B ffmpeg-build + cd - +} + +pull_fork "armv7" +pull_fork "armv7s" +pull_fork "arm64" +pull_fork "i386" +pull_fork "x86_64" diff --git a/sh/pull-speex.sh b/sh/pull-speex.sh new file mode 100755 index 0000000..a78137e --- /dev/null +++ b/sh/pull-speex.sh @@ -0,0 +1,42 @@ +#! /usr/bin/env bash +# +# Copyright (C) 2013-2015 Zhang Rui +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +IJK_SPEEX_UPSTREAM=https://github.com/xiph/speex +IJK_SPEEX_FORK=https://github.com/HatsuneMikuV/speex.git +IJK_SPEEX_COMMIT=Speex-1.2.0 +IJK_SPEEX_LOCAL_REPO=build/src/speex/${IJK_SPEEX_COMMIT} + +set -e +TOOLS=tools + +echo "== pull speex base ==" +sh $TOOLS/pull-repo-base.sh $IJK_SPEEX_UPSTREAM $IJK_SPEEX_LOCAL_REPO + +function pull_fork() +{ + echo "== pull speex fork $1 ==" + sh $TOOLS/pull-repo-ref.sh $IJK_SPEEX_FORK build/src/speex/$1 ${IJK_SPEEX_LOCAL_REPO} + cd build/src/speex/$1 + git checkout ${IJK_SPEEX_COMMIT} -B ffmpeg-build + cd - +} + +pull_fork "armv7" +pull_fork "armv7s" +pull_fork "arm64" +pull_fork "i386" +pull_fork "x86_64" diff --git a/sh/tools/do-compile-ogg.sh b/sh/tools/do-compile-ogg.sh new file mode 100755 index 0000000..d6bd7c0 --- /dev/null +++ b/sh/tools/do-compile-ogg.sh @@ -0,0 +1,187 @@ +#! /usr/bin/env bash +# +# Copyright (C) 2013-2014 Zhang Rui +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This script is based on projects below +# https://github.com/cxjwin/speex_libs/blob/master/libogg-1.3.2/build_ogg_ios.sh + +#-------------------- +echo "====================" +echo "[*] check host" +echo "====================" +set -e + + +FF_XCRUN_DEVELOPER=`xcode-select -print-path` +if [ ! -d "$FF_XCRUN_DEVELOPER" ]; then + echo "xcode path is not set correctly $FF_XCRUN_DEVELOPER does not exist (most likely because of xcode > 4.3)" + echo "run" + echo "sudo xcode-select -switch " + echo "for default installation:" + echo "sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer" + exit 1 +fi + +case $FF_XCRUN_DEVELOPER in + *\ * ) + echo "Your Xcode path contains whitespaces, which is not supported." + exit 1 + ;; +esac + + +#-------------------- +# include + + +#-------------------- +# common defines +FF_ARCH=$1 +if [ -z "$FF_ARCH" ]; then + echo "You must specific an architecture 'armv7, armv7s, arm64, i386, x86_64, ...'.\n" + exit 1 +fi + + +FF_BUILD_ROOT=`pwd` +FF_TAGET_OS="darwin" + + +# ogg build params +export COMMON_FF_CFG_FLAGS= + +OGG_CFG_FLAGS= +OGG_EXTRA_CFLAGS= +OGG_CFG_CPU= + +# i386, x86_64 +OGG_CFG_FLAGS_SIMULATOR="--host=arm" + +# armv7, armv7s, arm64 +OGG_CFG_FLAGS_ARM= +OGG_CFG_FLAGS_ARM="--host=arm-apple-darwin" + +echo "build_root: $FF_BUILD_ROOT" + +#-------------------- +echo "====================" +echo "[*] config arch $FF_ARCH" +echo "====================" + +FF_BUILD_NAME="unknown" +FF_XCRUN_PLATFORM="iPhoneOS" +FF_XCRUN_OSVERSION= +FF_GASPP_EXPORT= + +if [ "$FF_ARCH" = "i386" ]; then + FF_BUILD_NAME="ogg/i386" + FF_XCRUN_PLATFORM="iPhoneSimulator" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0" + OGG_CFG_FLAGS="$OGG_CFG_FLAGS_SIMULATOR $OGG_CFG_FLAGS" +elif [ "$FF_ARCH" = "x86_64" ]; then + FF_BUILD_NAME="ogg/x86_64" + FF_XCRUN_PLATFORM="iPhoneSimulator" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0" + OGG_CFG_FLAGS="$OGG_CFG_FLAGS_SIMULATOR $OGG_CFG_FLAGS" +elif [ "$FF_ARCH" = "armv7" ]; then + FF_BUILD_NAME="ogg/armv7" + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + OGG_CFG_FLAGS="$OGG_CFG_FLAGS_ARM $OGG_CFG_FLAGS" +elif [ "$FF_ARCH" = "armv7s" ]; then + FF_BUILD_NAME="ogg/armv7s" + OGG_CFG_CPU="--cpu=swift" + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + OGG_CFG_FLAGS="$OGG_CFG_FLAGS_ARM $OGG_CFG_FLAGS" +elif [ "$FF_ARCH" = "arm64" ]; then + FF_BUILD_NAME="ogg/arm64" + FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0" + OGG_CFG_FLAGS="$OGG_CFG_FLAGS_ARM $OGG_CFG_FLAGS" + FF_GASPP_EXPORT="GASPP_FIX_XCODE5=1" +else + echo "unknown architecture $FF_ARCH"; + exit 1 +fi + +echo "build_name: $FF_BUILD_NAME" +echo "platform: $FF_XCRUN_PLATFORM" +echo "osversion: $FF_XCRUN_OSVERSION" + +#-------------------- +echo "====================" +echo "[*] make ios toolchain $FF_BUILD_NAME" +echo "====================" + + +FF_BUILD_SOURCE="$FF_BUILD_ROOT/build/src/$FF_BUILD_NAME" +FF_BUILD_PREFIX="$FF_BUILD_ROOT/build/thin/$FF_BUILD_NAME" + +mkdir -p $FF_BUILD_PREFIX + + +FF_XCRUN_SDK=`echo $FF_XCRUN_PLATFORM | tr '[:upper:]' '[:lower:]'` +FF_XCRUN_SDK_PLATFORM_PATH=`xcrun -sdk $FF_XCRUN_SDK --show-sdk-platform-path` +FF_XCRUN_SDK_PATH=`xcrun -sdk $FF_XCRUN_SDK --show-sdk-path` +FF_XCRUN_CC="xcrun -sdk $FF_XCRUN_SDK clang" + +export CROSS_TOP="$FF_XCRUN_SDK_PLATFORM_PATH/Developer" +export CROSS_SDK=`echo ${FF_XCRUN_SDK_PATH/#$CROSS_TOP\/SDKs\//}` +export BUILD_TOOL="$FF_XCRUN_DEVELOPER" +export CC="$FF_XCRUN_CC -arch $FF_ARCH $FF_XCRUN_OSVERSION" + +echo "build_source: $FF_BUILD_SOURCE" +echo "build_prefix: $FF_BUILD_PREFIX" +echo "CROSS_TOP: $CROSS_TOP" +echo "CROSS_SDK: $CROSS_SDK" +echo "BUILD_TOOL: $BUILD_TOOL" +echo "CC: $CC" + +#-------------------- +echo "\n--------------------" +echo "[*] configurate ogg" +echo "--------------------" + +OGG_CFG_FLAGS="$OGG_CFG_FLAGS --prefix=$FF_BUILD_PREFIX" + +# xcode configuration +export DEBUG_INFORMATION_FORMAT=dwarf-with-dsym + +function configure() { + cd $FF_BUILD_SOURCE + if [ -f "./Makefile" ]; then + echo 'reuse configure' + elif [ -f "./configure" ]; then + echo 'already run autogen.sh' + echo "config: $OGG_CFG_FLAGS" + ./Configure \ + $OGG_CFG_FLAGS + configure + else + echo 'should run autogen.sh first' + echo "config: $OGG_CFG_FLAGS" + ./autogen.sh + configure + fi +} + +configure + +#-------------------- +echo "\n--------------------" +echo "[*] compile ogg" +echo "--------------------" +set +e +make +make install diff --git a/sh/tools/do-compile-speex.sh b/sh/tools/do-compile-speex.sh new file mode 100755 index 0000000..884b7fc --- /dev/null +++ b/sh/tools/do-compile-speex.sh @@ -0,0 +1,204 @@ +#! /usr/bin/env bash +# +# Copyright (C) 2013-2014 Zhang Rui +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# This script is based on projects below +# https://github.com/cxjwin/speex_libs/blob/master/speex-1.2rc2/build_speex_ios.sh + +#-------------------- +echo "====================" +echo "[*] check host" +echo "====================" +set -e + + +FF_XCRUN_DEVELOPER=`xcode-select -print-path` +if [ ! -d "$FF_XCRUN_DEVELOPER" ]; then + echo "xcode path is not set correctly $FF_XCRUN_DEVELOPER does not exist (most likely because of xcode > 4.3)" + echo "run" + echo "sudo xcode-select -switch " + echo "for default installation:" + echo "sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer" + exit 1 +fi + +case $FF_XCRUN_DEVELOPER in + *\ * ) + echo "Your Xcode path contains whitespaces, which is not supported." + exit 1 + ;; +esac + + +#-------------------- +# include + + +#-------------------- +# common defines +FF_ARCH=$1 +if [ -z "$FF_ARCH" ]; then + echo "You must specific an architecture 'armv7, armv7s, arm64, i386, x86_64, ...'.\n" + exit 1 +fi + + +FF_BUILD_ROOT=`pwd` +FF_TAGET_OS="darwin" + + +# speex build params +export COMMON_FF_CFG_FLAGS= + +SPEEX_CFG_FLAGS= +SPEEX_EXTRA_CFLAGS= +SPEEX_CFG_CPU= + +# i386, x86_64 +SPEEX_CFG_FLAGS_SIMULATOR="--host=arm" + +# armv7, armv7s, arm64 +SPEEX_CFG_FLAGS_ARM= +SPEEX_CFG_FLAGS_ARM="--host=arm-apple-darwin" + +echo "build_root: $FF_BUILD_ROOT" + +#-------------------- +echo "====================" +echo "[*] config arch $FF_ARCH" +echo "====================" + +FF_BUILD_NAME="unknown" +FF_XCRUN_PLATFORM="iPhoneOS" +FF_XCRUN_OSVERSION= +FF_GASPP_EXPORT= + +if [ "$FF_ARCH" = "i386" ]; then + FF_BUILD_NAME="speex/i386" + FF_BUILD_NAME_OGG="ogg/i386" + FF_XCRUN_PLATFORM="iPhoneSimulator" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" +elif [ "$FF_ARCH" = "x86_64" ]; then + FF_BUILD_NAME="speex/x86_64" + FF_BUILD_NAME_OGG="ogg/x86_64" + FF_XCRUN_PLATFORM="iPhoneSimulator" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" +elif [ "$FF_ARCH" = "armv7" ]; then + FF_BUILD_NAME="speex/armv7" + FF_BUILD_NAME_OGG="ogg/armv7" + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" +# OPENSSL_CFG_CPU="--cpu=cortex-a8" +elif [ "$FF_ARCH" = "armv7s" ]; then + FF_BUILD_NAME="speex/armv7s" + FF_BUILD_NAME_OGG="ogg/armv7s" + SPEEX_CFG_CPU="--cpu=swift" + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" +elif [ "$FF_ARCH" = "arm64" ]; then + FF_BUILD_NAME="speex/arm64" + FF_BUILD_NAME_OGG="ogg/arm64" + FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" + FF_GASPP_EXPORT="GASPP_FIX_XCODE5=1" +else + echo "unknown architecture $FF_ARCH"; + exit 1 +fi + +echo "build_name: $FF_BUILD_NAME" +echo "platform: $FF_XCRUN_PLATFORM" +echo "osversion: $FF_XCRUN_OSVERSION" + +#-------------------- +echo "====================" +echo "[*] make ios toolchain $FF_BUILD_NAME" +echo "====================" + + +FF_BUILD_SOURCE="$FF_BUILD_ROOT/build/src/$FF_BUILD_NAME" +FF_BUILD_PREFIX="$FF_BUILD_ROOT/build/thin/$FF_BUILD_NAME" + +mkdir -p $FF_BUILD_PREFIX + + +FF_XCRUN_SDK=`echo $FF_XCRUN_PLATFORM | tr '[:upper:]' '[:lower:]'` +FF_XCRUN_SDK_PLATFORM_PATH=`xcrun -sdk $FF_XCRUN_SDK --show-sdk-platform-path` +FF_XCRUN_SDK_PATH=`xcrun -sdk $FF_XCRUN_SDK --show-sdk-path` +FF_XCRUN_CC="xcrun -sdk $FF_XCRUN_SDK clang" + +export CROSS_TOP="$FF_XCRUN_SDK_PLATFORM_PATH/Developer" +export CROSS_SDK=`echo ${FF_XCRUN_SDK_PATH/#$CROSS_TOP\/SDKs\//}` +export BUILD_TOOL="$FF_XCRUN_DEVELOPER" +export CC="$FF_XCRUN_CC -arch $FF_ARCH $FF_XCRUN_OSVERSION" + +echo "build_source: $FF_BUILD_SOURCE" +echo "build_prefix: $FF_BUILD_PREFIX" +echo "CROSS_TOP: $CROSS_TOP" +echo "CROSS_SDK: $CROSS_SDK" +echo "BUILD_TOOL: $BUILD_TOOL" +echo "CC: $CC" + +#-------------------- +echo "\n--------------------" +echo "[*] check OGG" +echo "----------------------" +FFMPEG_DEP_OGG=$FF_BUILD_ROOT/build/thin/$FF_BUILD_NAME_OGG +FFMPEG_DEP_OGG_LIB=$FF_BUILD_ROOT/build/thin/$FF_BUILD_NAME_OGG/lib +#-------------------- +# with ogg +if [ -f "${FFMPEG_DEP_OGG_LIB}/libogg.a" ]; then + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS --with-ogg=${FFMPEG_DEP_OGG}" +fi + +#-------------------- +echo "\n--------------------" +echo "[*] configurate speex" +echo "--------------------" + +SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS --prefix=$FF_BUILD_PREFIX" + +# xcode configuration +export DEBUG_INFORMATION_FORMAT=dwarf-with-dsym + +function configure() { + cd $FF_BUILD_SOURCE + if [ -f "./Makefile" ]; then + echo 'reuse configure' + elif [ -f "./configure" ]; then + echo 'already run autogen.sh' + echo "config: $SPEEX_CFG_FLAGS" + ./Configure \ + $SPEEX_CFG_FLAGS + configure + else + echo 'should run autogen.sh first' + ./autogen.sh + configure + fi +} + +configure + +#-------------------- +echo "\n--------------------" +echo "[*] compile speex" +echo "--------------------" +set +e +make +make install diff --git a/sh/tools/pull-repo-base.sh b/sh/tools/pull-repo-base.sh new file mode 100755 index 0000000..59fb5c7 --- /dev/null +++ b/sh/tools/pull-repo-base.sh @@ -0,0 +1,15 @@ +#! /usr/bin/env bash + +REMOTE_REPO=$1 +LOCAL_WORKSPACE=$2 + + +if [ -z $REMOTE_REPO -o -z $LOCAL_WORKSPACE ]; then + echo "invalid call pull-repo.sh '$REMOTE_REPO' '$LOCAL_WORKSPACE'" +elif [ ! -d $LOCAL_WORKSPACE ]; then + git clone $REMOTE_REPO $LOCAL_WORKSPACE +else + cd $LOCAL_WORKSPACE + git fetch --all --tags + cd - +fi diff --git a/sh/tools/pull-repo-ref.sh b/sh/tools/pull-repo-ref.sh new file mode 100755 index 0000000..d2247ed --- /dev/null +++ b/sh/tools/pull-repo-ref.sh @@ -0,0 +1,17 @@ +#! /usr/bin/env bash + +REMOTE_REPO=$1 +LOCAL_WORKSPACE=$2 +REF_REPO=$3 + +if [ -z $1 -o -z $2 -o -z $3 ]; then + echo "invalid call pull-repo.sh '$1' '$2' '$3'" +elif [ ! -d $LOCAL_WORKSPACE ]; then + git clone --reference $REF_REPO $REMOTE_REPO $LOCAL_WORKSPACE + cd $LOCAL_WORKSPACE + git repack -a +else + cd $LOCAL_WORKSPACE + git fetch --all --tags + cd - +fi diff --git a/sh/tools/setup-as-commiter.sh b/sh/tools/setup-as-commiter.sh new file mode 100755 index 0000000..73b2bc8 --- /dev/null +++ b/sh/tools/setup-as-commiter.sh @@ -0,0 +1,7 @@ +#! /usr/bin/env bash + +git remote add gitcafe git@gitcafe.com:bbcallen/ijkplayer.git +git remote add oschina git@git.oschina.net:bbcallen/ijkplayer.git +git remote add csdn git@code.csdn.net:bbcallen/ijkplayer.git +git fetch --all + diff --git a/sh/tools/sync-mirrors.sh b/sh/tools/sync-mirrors.sh new file mode 100755 index 0000000..bde1174 --- /dev/null +++ b/sh/tools/sync-mirrors.sh @@ -0,0 +1,7 @@ +#! /usr/bin/env bash + +git push origin --all --follow-tags +git push gitcafe --all --follow-tags +git push oschina --all --follow-tags +git push csdn --all --follow-tags + From e608d5376098a4056fea23ee44f9d89244d45d4b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 12 Dec 2018 14:24:04 +0900 Subject: [PATCH 025/215] Update README --- Example-Carthage/Cartfile.resolved | 2 +- README.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Example-Carthage/Cartfile.resolved b/Example-Carthage/Cartfile.resolved index 26ff205..b9b51bf 100644 --- a/Example-Carthage/Cartfile.resolved +++ b/Example-Carthage/Cartfile.resolved @@ -1 +1 @@ -github "pisces/DLGPlayer" "e1fd0aae33d771dd6b88883edc5676d4a1eae309" +github "pisces/DLGPlayer" "dfe51a7e44cdf8333396c1f61e33befbd4953e8b" diff --git a/README.md b/README.md index 101549e..4a79daa 100644 --- a/README.md +++ b/README.md @@ -165,5 +165,7 @@ github "pisces/DLGPlayer" "master" Run `XCODE_XCCONFIG_FILE="Carthage.xcconfig" carthage update` to build the framework and drag the built `DLGPlayer.framework` into your Xcode project. +It will build ffmpeg, ogg and speex when carthage build automacally. + ## 8. License See [LICENSE](https://github.com/DeviLeo/DLGPlayer/blob/master/LICENSE "LGPL-3.0"). From 0fa876ba8704d96fbcbc2652ea74c1aea22017a8 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 12 Dec 2018 14:26:59 +0900 Subject: [PATCH 026/215] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a79daa..19062ae 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ github "pisces/DLGPlayer" "master" Run `XCODE_XCCONFIG_FILE="Carthage.xcconfig" carthage update` to build the framework and drag the built `DLGPlayer.framework` into your Xcode project. -It will build ffmpeg, ogg and speex when carthage build automacally. +Cathage building will build ffmpeg, ogg and speex automacally. ## 8. License See [LICENSE](https://github.com/DeviLeo/DLGPlayer/blob/master/LICENSE "LGPL-3.0"). From a7d0a2ab55df70289815b8ba61bfd6600bdac2cc Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 13 Dec 2018 16:50:49 +0900 Subject: [PATCH 027/215] New feature: brightness filter Created new demo application includes source project. Update gitignore. --- .gitignore | 3 +- DLGPlayer.xcodeproj/project.pbxproj | 281 +++++++++++------- .../xcshareddata/xcschemes/DLGPlayer.xcscheme | 2 +- .../xcschemes/DLGPlayerDemo.xcscheme | 105 +++++++ DLGPlayer/DLGPlayer.h | 1 + DLGPlayer/DLGPlayer.m | 39 +-- DLGPlayer/frame/DLGPlayerVideoFrame.h | 1 + DLGPlayer/frame/DLGPlayerVideoFrame.m | 1 + DLGPlayer/frame/DLGPlayerVideoRGBFrame.m | 1 + DLGPlayer/frame/DLGPlayerVideoYUVFrame.m | 2 + .../resource/DLGPlayerYUVFragmentShader.glsl | 5 +- DLGPlayerDemo/AppDelegate.swift | 46 +++ .../AppIcon.appiconset/Contents.json | 98 ++++++ DLGPlayerDemo/Assets.xcassets/Contents.json | 6 + .../Base.lproj/LaunchScreen.storyboard | 25 ++ DLGPlayerDemo/Base.lproj/Main.storyboard | 133 +++++++++ DLGPlayerDemo/DLGPlayerDemo-Bridging-Header.h | 14 + DLGPlayerDemo/Info.plist | 45 +++ DLGPlayerDemo/ViewController.swift | 75 +++++ .../Base.lproj/LaunchScreen.storyboard | 10 +- .../DLGPlayerDemo/Base.lproj/Main.storyboard | 74 ++++- .../DLGPlayerDemo/ViewController.swift | 11 +- {sh => libs}/build-ffmpeg.sh | 30 +- {sh => libs}/build-ogg.sh | 4 +- {sh => libs}/build-speex.sh | 4 +- {sh => libs}/build.sh | 6 +- {sh => libs}/pull-ogg.sh | 0 {sh => libs}/pull-speex.sh | 0 {sh => libs}/tools/do-compile-ogg.sh | 0 {sh => libs}/tools/do-compile-speex.sh | 11 +- {sh => libs}/tools/pull-repo-base.sh | 0 {sh => libs}/tools/pull-repo-ref.sh | 0 {sh => libs}/tools/setup-as-commiter.sh | 0 {sh => libs}/tools/sync-mirrors.sh | 0 34 files changed, 866 insertions(+), 167 deletions(-) create mode 100644 DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme create mode 100644 DLGPlayerDemo/AppDelegate.swift create mode 100644 DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 DLGPlayerDemo/Assets.xcassets/Contents.json create mode 100644 DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard create mode 100644 DLGPlayerDemo/Base.lproj/Main.storyboard create mode 100644 DLGPlayerDemo/DLGPlayerDemo-Bridging-Header.h create mode 100644 DLGPlayerDemo/Info.plist create mode 100644 DLGPlayerDemo/ViewController.swift rename {sh => libs}/build-ffmpeg.sh (76%) rename {sh => libs}/build-ogg.sh (97%) rename {sh => libs}/build-speex.sh (97%) rename {sh => libs}/build.sh (94%) rename {sh => libs}/pull-ogg.sh (100%) rename {sh => libs}/pull-speex.sh (100%) rename {sh => libs}/tools/do-compile-ogg.sh (100%) rename {sh => libs}/tools/do-compile-speex.sh (96%) rename {sh => libs}/tools/pull-repo-base.sh (100%) rename {sh => libs}/tools/pull-repo-ref.sh (100%) rename {sh => libs}/tools/setup-as-commiter.sh (100%) rename {sh => libs}/tools/sync-mirrors.sh (100%) diff --git a/.gitignore b/.gitignore index bc61d34..03b4b51 100644 --- a/.gitignore +++ b/.gitignore @@ -60,7 +60,6 @@ fastlane/screenshots iOSInjectionProject/ -libs/ -sh/build/ +libs/build/ Example-Carthage/Carthage/ diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index eb84b33..ad5f236 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -19,7 +19,13 @@ 235409BD21BA05BC00533B9B /* DLGPlayerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293421B810B50012243A /* DLGPlayerView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 235409C621BA177A00533B9B /* DLGSimplePlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 235409C721BA177A00533B9B /* DLGSimplePlayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */; }; - 23DC26D821B80F5A0012243A /* DLGPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; }; + 239BC97121C234CF00DEEC73 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 239BC97021C234CF00DEEC73 /* AppDelegate.swift */; }; + 239BC97321C234CF00DEEC73 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 239BC97221C234CF00DEEC73 /* ViewController.swift */; }; + 239BC97621C234CF00DEEC73 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 239BC97421C234CF00DEEC73 /* Main.storyboard */; }; + 239BC97821C234D000DEEC73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 239BC97721C234D000DEEC73 /* Assets.xcassets */; }; + 239BC97B21C234D000DEEC73 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 239BC97921C234D000DEEC73 /* LaunchScreen.storyboard */; }; + 239BC99121C2362100DEEC73 /* DLGPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; }; + 239BC99321C2457600DEEC73 /* DLGPlayer.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 23DC293921B810B50012243A /* DLGPlayerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291421B810B40012243A /* DLGPlayerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 23DC293A21B810B50012243A /* DLGPlayerDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC291621B810B40012243A /* DLGPlayerDecoder.m */; }; 23DC293B21B810B50012243A /* DLGPlayerAudioManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC291721B810B40012243A /* DLGPlayerAudioManager.m */; }; @@ -41,22 +47,31 @@ 23DC295521B810B50012243A /* DLGPlayerUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 23DC293821B810B50012243A /* DLGPlayerUtils.m */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 23DC26D921B80F5A0012243A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 23DC26C521B80F5A0012243A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 23DC26CD21B80F5A0012243A; - remoteInfo = DLGPlayer; - }; -/* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 239BC99221C2456B00DEEC73 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 239BC99321C2457600DEEC73 /* DLGPlayer.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DLGSimplePlayerViewController.h; sourceTree = ""; }; 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DLGSimplePlayerViewController.m; sourceTree = ""; }; + 239BC96E21C234CF00DEEC73 /* DLGPlayerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DLGPlayerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 239BC97021C234CF00DEEC73 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 239BC97221C234CF00DEEC73 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 239BC97521C234CF00DEEC73 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 239BC97721C234D000DEEC73 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 239BC97A21C234D000DEEC73 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 239BC97C21C234D000DEEC73 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DLGPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 23DC26D221B80F5A0012243A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 23DC26D721B80F5A0012243A /* DLGPlayerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DLGPlayerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 23DC291421B810B40012243A /* DLGPlayerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DLGPlayerViewController.h; sourceTree = ""; }; 23DC291621B810B40012243A /* DLGPlayerDecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerDecoder.m; sourceTree = ""; }; 23DC291721B810B40012243A /* DLGPlayerAudioManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerAudioManager.m; sourceTree = ""; }; @@ -102,28 +117,42 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 23DC26CB21B80F5A0012243A /* Frameworks */ = { + 239BC96B21C234CF00DEEC73 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 239BC99121C2362100DEEC73 /* DLGPlayer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 23DC26D421B80F5A0012243A /* Frameworks */ = { + 23DC26CB21B80F5A0012243A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 23DC26D821B80F5A0012243A /* DLGPlayer.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 239BC96F21C234CF00DEEC73 /* DLGPlayerDemo */ = { + isa = PBXGroup; + children = ( + 239BC97021C234CF00DEEC73 /* AppDelegate.swift */, + 239BC97221C234CF00DEEC73 /* ViewController.swift */, + 239BC97421C234CF00DEEC73 /* Main.storyboard */, + 239BC97721C234D000DEEC73 /* Assets.xcassets */, + 239BC97921C234D000DEEC73 /* LaunchScreen.storyboard */, + 239BC97C21C234D000DEEC73 /* Info.plist */, + ); + path = DLGPlayerDemo; + sourceTree = ""; + }; 23DC26C421B80F5A0012243A = { isa = PBXGroup; children = ( 23DC26D021B80F5A0012243A /* DLGPlayer */, + 239BC96F21C234CF00DEEC73 /* DLGPlayerDemo */, 23DC26CF21B80F5A0012243A /* Products */, 23DC295D21B814470012243A /* Frameworks */, ); @@ -133,7 +162,7 @@ isa = PBXGroup; children = ( 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */, - 23DC26D721B80F5A0012243A /* DLGPlayerTests.xctest */, + 239BC96E21C234CF00DEEC73 /* DLGPlayerDemo.app */, ); name = Products; sourceTree = ""; @@ -144,15 +173,15 @@ 23DC291521B810B40012243A /* codec */, 23DC293521B810B50012243A /* common */, 23DC291A21B810B50012243A /* DLGPlayer.h */, - 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */, - 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */, 23DC291C21B810B50012243A /* DLGPlayer.m */, 23DC291421B810B40012243A /* DLGPlayerViewController.h */, 23DC291B21B810B50012243A /* DLGPlayerViewController.m */, + 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */, + 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */, 23DC292721B810B50012243A /* frame */, + 23DC26D221B80F5A0012243A /* Info.plist */, 23DC291D21B810B50012243A /* resource */, 23DC293221B810B50012243A /* view */, - 23DC26D221B80F5A0012243A /* Info.plist */, ); path = DLGPlayer; sourceTree = ""; @@ -261,6 +290,24 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 239BC96D21C234CF00DEEC73 /* DLGPlayerDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 239BC98C21C234D000DEEC73 /* Build configuration list for PBXNativeTarget "DLGPlayerDemo" */; + buildPhases = ( + 239BC96A21C234CF00DEEC73 /* Sources */, + 239BC96B21C234CF00DEEC73 /* Frameworks */, + 239BC96C21C234CF00DEEC73 /* Resources */, + 239BC99221C2456B00DEEC73 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DLGPlayerDemo; + productName = DLGPlayerDemo; + productReference = 239BC96E21C234CF00DEEC73 /* DLGPlayerDemo.app */; + productType = "com.apple.product-type.application"; + }; 23DC26CD21B80F5A0012243A /* DLGPlayer */ = { isa = PBXNativeTarget; buildConfigurationList = 23DC26E221B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayer" */; @@ -280,37 +327,20 @@ productReference = 23DC26CE21B80F5A0012243A /* DLGPlayer.framework */; productType = "com.apple.product-type.framework"; }; - 23DC26D621B80F5A0012243A /* DLGPlayerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 23DC26E521B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayerTests" */; - buildPhases = ( - 23DC26D321B80F5A0012243A /* Sources */, - 23DC26D421B80F5A0012243A /* Frameworks */, - 23DC26D521B80F5A0012243A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 23DC26DA21B80F5A0012243A /* PBXTargetDependency */, - ); - name = DLGPlayerTests; - productName = DLGPlayerTests; - productReference = 23DC26D721B80F5A0012243A /* DLGPlayerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 23DC26C521B80F5A0012243A /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 1010; LastUpgradeCheck = 1010; ORGANIZATIONNAME = "KWANG HYOUN KIM"; TargetAttributes = { - 23DC26CD21B80F5A0012243A = { + 239BC96D21C234CF00DEEC73 = { CreatedOnToolsVersion = 10.1; }; - 23DC26D621B80F5A0012243A = { + 23DC26CD21B80F5A0012243A = { CreatedOnToolsVersion = 10.1; }; }; @@ -330,12 +360,22 @@ projectRoot = ""; targets = ( 23DC26CD21B80F5A0012243A /* DLGPlayer */, - 23DC26D621B80F5A0012243A /* DLGPlayerTests */, + 239BC96D21C234CF00DEEC73 /* DLGPlayerDemo */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 239BC96C21C234CF00DEEC73 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 239BC97B21C234D000DEEC73 /* LaunchScreen.storyboard in Resources */, + 239BC97821C234D000DEEC73 /* Assets.xcassets in Resources */, + 239BC97621C234CF00DEEC73 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 23DC26CC21B80F5A0012243A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -349,13 +389,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 23DC26D521B80F5A0012243A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ @@ -375,11 +408,21 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "${SRCROOT}/sh/build.sh\n"; + shellScript = " +"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 239BC96A21C234CF00DEEC73 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 239BC97321C234CF00DEEC73 /* ViewController.swift in Sources */, + 239BC97121C234CF00DEEC73 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 23DC26CA21B80F5A0012243A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -399,24 +442,25 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 23DC26D321B80F5A0012243A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 23DC26DA21B80F5A0012243A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 23DC26CD21B80F5A0012243A /* DLGPlayer */; - targetProxy = 23DC26D921B80F5A0012243A /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ + 239BC97421C234CF00DEEC73 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 239BC97521C234CF00DEEC73 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 239BC97921C234D000DEEC73 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 239BC97A21C234D000DEEC73 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; 23DC291E21B810B50012243A /* DLGPlayerStrings.strings */ = { isa = PBXVariantGroup; children = ( @@ -430,6 +474,52 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 239BC98821C234D000DEEC73 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = F5NU2PA3PK; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = DLGPlayerDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OBJC_BRIDGING_HEADER = "${PRODUCT_NAME}/DLGPlayerDemo-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 239BC98921C234D000DEEC73 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = F5NU2PA3PK; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = DLGPlayerDemo/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = example.DLGPlayerDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OBJC_BRIDGING_HEADER = "${PRODUCT_NAME}/DLGPlayerDemo-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; 23DC26E021B80F5A0012243A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -558,10 +648,8 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "${SRCROOT}/libs/include", - ); + ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/libs/build/universal/include"; INFOPLIST_FILE = DLGPlayer/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( @@ -571,8 +659,9 @@ ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/libs/lib", + "$(PROJECT_DIR)/libs/build/universal/lib", ); + ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", @@ -625,10 +714,8 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "${SRCROOT}/libs/include", - ); + ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/libs/build/universal/include"; INFOPLIST_FILE = DLGPlayer/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( @@ -638,7 +725,7 @@ ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", - "$(PROJECT_DIR)/libs/lib", + "$(PROJECT_DIR)/libs/build/universal/lib", ); ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = ( @@ -684,64 +771,32 @@ }; name = Release; }; - 23DC26E621B80F5A0012243A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = DLGPlayerTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = pisces.libs.DLGPlayerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 23DC26E721B80F5A0012243A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = DLGPlayerTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = pisces.libs.DLGPlayerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 23DC26C821B80F5A0012243A /* Build configuration list for PBXProject "DLGPlayer" */ = { + 239BC98C21C234D000DEEC73 /* Build configuration list for PBXNativeTarget "DLGPlayerDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( - 23DC26E021B80F5A0012243A /* Debug */, - 23DC26E121B80F5A0012243A /* Release */, + 239BC98821C234D000DEEC73 /* Debug */, + 239BC98921C234D000DEEC73 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 23DC26E221B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayer" */ = { + 23DC26C821B80F5A0012243A /* Build configuration list for PBXProject "DLGPlayer" */ = { isa = XCConfigurationList; buildConfigurations = ( - 23DC26E321B80F5A0012243A /* Debug */, - 23DC26E421B80F5A0012243A /* Release */, + 23DC26E021B80F5A0012243A /* Debug */, + 23DC26E121B80F5A0012243A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 23DC26E521B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayerTests" */ = { + 23DC26E221B80F5A0012243A /* Build configuration list for PBXNativeTarget "DLGPlayer" */ = { isa = XCConfigurationList; buildConfigurations = ( - 23DC26E621B80F5A0012243A /* Debug */, - 23DC26E721B80F5A0012243A /* Release */, + 23DC26E321B80F5A0012243A /* Debug */, + 23DC26E421B80F5A0012243A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme index e48435b..a178d30 100644 --- a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme +++ b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayer.xcscheme @@ -52,7 +52,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 6173f5e..eb348fd 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -33,6 +33,7 @@ typedef void (^onPauseComplete)(void); @property (nonatomic) BOOL opened; @property (nonatomic) BOOL playing; @property (nonatomic) BOOL buffering; +@property (nonatomic) float brightness; @property (nonatomic, strong) NSDictionary *metadata; @property (nonatomic, readonly) DLGPlayerAudioManager *audio; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 7a9ea5d..c752535 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -63,24 +63,25 @@ - (void)initAll { } - (void)initVars { - self.minBufferDuration = DLGPlayerMinBufferDuration; - self.maxBufferDuration = DLGPlayerMaxBufferDuration; - self.bufferedDuration = 0; - self.mediaPosition = 0; - self.mediaSyncTime = 0; - self.vframes = [NSMutableArray arrayWithCapacity:128]; - self.aframes = [NSMutableArray arrayWithCapacity:128]; - self.playingAudioFrame = nil; - self.playingAudioFrameDataPosition = 0; - self.opening = NO; - self.buffering = NO; - self.playing = NO; - self.opened = NO; - self.requestSeek = NO; - self.requestSeekPosition = 0; - self.frameReaderThread = nil; - self.aFramesLock = dispatch_semaphore_create(1); - self.vFramesLock = dispatch_semaphore_create(1); + _minBufferDuration = DLGPlayerMinBufferDuration; + _maxBufferDuration = DLGPlayerMaxBufferDuration; + _bufferedDuration = 0; + _mediaPosition = 0; + _mediaSyncTime = 0; + _brightness = 1; + _vframes = [NSMutableArray arrayWithCapacity:128]; + _aframes = [NSMutableArray arrayWithCapacity:128]; + _playingAudioFrame = nil; + _playingAudioFrameDataPosition = 0; + _opening = NO; + _buffering = NO; + _playing = NO; + _opened = NO; + _requestSeek = NO; + _requestSeekPosition = 0; + _frameReaderThread = nil; + _aFramesLock = dispatch_semaphore_create(1); + _vFramesLock = dispatch_semaphore_create(1); } - (void)initView { @@ -387,6 +388,7 @@ - (void)render { // Render if has picture if (self.decoder.hasPicture && self.vframes.count > 0) { DLGPlayerVideoFrame *frame = self.vframes[0]; + frame.brightness = _brightness; self.view.contentSize = CGSizeMake(frame.width, frame.height); [self.vframes removeObjectAtIndex:0]; [self.view render:frame]; @@ -407,6 +409,7 @@ - (void)render { long timeout = dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_NOW); if (timeout == 0) { frame = self.vframes[0]; + frame.brightness = _brightness; self.mediaPosition = frame.position; self.bufferedDuration -= frame.duration; [self.vframes removeObjectAtIndex:0]; diff --git a/DLGPlayer/frame/DLGPlayerVideoFrame.h b/DLGPlayer/frame/DLGPlayerVideoFrame.h index 5748e8c..1ffcf1a 100644 --- a/DLGPlayer/frame/DLGPlayerVideoFrame.h +++ b/DLGPlayer/frame/DLGPlayerVideoFrame.h @@ -20,6 +20,7 @@ typedef enum : NSUInteger { @property (nonatomic) DLGPlayerVideoFrameType videoType; @property (nonatomic) int width; @property (nonatomic) int height; +@property (nonatomic) float brightness; - (BOOL)prepareRender:(GLuint)program; diff --git a/DLGPlayer/frame/DLGPlayerVideoFrame.m b/DLGPlayer/frame/DLGPlayerVideoFrame.m index 1859041..fb20722 100644 --- a/DLGPlayer/frame/DLGPlayerVideoFrame.m +++ b/DLGPlayer/frame/DLGPlayerVideoFrame.m @@ -13,6 +13,7 @@ @implementation DLGPlayerVideoFrame - (id)init { self = [super init]; if (self) { + _brightness = 1; self.type = kDLGPlayerFrameTypeVideo; } return self; diff --git a/DLGPlayer/frame/DLGPlayerVideoRGBFrame.m b/DLGPlayer/frame/DLGPlayerVideoRGBFrame.m index 656a353..8d8525c 100644 --- a/DLGPlayer/frame/DLGPlayerVideoRGBFrame.m +++ b/DLGPlayer/frame/DLGPlayerVideoRGBFrame.m @@ -73,6 +73,7 @@ - (BOOL)prepareRender:(GLuint)program { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, _texture); glUniform1i(_sampler, 0); + glUniform1f(glGetUniformLocation(program, "f_brightness"), self.brightness); return YES; } diff --git a/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m b/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m index 8d6f3cc..975f7df 100644 --- a/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m +++ b/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m @@ -101,6 +101,8 @@ - (BOOL)prepareRender:(GLuint)program { glUniform1i(_sampler[i], i); } + glUniform1f(glGetUniformLocation(program, "f_brightness"), self.brightness); + return YES; } diff --git a/DLGPlayer/resource/DLGPlayerYUVFragmentShader.glsl b/DLGPlayer/resource/DLGPlayerYUVFragmentShader.glsl index f1c903e..0f8e4f8 100644 --- a/DLGPlayer/resource/DLGPlayerYUVFragmentShader.glsl +++ b/DLGPlayer/resource/DLGPlayerYUVFragmentShader.glsl @@ -1,4 +1,5 @@ varying highp vec2 v_texcoord; +uniform highp float f_brightness; uniform sampler2D s_texture_y; uniform sampler2D s_texture_u; uniform sampler2D s_texture_v; @@ -11,6 +12,8 @@ void main() { highp float r = y + 1.402 * v; highp float g = y - 0.344 * u - 0.714 * v; highp float b = y + 1.772 * u; + highp vec3 rgb = vec3(r, g, b); + highp vec3 black = vec3(0, 0, 0); - gl_FragColor = vec4(r, g, b, 1); + gl_FragColor = vec4(mix(black, rgb, f_brightness), 1); } diff --git a/DLGPlayerDemo/AppDelegate.swift b/DLGPlayerDemo/AppDelegate.swift new file mode 100644 index 0000000..02d1988 --- /dev/null +++ b/DLGPlayerDemo/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 13/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d8db8d6 --- /dev/null +++ b/DLGPlayerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DLGPlayerDemo/Assets.xcassets/Contents.json b/DLGPlayerDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/DLGPlayerDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard b/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..bfa3612 --- /dev/null +++ b/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard new file mode 100644 index 0000000..8d49751 --- /dev/null +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DLGPlayerDemo/DLGPlayerDemo-Bridging-Header.h b/DLGPlayerDemo/DLGPlayerDemo-Bridging-Header.h new file mode 100644 index 0000000..34781b4 --- /dev/null +++ b/DLGPlayerDemo/DLGPlayerDemo-Bridging-Header.h @@ -0,0 +1,14 @@ +// +// DLGPlayerDemo-Bridging-Header.h +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 07/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +#ifndef DLGPlayerDemo_Bridging_Header_h +#define DLGPlayerDemo_Bridging_Header_h + +@import DLGPlayer; + +#endif /* DLGPlayerDemo_Bridging_Header_h */ diff --git a/DLGPlayerDemo/Info.plist b/DLGPlayerDemo/Info.plist new file mode 100644 index 0000000..16be3b6 --- /dev/null +++ b/DLGPlayerDemo/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift new file mode 100644 index 0000000..22fe3ce --- /dev/null +++ b/DLGPlayerDemo/ViewController.swift @@ -0,0 +1,75 @@ +// +// ViewController.swift +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 07/12/2018. +// Copyright © 2018 KWANG HYOUN KIM. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController { + + private var timer: Timer? + private var playerViewController: DLGSimplePlayerViewController! { + didSet { + playerViewController.delegate = self + playerViewController.autoplay = true + playerViewController.repeat = true + playerViewController.preventFromScreenLock = true + playerViewController.restorePlayAfterAppEnterForeground = true + } + } + + override func viewDidLoad() { + super.viewDidLoad() + + playerViewController.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" + playerViewController.player.minBufferDuration = 1 + playerViewController.player.audio.volume = 1 + playerViewController.open() + } + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + switch segue.destination { + case let vc as DLGSimplePlayerViewController: + playerViewController = vc + default: () + } + } + + private func startTimer() { + stopTimer() + timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerCompletion), userInfo: nil, repeats: true) + } + private func stopTimer() { + timer?.invalidate() + timer = nil + } + + @objc private func timerCompletion() { +// print("player.position", playerViewController.player.position) + } + + @IBAction private func valueChanged(_ sender: UISlider) { + playerViewController.player.brightness = sender.value + } +} + +extension ViewController: DLGSimplePlayerViewControllerDelegate { + func viewController(_ viewController: DLGSimplePlayerViewController, didReceiveError error: Error) { + print("didReceiveError", error) + } + func viewController(_ viewController: DLGSimplePlayerViewController, didChange status: DLGPlayerStatus) { + print("didChange", status.rawValue) + + switch status { + case .opened: + startTimer() + case .closed: + stopTimer() +// case .playing: +// print("player.audio.volume", playerViewController.player.audio.volume) + default: () + } + } +} diff --git a/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard b/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard index bfa3612..42a6734 100644 --- a/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard +++ b/Example-Carthage/DLGPlayerDemo/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,11 @@ - - + + + + + - + + diff --git a/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard b/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard index b3ce660..9b0f7a3 100644 --- a/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/Example-Carthage/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -15,11 +15,11 @@ - + - + @@ -40,19 +40,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + + + + diff --git a/Example-Carthage/DLGPlayerDemo/ViewController.swift b/Example-Carthage/DLGPlayerDemo/ViewController.swift index 0e3185c..8e8b6f3 100644 --- a/Example-Carthage/DLGPlayerDemo/ViewController.swift +++ b/Example-Carthage/DLGPlayerDemo/ViewController.swift @@ -19,12 +19,15 @@ class ViewController: UIViewController { playerViewController.restorePlayAfterAppEnterForeground = true } } + + private static var num: Int = 11 override func viewDidLoad() { super.viewDidLoad() playerViewController.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" playerViewController.player.minBufferDuration = 1 + playerViewController.player.audio.volume = 1 playerViewController.open() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { @@ -45,7 +48,7 @@ class ViewController: UIViewController { } @objc private func timerCompletion() { - print("player.position", playerViewController.player.position) +// print("player.position", playerViewController.player.position) } } @@ -54,15 +57,15 @@ extension ViewController: DLGSimplePlayerViewControllerDelegate { print("didReceiveError", error) } func viewController(_ viewController: DLGSimplePlayerViewController, didChange status: DLGPlayerStatus) { - print("didChange", status) + print("didChange", status.rawValue) switch status { case .opened: startTimer() case .closed: stopTimer() - case .playing: - print("player.audio.volume", playerViewController.player.audio.volume) +// case .playing: +// print("player.audio.volume", playerViewController.player.audio.volume) default: () } } diff --git a/sh/build-ffmpeg.sh b/libs/build-ffmpeg.sh similarity index 76% rename from sh/build-ffmpeg.sh rename to libs/build-ffmpeg.sh index 47f2404..32a3113 100755 --- a/sh/build-ffmpeg.sh +++ b/libs/build-ffmpeg.sh @@ -7,13 +7,16 @@ if [[ $FFMPEG_VERSION != "" ]]; then FF_VERSION=$FFMPEG_VERSION fi SOURCE=`pwd`/"build/src/ffmpeg" -FAT=`pwd`/"../libs" -THIN=`pwd`/"build/thin/ffmpeg" +FAT=`pwd`/"build/universal" +THIN=`pwd`/"build/thin" +FFMPEG=$THIN/ffmpeg -CONFIGURE_FLAGS="--enable-cross-compile --disable-debug --disable-programs \ - --disable-doc --enable-pic" +echo "PKG_CONFIG_PATH -> $PKG_CONFIG_PATH" -ARCHS="armv7 arm64 i386 x86_64" +CONFIGURE_FLAGS="--enable-cross-compile --enable-static --disable-shared --disable-debug --disable-programs \ + --disable-doc --enable-pic --enable-neon --enable-optimizations --enable-small" + +ARCHS="armv7 armv7s arm64 i386 x86_64" COMPILE="y" LIPO="y" @@ -103,6 +106,13 @@ then CXXFLAGS="$CFLAGS" LDFLAGS="$CFLAGS" + SPEEX=$THIN/speex/$ARCH + + if [ -f "${SPEEX}/lib/libspeex.a" ]; then + CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-libspeex" + CFLAGS="$CFLAGS -I$SPEEX/include" + LDFLAGS="$LDFLAGS -L$SPEEX/lib -lspeex" + fi echo "configure $ARCH -> $SOURCE/ffmpeg-$FF_VERSION" @@ -114,7 +124,7 @@ then $CONFIGURE_FLAGS \ --extra-cflags="$CFLAGS" \ --extra-ldflags="$LDFLAGS" \ - --prefix="$THIN/$ARCH" \ + --prefix="$FFMPEG/$ARCH" \ || exit 1 make -j3 install $EXPORT || exit 1 @@ -128,16 +138,16 @@ then mkdir -p $FAT/lib set - $ARCHS CWD=`pwd` - cd $THIN/$1/lib + cd $FFMPEG/$1/lib for LIB in *.a do cd $CWD - echo lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB 1>&2 - lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB || exit 1 + echo lipo -create `find $FFMPEG -name $LIB` -output $FAT/lib/$LIB 1>&2 + lipo -create `find $FFMPEG -name $LIB` -output $FAT/lib/$LIB || exit 1 done cd $CWD - cp -rf $THIN/$1/include $FAT + cp -rf $FFMPEG/$1/include $FAT fi echo Done diff --git a/sh/build-ogg.sh b/libs/build-ogg.sh similarity index 97% rename from sh/build-ogg.sh rename to libs/build-ogg.sh index fde8ba0..2b270dd 100755 --- a/sh/build-ogg.sh +++ b/libs/build-ogg.sh @@ -22,11 +22,11 @@ FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386" FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64" FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64" -FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS8_SDK +FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS7_SDK #---------- UNI_BUILD_ROOT=`pwd` -LIBS="$UNI_BUILD_ROOT/../libs" +LIBS="$UNI_BUILD_ROOT/build/universal" UNI_TMP="$UNI_BUILD_ROOT/tmp" UNI_TMP_LLVM_VER_FILE="$UNI_TMP/llvm.ver.txt" FF_TARGET=$1 diff --git a/sh/build-speex.sh b/libs/build-speex.sh similarity index 97% rename from sh/build-speex.sh rename to libs/build-speex.sh index 0175796..49e5daa 100755 --- a/sh/build-speex.sh +++ b/libs/build-speex.sh @@ -22,11 +22,11 @@ FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386" FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64" FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64" -FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS8_SDK +FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS7_SDK #---------- UNI_BUILD_ROOT=`pwd` -LIBS="$UNI_BUILD_ROOT/../libs" +LIBS="$UNI_BUILD_ROOT/build/universal" UNI_TMP="$UNI_BUILD_ROOT/tmp" UNI_TMP_LLVM_VER_FILE="$UNI_TMP/llvm.ver.txt" FF_TARGET=$1 diff --git a/sh/build.sh b/libs/build.sh similarity index 94% rename from sh/build.sh rename to libs/build.sh index 1221109..753b4c7 100755 --- a/sh/build.sh +++ b/libs/build.sh @@ -1,7 +1,7 @@ #!/bin/sh TARGETS=$1 -LIBS=`pwd`"/libs" +LIBS=`pwd`"/build/universal" function buildLib() { echo "include: ${LIBS}/include/$1, lib: ${LIBS}/lib/lib$1.a" @@ -47,7 +47,9 @@ function buildTargets() { done } -cd `pwd`/"sh" +cd `pwd`/"libs" + +sh config/module.sh if [ ! $TARGETS ] then diff --git a/sh/pull-ogg.sh b/libs/pull-ogg.sh similarity index 100% rename from sh/pull-ogg.sh rename to libs/pull-ogg.sh diff --git a/sh/pull-speex.sh b/libs/pull-speex.sh similarity index 100% rename from sh/pull-speex.sh rename to libs/pull-speex.sh diff --git a/sh/tools/do-compile-ogg.sh b/libs/tools/do-compile-ogg.sh similarity index 100% rename from sh/tools/do-compile-ogg.sh rename to libs/tools/do-compile-ogg.sh diff --git a/sh/tools/do-compile-speex.sh b/libs/tools/do-compile-speex.sh similarity index 96% rename from sh/tools/do-compile-speex.sh rename to libs/tools/do-compile-speex.sh index 884b7fc..6ad6090 100755 --- a/sh/tools/do-compile-speex.sh +++ b/libs/tools/do-compile-speex.sh @@ -88,31 +88,31 @@ FF_GASPP_EXPORT= if [ "$FF_ARCH" = "i386" ]; then FF_BUILD_NAME="speex/i386" - FF_BUILD_NAME_OGG="ogg/i386" + FF_BUILD_NAME_OGG=ogg/i386 FF_XCRUN_PLATFORM="iPhoneSimulator" FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" elif [ "$FF_ARCH" = "x86_64" ]; then FF_BUILD_NAME="speex/x86_64" - FF_BUILD_NAME_OGG="ogg/x86_64" + FF_BUILD_NAME_OGG=ogg/x86_64 FF_XCRUN_PLATFORM="iPhoneSimulator" FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" elif [ "$FF_ARCH" = "armv7" ]; then FF_BUILD_NAME="speex/armv7" - FF_BUILD_NAME_OGG="ogg/armv7" + FF_BUILD_NAME_OGG=ogg/armv7 FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" # OPENSSL_CFG_CPU="--cpu=cortex-a8" elif [ "$FF_ARCH" = "armv7s" ]; then FF_BUILD_NAME="speex/armv7s" - FF_BUILD_NAME_OGG="ogg/armv7s" + FF_BUILD_NAME_OGG=ogg/armv7s SPEEX_CFG_CPU="--cpu=swift" FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" elif [ "$FF_ARCH" = "arm64" ]; then FF_BUILD_NAME="speex/arm64" - FF_BUILD_NAME_OGG="ogg/arm64" + FF_BUILD_NAME_OGG=ogg/arm64 FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" FF_GASPP_EXPORT="GASPP_FIX_XCODE5=1" @@ -163,6 +163,7 @@ FFMPEG_DEP_OGG_LIB=$FF_BUILD_ROOT/build/thin/$FF_BUILD_NAME_OGG/lib #-------------------- # with ogg if [ -f "${FFMPEG_DEP_OGG_LIB}/libogg.a" ]; then + echo "FFMPEG_DEP_OGG -> $FFMPEG_DEP_OGG" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS --with-ogg=${FFMPEG_DEP_OGG}" fi diff --git a/sh/tools/pull-repo-base.sh b/libs/tools/pull-repo-base.sh similarity index 100% rename from sh/tools/pull-repo-base.sh rename to libs/tools/pull-repo-base.sh diff --git a/sh/tools/pull-repo-ref.sh b/libs/tools/pull-repo-ref.sh similarity index 100% rename from sh/tools/pull-repo-ref.sh rename to libs/tools/pull-repo-ref.sh diff --git a/sh/tools/setup-as-commiter.sh b/libs/tools/setup-as-commiter.sh similarity index 100% rename from sh/tools/setup-as-commiter.sh rename to libs/tools/setup-as-commiter.sh diff --git a/sh/tools/sync-mirrors.sh b/libs/tools/sync-mirrors.sh similarity index 100% rename from sh/tools/sync-mirrors.sh rename to libs/tools/sync-mirrors.sh From bcb958b1cad202b9459a788e82eb3cb8fcb4fc6b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 14 Dec 2018 11:35:05 +0900 Subject: [PATCH 028/215] New feature: mute function. Update demo application to control brightness and mute. --- DLGPlayer.xcodeproj/project.pbxproj | 22 +++-- DLGPlayer/DLGPlayer.m | 1 - DLGPlayer/codec/DLGPlayerAudioManager.h | 1 + DLGPlayer/codec/DLGPlayerAudioManager.m | 17 ++++ .../resource/DLGPlayerRGBFragmentShader.glsl | 6 +- DLGPlayerDemo/Base.lproj/Main.storyboard | 94 +++++-------------- DLGPlayerDemo/ViewController.swift | 7 +- 7 files changed, 67 insertions(+), 81 deletions(-) diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index ad5f236..bd6ec39 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -170,16 +170,16 @@ 23DC26D021B80F5A0012243A /* DLGPlayer */ = { isa = PBXGroup; children = ( - 23DC291521B810B40012243A /* codec */, - 23DC293521B810B50012243A /* common */, 23DC291A21B810B50012243A /* DLGPlayer.h */, 23DC291C21B810B50012243A /* DLGPlayer.m */, 23DC291421B810B40012243A /* DLGPlayerViewController.h */, 23DC291B21B810B50012243A /* DLGPlayerViewController.m */, 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */, 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */, - 23DC292721B810B50012243A /* frame */, 23DC26D221B80F5A0012243A /* Info.plist */, + 23DC291521B810B40012243A /* codec */, + 23DC293521B810B50012243A /* common */, + 23DC292721B810B50012243A /* frame */, 23DC291D21B810B50012243A /* resource */, 23DC293221B810B50012243A /* view */, ); @@ -189,10 +189,10 @@ 23DC291521B810B40012243A /* codec */ = { isa = PBXGroup; children = ( - 23DC291621B810B40012243A /* DLGPlayerDecoder.m */, + 23DC291921B810B40012243A /* DLGPlayerAudioManager.h */, 23DC291721B810B40012243A /* DLGPlayerAudioManager.m */, 23DC291821B810B40012243A /* DLGPlayerDecoder.h */, - 23DC291921B810B40012243A /* DLGPlayerAudioManager.h */, + 23DC291621B810B40012243A /* DLGPlayerDecoder.m */, ); path = codec; sourceTree = ""; @@ -342,6 +342,7 @@ }; 23DC26CD21B80F5A0012243A = { CreatedOnToolsVersion = 10.1; + LastSwiftMigration = 1010; }; }; }; @@ -481,8 +482,9 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = F5NU2PA3PK; ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = DLGPlayerDemo/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -504,8 +506,9 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = F5NU2PA3PK; ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = DLGPlayerDemo/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.1; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -642,6 +645,7 @@ 23DC26E321B80F5A0012243A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; @@ -701,6 +705,8 @@ PRODUCT_BUNDLE_IDENTIFIER = carthage.DLGPlayer; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -708,6 +714,7 @@ 23DC26E421B80F5A0012243A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; @@ -767,6 +774,7 @@ PRODUCT_BUNDLE_IDENTIFIER = carthage.DLGPlayer; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index c752535..6b3c7a9 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -38,7 +38,6 @@ @interface DLGPlayer () @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; - @end @implementation DLGPlayer diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.h b/DLGPlayer/codec/DLGPlayerAudioManager.h index 7430f16..3ab6039 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.h +++ b/DLGPlayer/codec/DLGPlayerAudioManager.h @@ -12,6 +12,7 @@ typedef void(^DLGPlayerAudioManagerFrameReaderBlock)(float *data, UInt32 num, UI @interface DLGPlayerAudioManager : NSObject +@property (nonatomic) BOOL mute; @property (nonatomic, copy) DLGPlayerAudioManagerFrameReaderBlock frameReaderBlock; @property (nonatomic) float volume; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 99ed490..af175d3 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -51,6 +51,7 @@ - (id)init { } - (void)initVars { + _mute = NO; _registeredKVO = NO; _opened = NO; _closing = NO; @@ -72,6 +73,18 @@ - (void)dealloc { } } +#pragma mark - Added by KKH to mute sound. + +- (void)setMute:(BOOL)mute { + _mute = mute; + + if (_mute) { + [self pause]; + } else { + [self play]; + } +} + /* * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ @@ -308,6 +321,10 @@ - (BOOL)play { } - (BOOL)play:(NSError **)error { + if (_mute) { + return _playing; + } + if (_opened) { OSStatus status = AudioOutputUnitStart(_audioUnit); _playing = (status == noErr); diff --git a/DLGPlayer/resource/DLGPlayerRGBFragmentShader.glsl b/DLGPlayer/resource/DLGPlayerRGBFragmentShader.glsl index fc71053..2e896f0 100644 --- a/DLGPlayer/resource/DLGPlayerRGBFragmentShader.glsl +++ b/DLGPlayer/resource/DLGPlayerRGBFragmentShader.glsl @@ -1,6 +1,10 @@ varying highp vec2 v_texcoord; +uniform highp float f_brightness; uniform sampler2D s_texture; void main() { - gl_FragColor = texture2D(s_texture, v_texcoord); + highp vec4 texture = texture2D(s_texture, v_texcoord); + highp vec3 black = vec3(0, 0, 0); + + gl_FragColor = vec4(mix(black, texture.rgb, f_brightness), 1); } diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index 8d49751..ebfc798 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -15,11 +15,11 @@ - + - + @@ -27,21 +27,40 @@ + - + + + + + - + + + @@ -49,74 +68,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -127,7 +84,4 @@ - - - diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 22fe3ce..a91217f 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -26,7 +26,6 @@ class ViewController: UIViewController { playerViewController.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" playerViewController.player.minBufferDuration = 1 - playerViewController.player.audio.volume = 1 playerViewController.open() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { @@ -47,9 +46,13 @@ class ViewController: UIViewController { } @objc private func timerCompletion() { -// print("player.position", playerViewController.player.position) + print("player.position", playerViewController.player.position) } + @IBAction private func clicked(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + playerViewController.player.audio.mute = sender.isSelected + } @IBAction private func valueChanged(_ sender: UISlider) { playerViewController.player.brightness = sender.value } From 098592fa8e5b802cbb7a7497737e5d5468182f95 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 14 Dec 2018 15:56:43 +0900 Subject: [PATCH 029/215] Update build scripts. --- libs/build-ffmpeg.sh | 6 +- libs/build-speex.sh | 250 +++++++++++++++++++++++---------- libs/build.sh | 6 +- libs/tools/do-compile-ogg.sh | 4 +- libs/tools/do-compile-speex.sh | 4 +- 5 files changed, 185 insertions(+), 85 deletions(-) diff --git a/libs/build-ffmpeg.sh b/libs/build-ffmpeg.sh index 32a3113..2099942 100755 --- a/libs/build-ffmpeg.sh +++ b/libs/build-ffmpeg.sh @@ -11,8 +11,6 @@ FAT=`pwd`/"build/universal" THIN=`pwd`/"build/thin" FFMPEG=$THIN/ffmpeg -echo "PKG_CONFIG_PATH -> $PKG_CONFIG_PATH" - CONFIGURE_FLAGS="--enable-cross-compile --enable-static --disable-shared --disable-debug --disable-programs \ --disable-doc --enable-pic --enable-neon --enable-optimizations --enable-small" @@ -23,6 +21,10 @@ LIPO="y" DEPLOYMENT_TARGET="8.0" +if [ -f "${FAT}/lib/libspeex.a" ]; then + brew install speex +fi + if [ "$*" ] then if [ "$*" = "lipo" ] diff --git a/libs/build-speex.sh b/libs/build-speex.sh index 49e5daa..c65c3e0 100755 --- a/libs/build-speex.sh +++ b/libs/build-speex.sh @@ -15,91 +15,191 @@ # limitations under the License. # -#---------- -# modify for your build tool +# This script is based on projects below +# https://github.com/cxjwin/speex_libs/blob/master/speex-1.2rc2/build_speex_ios.sh -FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386" -FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64" -FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64" +#-------------------- +echo "====================" +echo "[*] check host" +echo "====================" +set -e -FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS7_SDK -#---------- -UNI_BUILD_ROOT=`pwd` -LIBS="$UNI_BUILD_ROOT/build/universal" -UNI_TMP="$UNI_BUILD_ROOT/tmp" -UNI_TMP_LLVM_VER_FILE="$UNI_TMP/llvm.ver.txt" -FF_TARGET=$1 -set -e +FF_XCRUN_DEVELOPER=`xcode-select -print-path` +if [ ! -d "$FF_XCRUN_DEVELOPER" ]; then + echo "xcode path is not set correctly $FF_XCRUN_DEVELOPER does not exist (most likely because of xcode > 4.3)" + echo "run" + echo "sudo xcode-select -switch " + echo "for default installation:" + echo "sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer" + exit 1 +fi -#---------- -FF_LIBS="libspeex" -OGG_LIBS="libogg" +case $FF_XCRUN_DEVELOPER in + *\ * ) + echo "Your Xcode path contains whitespaces, which is not supported." + exit 1 + ;; +esac -#---------- -echo_archs() { - echo "====================" - echo "[*] check xcode version" - echo "====================" - echo "FF_ALL_ARCHS = $FF_ALL_ARCHS" -} -do_lipo () { - LIB_FILE=$1 - LIPO_FLAGS= - for ARCH in $FF_ALL_ARCHS - do - LIPO_FLAGS="$LIPO_FLAGS $UNI_BUILD_ROOT/build/thin/speex/$ARCH/lib/$LIB_FILE" - done +#-------------------- +# include - xcrun lipo -create $LIPO_FLAGS -output $LIBS/lib/$LIB_FILE - xcrun lipo -info $LIBS/lib/$LIB_FILE -} -do_lipo_all () { - mkdir -p $LIBS/lib - echo "lipo archs: $FF_ALL_ARCHS" - for FF_LIB in $FF_LIBS - do - do_lipo "$FF_LIB.a"; - done +#-------------------- +# common defines +FF_ARCH=$1 +if [ -z "$FF_ARCH" ]; then + echo "You must specific an architecture 'armv7, armv7s, arm64, i386, x86_64, ...'.\n" + exit 1 +fi + + +FF_BUILD_ROOT=`pwd` +FF_TAGET_OS="darwin" - cp -R $UNI_BUILD_ROOT/build/thin/speex/armv7/include $LIBS -} -#---------- -if [ "$FF_TARGET" = "armv7" -o "$FF_TARGET" = "armv7s" -o "$FF_TARGET" = "arm64" ]; then - echo_archs - sh tools/do-compile-speex.sh $FF_TARGET -elif [ "$FF_TARGET" = "i386" -o "$FF_TARGET" = "x86_64" ]; then - echo_archs - sh tools/do-compile-speex.sh $FF_TARGET -elif [ "$FF_TARGET" = "lipo" ]; then - echo_archs - do_lipo_all -elif [ "$FF_TARGET" = "all" ]; then - echo_archs - for ARCH in $FF_ALL_ARCHS - do - sh tools/do-compile-speex.sh $ARCH - done - - do_lipo_all -elif [ "$FF_TARGET" = "check" ]; then - echo_archs -elif [ "$FF_TARGET" = "clean" ]; then - echo_archs - for ARCH in $FF_ALL_ARCHS - do - cd speex-$ARCH && git clean -xdf && cd - - done +# speex build params +export COMMON_FF_CFG_FLAGS= + +SPEEX_CFG_FLAGS= +SPEEX_EXTRA_CFLAGS= +SPEEX_CFG_CPU= + +# i386, x86_64 +SPEEX_CFG_FLAGS_SIMULATOR="--host=arm" + +# armv7, armv7s, arm64 +SPEEX_CFG_FLAGS_ARM= +SPEEX_CFG_FLAGS_ARM="--host=arm-apple-darwin" + +echo "build_root: $FF_BUILD_ROOT" + +#-------------------- +echo "====================" +echo "[*] config arch $FF_ARCH" +echo "====================" + +FF_BUILD_NAME="unknown" +FF_XCRUN_PLATFORM="iPhoneOS" +FF_XCRUN_OSVERSION= +FF_GASPP_EXPORT= + +if [ "$FF_ARCH" = "i386" ]; then + FF_BUILD_NAME="speex/i386" + FF_BUILD_NAME_OGG=ogg/i386 + FF_XCRUN_PLATFORM="iPhoneSimulator" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" +elif [ "$FF_ARCH" = "x86_64" ]; then + FF_BUILD_NAME="speex/x86_64" + FF_BUILD_NAME_OGG=ogg/x86_64 + FF_XCRUN_PLATFORM="iPhoneSimulator" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" +elif [ "$FF_ARCH" = "armv7" ]; then + FF_BUILD_NAME="speex/armv7" + FF_BUILD_NAME_OGG=ogg/armv7 + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" +# OPENSSL_CFG_CPU="--cpu=cortex-a8" +elif [ "$FF_ARCH" = "armv7s" ]; then + FF_BUILD_NAME="speex/armv7s" + FF_BUILD_NAME_OGG=ogg/armv7s + SPEEX_CFG_CPU="--cpu=swift" + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" +elif [ "$FF_ARCH" = "arm64" ]; then + FF_BUILD_NAME="speex/arm64" + FF_BUILD_NAME_OGG=ogg/arm64 + FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0" + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" + FF_GASPP_EXPORT="GASPP_FIX_XCODE5=1" else - echo "Usage:" - echo " compile-speex.sh armv7|arm64|i386|x86_64" - echo " compile-speex.sh armv7s (obselete)" - echo " compile-speex.sh lipo" - echo " compile-speex.sh all" - echo " compile-speex.sh clean" - echo " compile-speex.sh check" + echo "unknown architecture $FF_ARCH"; exit 1 fi + +echo "build_name: $FF_BUILD_NAME" +echo "platform: $FF_XCRUN_PLATFORM" +echo "osversion: $FF_XCRUN_OSVERSION" + +#-------------------- +echo "====================" +echo "[*] make ios toolchain $FF_BUILD_NAME" +echo "====================" + + +FF_BUILD_SOURCE="$FF_BUILD_ROOT/build/src/$FF_BUILD_NAME" +FF_BUILD_PREFIX="$FF_BUILD_ROOT/build/thin/$FF_BUILD_NAME" + +mkdir -p $FF_BUILD_PREFIX + + +FF_XCRUN_SDK=`echo $FF_XCRUN_PLATFORM | tr '[:upper:]' '[:lower:]'` +FF_XCRUN_SDK_PLATFORM_PATH=`xcrun -sdk $FF_XCRUN_SDK --show-sdk-platform-path` +FF_XCRUN_SDK_PATH=`xcrun -sdk $FF_XCRUN_SDK --show-sdk-path` +FF_XCRUN_CC="xcrun -sdk $FF_XCRUN_SDK clang" + +export CROSS_TOP="$FF_XCRUN_SDK_PLATFORM_PATH/Developer" +export CROSS_SDK=`echo ${FF_XCRUN_SDK_PATH/#$CROSS_TOP\/SDKs\//}` +export BUILD_TOOL="$FF_XCRUN_DEVELOPER" +export CC="$FF_XCRUN_CC -arch $FF_ARCH $FF_XCRUN_OSVERSION" + +echo "build_source: $FF_BUILD_SOURCE" +echo "build_prefix: $FF_BUILD_PREFIX" +echo "CROSS_TOP: $CROSS_TOP" +echo "CROSS_SDK: $CROSS_SDK" +echo "BUILD_TOOL: $BUILD_TOOL" +echo "CC: $CC" + +#-------------------- +echo "\n--------------------" +echo "[*] check OGG" +echo "----------------------" + +CXXFLAGS="$CFLAGS" +LDFLAGS="$CFLAGS" +OGG=$FF_BUILD_ROOT/build/thin/$FF_BUILD_NAME_OGG + +if [ -f "${OGG}/lib/libogg.a" ]; then + SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS --with-ogg=${OGG}" +fi + +#-------------------- +echo "\n--------------------" +echo "[*] configurate speex" +echo "--------------------" + +SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS --prefix=$FF_BUILD_PREFIX" + +# xcode configuration +export DEBUG_INFORMATION_FORMAT=dwarf-with-dsym + +function configure() { + cd $FF_BUILD_SOURCE + if [ -f "./Makefile" ]; then + echo 'reuse configure' + elif [ -f "./configure" ]; then + echo 'already run autogen.sh' + echo "config: $SPEEX_CFG_FLAGS" + ./Configure \ + $SPEEX_CFG_FLAGS + configure + else + echo 'should run autogen.sh first' + ./autogen.sh + configure + fi +} + +configure + +#-------------------- +echo "\n--------------------" +echo "[*] compile speex" +echo "--------------------" +set +e +make +make install diff --git a/libs/build.sh b/libs/build.sh index 753b4c7..215b67e 100755 --- a/libs/build.sh +++ b/libs/build.sh @@ -41,7 +41,11 @@ function buildTargets() { do if [ $TARGET = "ffmpeg" ]; then buildFFmpeg + elif [ $TARGET = "ogg" ]; then + brew uninstall --ignore-dependencies libogg + buildLib $TARGET else + brew uninstall speex buildLib $TARGET fi done @@ -49,8 +53,6 @@ function buildTargets() { cd `pwd`/"libs" -sh config/module.sh - if [ ! $TARGETS ] then buildTargets "ogg speex ffmpeg" diff --git a/libs/tools/do-compile-ogg.sh b/libs/tools/do-compile-ogg.sh index d6bd7c0..3fc9774 100755 --- a/libs/tools/do-compile-ogg.sh +++ b/libs/tools/do-compile-ogg.sh @@ -160,9 +160,7 @@ export DEBUG_INFORMATION_FORMAT=dwarf-with-dsym function configure() { cd $FF_BUILD_SOURCE - if [ -f "./Makefile" ]; then - echo 'reuse configure' - elif [ -f "./configure" ]; then + if [ -f "./configure" ]; then echo 'already run autogen.sh' echo "config: $OGG_CFG_FLAGS" ./Configure \ diff --git a/libs/tools/do-compile-speex.sh b/libs/tools/do-compile-speex.sh index 6ad6090..92e850d 100755 --- a/libs/tools/do-compile-speex.sh +++ b/libs/tools/do-compile-speex.sh @@ -179,9 +179,7 @@ export DEBUG_INFORMATION_FORMAT=dwarf-with-dsym function configure() { cd $FF_BUILD_SOURCE - if [ -f "./Makefile" ]; then - echo 'reuse configure' - elif [ -f "./configure" ]; then + if [ -f "./configure" ]; then echo 'already run autogen.sh' echo "config: $SPEEX_CFG_FLAGS" ./Configure \ From cd5e99301cba4fc2cf3fc32fbf6c5332409150e6 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 14 Dec 2018 18:27:27 +0900 Subject: [PATCH 030/215] Update project settings to build carthage. --- DLGPlayer.xcodeproj/project.pbxproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index bd6ec39..45d842a 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -409,8 +409,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = " -"; + shellScript = "libs/build.sh\n"; }; /* End PBXShellScriptBuildPhase section */ From 2cc2672fe39519507eba5ae3a058206c890e4d15 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 14 Dec 2018 19:30:15 +0900 Subject: [PATCH 031/215] Build script: bug fix. --- libs/tools/do-compile-ogg.sh | 5 +++-- libs/tools/do-compile-speex.sh | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libs/tools/do-compile-ogg.sh b/libs/tools/do-compile-ogg.sh index 3fc9774..6313d35 100755 --- a/libs/tools/do-compile-ogg.sh +++ b/libs/tools/do-compile-ogg.sh @@ -160,12 +160,13 @@ export DEBUG_INFORMATION_FORMAT=dwarf-with-dsym function configure() { cd $FF_BUILD_SOURCE - if [ -f "./configure" ]; then + if [ -f "./Makefile" ]; then + echo 'reuse configure' + elif [ -f "./configure" ]; then echo 'already run autogen.sh' echo "config: $OGG_CFG_FLAGS" ./Configure \ $OGG_CFG_FLAGS - configure else echo 'should run autogen.sh first' echo "config: $OGG_CFG_FLAGS" diff --git a/libs/tools/do-compile-speex.sh b/libs/tools/do-compile-speex.sh index 92e850d..4fd3052 100755 --- a/libs/tools/do-compile-speex.sh +++ b/libs/tools/do-compile-speex.sh @@ -179,12 +179,13 @@ export DEBUG_INFORMATION_FORMAT=dwarf-with-dsym function configure() { cd $FF_BUILD_SOURCE - if [ -f "./configure" ]; then + if [ -f "./Makefile" ]; then + echo 'reuse configure' + elif [ -f "./configure" ]; then echo 'already run autogen.sh' echo "config: $SPEEX_CFG_FLAGS" ./Configure \ $SPEEX_CFG_FLAGS - configure else echo 'should run autogen.sh first' ./autogen.sh From 72a0cbbe737373c14164ac992f29e6e152a15ac2 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sat, 15 Dec 2018 01:07:28 +0900 Subject: [PATCH 032/215] Update project settings and script to build carthage. --- DLGPlayer.xcodeproj/project.pbxproj | 2 +- libs/build-ffmpeg.sh | 15 +++++++-------- libs/build.sh | 5 ----- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index 45d842a..2b06c2a 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -409,7 +409,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "libs/build.sh\n"; + shellScript = "cd libs\nsh build.sh\n"; }; /* End PBXShellScriptBuildPhase section */ diff --git a/libs/build-ffmpeg.sh b/libs/build-ffmpeg.sh index 2099942..bfa3b74 100755 --- a/libs/build-ffmpeg.sh +++ b/libs/build-ffmpeg.sh @@ -13,18 +13,11 @@ FFMPEG=$THIN/ffmpeg CONFIGURE_FLAGS="--enable-cross-compile --enable-static --disable-shared --disable-debug --disable-programs \ --disable-doc --enable-pic --enable-neon --enable-optimizations --enable-small" - ARCHS="armv7 armv7s arm64 i386 x86_64" - COMPILE="y" LIPO="y" - DEPLOYMENT_TARGET="8.0" -if [ -f "${FAT}/lib/libspeex.a" ]; then - brew install speex -fi - if [ "$*" ] then if [ "$*" = "lipo" ] @@ -49,12 +42,18 @@ then if [ ! `which brew` ] then echo 'Homebrew not found. Trying to install...' - ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" \ + ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" \ || exit 1 fi echo 'Trying to install Yasm...' brew install yasm || exit 1 fi + + HAS_SPEEX=shell pkg-config --exists speex + if [ ! HAS_SPEEX ]; then + brew install speex || exit 1 + fi + if [ ! `which gas-preprocessor.pl` ] then echo 'gas-preprocessor.pl not found. Trying to install...' diff --git a/libs/build.sh b/libs/build.sh index 215b67e..d37b2f2 100755 --- a/libs/build.sh +++ b/libs/build.sh @@ -4,7 +4,6 @@ TARGETS=$1 LIBS=`pwd`"/build/universal" function buildLib() { - echo "include: ${LIBS}/include/$1, lib: ${LIBS}/lib/lib$1.a" if [ -d "${LIBS}/include/$1" ] && [ -f "${LIBS}/lib/lib$1.a" ] then echo "Already compiled $1." @@ -42,17 +41,13 @@ function buildTargets() { if [ $TARGET = "ffmpeg" ]; then buildFFmpeg elif [ $TARGET = "ogg" ]; then - brew uninstall --ignore-dependencies libogg buildLib $TARGET else - brew uninstall speex buildLib $TARGET fi done } -cd `pwd`/"libs" - if [ ! $TARGETS ] then buildTargets "ogg speex ffmpeg" From 740bd2996c00900c938c6f7c0fd41c85a84c1cea Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sat, 15 Dec 2018 01:57:20 +0900 Subject: [PATCH 033/215] Recovery build-speex.sh --- libs/build-speex.sh | 250 +++++++++++++------------------------------- 1 file changed, 75 insertions(+), 175 deletions(-) diff --git a/libs/build-speex.sh b/libs/build-speex.sh index c65c3e0..49e5daa 100755 --- a/libs/build-speex.sh +++ b/libs/build-speex.sh @@ -15,191 +15,91 @@ # limitations under the License. # -# This script is based on projects below -# https://github.com/cxjwin/speex_libs/blob/master/speex-1.2rc2/build_speex_ios.sh +#---------- +# modify for your build tool -#-------------------- -echo "====================" -echo "[*] check host" -echo "====================" -set -e - - -FF_XCRUN_DEVELOPER=`xcode-select -print-path` -if [ ! -d "$FF_XCRUN_DEVELOPER" ]; then - echo "xcode path is not set correctly $FF_XCRUN_DEVELOPER does not exist (most likely because of xcode > 4.3)" - echo "run" - echo "sudo xcode-select -switch " - echo "for default installation:" - echo "sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer" - exit 1 -fi - -case $FF_XCRUN_DEVELOPER in - *\ * ) - echo "Your Xcode path contains whitespaces, which is not supported." - exit 1 - ;; -esac +FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386" +FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64" +FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64" +FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS7_SDK -#-------------------- -# include - - -#-------------------- -# common defines -FF_ARCH=$1 -if [ -z "$FF_ARCH" ]; then - echo "You must specific an architecture 'armv7, armv7s, arm64, i386, x86_64, ...'.\n" - exit 1 -fi - - -FF_BUILD_ROOT=`pwd` -FF_TAGET_OS="darwin" - - -# speex build params -export COMMON_FF_CFG_FLAGS= +#---------- +UNI_BUILD_ROOT=`pwd` +LIBS="$UNI_BUILD_ROOT/build/universal" +UNI_TMP="$UNI_BUILD_ROOT/tmp" +UNI_TMP_LLVM_VER_FILE="$UNI_TMP/llvm.ver.txt" +FF_TARGET=$1 +set -e -SPEEX_CFG_FLAGS= -SPEEX_EXTRA_CFLAGS= -SPEEX_CFG_CPU= +#---------- +FF_LIBS="libspeex" +OGG_LIBS="libogg" -# i386, x86_64 -SPEEX_CFG_FLAGS_SIMULATOR="--host=arm" +#---------- +echo_archs() { + echo "====================" + echo "[*] check xcode version" + echo "====================" + echo "FF_ALL_ARCHS = $FF_ALL_ARCHS" +} -# armv7, armv7s, arm64 -SPEEX_CFG_FLAGS_ARM= -SPEEX_CFG_FLAGS_ARM="--host=arm-apple-darwin" +do_lipo () { + LIB_FILE=$1 + LIPO_FLAGS= + for ARCH in $FF_ALL_ARCHS + do + LIPO_FLAGS="$LIPO_FLAGS $UNI_BUILD_ROOT/build/thin/speex/$ARCH/lib/$LIB_FILE" + done -echo "build_root: $FF_BUILD_ROOT" + xcrun lipo -create $LIPO_FLAGS -output $LIBS/lib/$LIB_FILE + xcrun lipo -info $LIBS/lib/$LIB_FILE +} -#-------------------- -echo "====================" -echo "[*] config arch $FF_ARCH" -echo "====================" +do_lipo_all () { + mkdir -p $LIBS/lib + echo "lipo archs: $FF_ALL_ARCHS" + for FF_LIB in $FF_LIBS + do + do_lipo "$FF_LIB.a"; + done -FF_BUILD_NAME="unknown" -FF_XCRUN_PLATFORM="iPhoneOS" -FF_XCRUN_OSVERSION= -FF_GASPP_EXPORT= + cp -R $UNI_BUILD_ROOT/build/thin/speex/armv7/include $LIBS +} -if [ "$FF_ARCH" = "i386" ]; then - FF_BUILD_NAME="speex/i386" - FF_BUILD_NAME_OGG=ogg/i386 - FF_XCRUN_PLATFORM="iPhoneSimulator" - FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0" - SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" -elif [ "$FF_ARCH" = "x86_64" ]; then - FF_BUILD_NAME="speex/x86_64" - FF_BUILD_NAME_OGG=ogg/x86_64 - FF_XCRUN_PLATFORM="iPhoneSimulator" - FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0" - SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" -elif [ "$FF_ARCH" = "armv7" ]; then - FF_BUILD_NAME="speex/armv7" - FF_BUILD_NAME_OGG=ogg/armv7 - FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" - SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" -# OPENSSL_CFG_CPU="--cpu=cortex-a8" -elif [ "$FF_ARCH" = "armv7s" ]; then - FF_BUILD_NAME="speex/armv7s" - FF_BUILD_NAME_OGG=ogg/armv7s - SPEEX_CFG_CPU="--cpu=swift" - FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" - SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" -elif [ "$FF_ARCH" = "arm64" ]; then - FF_BUILD_NAME="speex/arm64" - FF_BUILD_NAME_OGG=ogg/arm64 - FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0" - SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" - FF_GASPP_EXPORT="GASPP_FIX_XCODE5=1" +#---------- +if [ "$FF_TARGET" = "armv7" -o "$FF_TARGET" = "armv7s" -o "$FF_TARGET" = "arm64" ]; then + echo_archs + sh tools/do-compile-speex.sh $FF_TARGET +elif [ "$FF_TARGET" = "i386" -o "$FF_TARGET" = "x86_64" ]; then + echo_archs + sh tools/do-compile-speex.sh $FF_TARGET +elif [ "$FF_TARGET" = "lipo" ]; then + echo_archs + do_lipo_all +elif [ "$FF_TARGET" = "all" ]; then + echo_archs + for ARCH in $FF_ALL_ARCHS + do + sh tools/do-compile-speex.sh $ARCH + done + + do_lipo_all +elif [ "$FF_TARGET" = "check" ]; then + echo_archs +elif [ "$FF_TARGET" = "clean" ]; then + echo_archs + for ARCH in $FF_ALL_ARCHS + do + cd speex-$ARCH && git clean -xdf && cd - + done else - echo "unknown architecture $FF_ARCH"; + echo "Usage:" + echo " compile-speex.sh armv7|arm64|i386|x86_64" + echo " compile-speex.sh armv7s (obselete)" + echo " compile-speex.sh lipo" + echo " compile-speex.sh all" + echo " compile-speex.sh clean" + echo " compile-speex.sh check" exit 1 fi - -echo "build_name: $FF_BUILD_NAME" -echo "platform: $FF_XCRUN_PLATFORM" -echo "osversion: $FF_XCRUN_OSVERSION" - -#-------------------- -echo "====================" -echo "[*] make ios toolchain $FF_BUILD_NAME" -echo "====================" - - -FF_BUILD_SOURCE="$FF_BUILD_ROOT/build/src/$FF_BUILD_NAME" -FF_BUILD_PREFIX="$FF_BUILD_ROOT/build/thin/$FF_BUILD_NAME" - -mkdir -p $FF_BUILD_PREFIX - - -FF_XCRUN_SDK=`echo $FF_XCRUN_PLATFORM | tr '[:upper:]' '[:lower:]'` -FF_XCRUN_SDK_PLATFORM_PATH=`xcrun -sdk $FF_XCRUN_SDK --show-sdk-platform-path` -FF_XCRUN_SDK_PATH=`xcrun -sdk $FF_XCRUN_SDK --show-sdk-path` -FF_XCRUN_CC="xcrun -sdk $FF_XCRUN_SDK clang" - -export CROSS_TOP="$FF_XCRUN_SDK_PLATFORM_PATH/Developer" -export CROSS_SDK=`echo ${FF_XCRUN_SDK_PATH/#$CROSS_TOP\/SDKs\//}` -export BUILD_TOOL="$FF_XCRUN_DEVELOPER" -export CC="$FF_XCRUN_CC -arch $FF_ARCH $FF_XCRUN_OSVERSION" - -echo "build_source: $FF_BUILD_SOURCE" -echo "build_prefix: $FF_BUILD_PREFIX" -echo "CROSS_TOP: $CROSS_TOP" -echo "CROSS_SDK: $CROSS_SDK" -echo "BUILD_TOOL: $BUILD_TOOL" -echo "CC: $CC" - -#-------------------- -echo "\n--------------------" -echo "[*] check OGG" -echo "----------------------" - -CXXFLAGS="$CFLAGS" -LDFLAGS="$CFLAGS" -OGG=$FF_BUILD_ROOT/build/thin/$FF_BUILD_NAME_OGG - -if [ -f "${OGG}/lib/libogg.a" ]; then - SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS --with-ogg=${OGG}" -fi - -#-------------------- -echo "\n--------------------" -echo "[*] configurate speex" -echo "--------------------" - -SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS --prefix=$FF_BUILD_PREFIX" - -# xcode configuration -export DEBUG_INFORMATION_FORMAT=dwarf-with-dsym - -function configure() { - cd $FF_BUILD_SOURCE - if [ -f "./Makefile" ]; then - echo 'reuse configure' - elif [ -f "./configure" ]; then - echo 'already run autogen.sh' - echo "config: $SPEEX_CFG_FLAGS" - ./Configure \ - $SPEEX_CFG_FLAGS - configure - else - echo 'should run autogen.sh first' - ./autogen.sh - configure - fi -} - -configure - -#-------------------- -echo "\n--------------------" -echo "[*] compile speex" -echo "--------------------" -set +e -make -make install From da4997e58d8d6ede46b9ee4f2d0494b44ac499c3 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sat, 15 Dec 2018 14:32:21 +0900 Subject: [PATCH 034/215] Build script: bug fix. --- libs/build-ogg.sh | 2 +- libs/build-speex.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/build-ogg.sh b/libs/build-ogg.sh index 2b270dd..416d54a 100755 --- a/libs/build-ogg.sh +++ b/libs/build-ogg.sh @@ -90,7 +90,7 @@ elif [ "$FF_TARGET" = "clean" ]; then echo_archs for ARCH in $FF_ALL_ARCHS do - cd ogg-$ARCH && git clean -xdf && cd - + cd ogg/$ARCH && git clean -xdf && cd - done else echo "Usage:" diff --git a/libs/build-speex.sh b/libs/build-speex.sh index 49e5daa..2ac5bfc 100755 --- a/libs/build-speex.sh +++ b/libs/build-speex.sh @@ -91,7 +91,7 @@ elif [ "$FF_TARGET" = "clean" ]; then echo_archs for ARCH in $FF_ALL_ARCHS do - cd speex-$ARCH && git clean -xdf && cd - + cd speex/$ARCH && git clean -xdf && cd - done else echo "Usage:" From 82955270882886c71eba514bd9066151e312c0b0 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sat, 15 Dec 2018 20:26:55 +0900 Subject: [PATCH 035/215] New feature snapshot: Make snapshot image from CAEAGLLayer. Add properties: isMute in DLGSimplePlayerViewController. Rename properties: autoplay to isAutoPlay, repeat to isRepeat in DLGSimplePlayerViewController. --- DLGPlayer.xcodeproj/project.pbxproj | 2 +- DLGPlayer/DLGPlayer.h | 1 + DLGPlayer/DLGPlayer.m | 4 +++ DLGPlayer/DLGSimplePlayerViewController.h | 5 +-- DLGPlayer/DLGSimplePlayerViewController.m | 12 ++++++-- DLGPlayer/view/DLGPlayerView.h | 1 + DLGPlayer/view/DLGPlayerView.m | 37 +++++++++++++++++++++++ DLGPlayerDemo/Base.lproj/Main.storyboard | 12 +++++++- DLGPlayerDemo/ViewController.swift | 14 ++++++--- 9 files changed, 78 insertions(+), 10 deletions(-) diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index 2b06c2a..0957942 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -230,8 +230,8 @@ 23DC293221B810B50012243A /* view */ = { isa = PBXGroup; children = ( - 23DC293321B810B50012243A /* DLGPlayerView.m */, 23DC293421B810B50012243A /* DLGPlayerView.h */, + 23DC293321B810B50012243A /* DLGPlayerView.m */, ); path = view; sourceTree = ""; diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index eb348fd..e4c3f02 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -41,5 +41,6 @@ typedef void (^onPauseComplete)(void); - (void)close; - (void)play; - (void)pause; +- (UIImage *)snapshot; @end diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 6b3c7a9..b6d1f32 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -230,6 +230,10 @@ - (void)pause { } } +- (UIImage *)snapshot { + return [_view snapshot]; +} + - (void)startFrameReaderThread { if (self.frameReaderThread == nil) { self.frameReaderThread = [[NSThread alloc] initWithTarget:self selector:@selector(runFrameReader) object:nil]; diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index 16ffc05..9caac5d 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -22,8 +22,9 @@ NS_ASSUME_NONNULL_BEGIN @interface DLGSimplePlayerViewController : UIViewController @property (nonatomic, copy) NSString *url; -@property (nonatomic) BOOL autoplay; -@property (nonatomic) BOOL repeat; +@property (nonatomic) BOOL isAutoplay; +@property (nonatomic) BOOL isMute; +@property (nonatomic) BOOL isRepeat; @property (nonatomic) BOOL preventFromScreenLock; @property (nonatomic) BOOL restorePlayAfterAppEnterForeground; @property (nonatomic, readonly) DLGPlayerStatus status; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 1b8194b..57de157 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -70,6 +70,14 @@ - (void)setStatus:(DLGPlayerStatus)status { [_delegate viewController:self didChangeStatus:status]; } } + +- (BOOL)isMute { + return _player.audio.mute; +} + +- (void)setIsMute:(BOOL)isMute { + _player.audio.mute = isMute; +} #pragma mark - Init - (void)initAll { @@ -195,7 +203,7 @@ - (void)notifyAppWillEnterForeground:(NSNotification *)notif { - (void)notifyPlayerEOF:(NSNotification *)notif { self.status = DLGPlayerStatusEOF; - if (_repeat) [self replay]; + if (_isRepeat) [self replay]; else [self close]; } @@ -209,7 +217,7 @@ - (void)notifyPlayerOpened:(NSNotification *)notif { self.status = DLGPlayerStatusOpened; if (![self doNextOperation]) { - if (_autoplay) [self play]; + if (_isAutoplay) [self play]; } } diff --git a/DLGPlayer/view/DLGPlayerView.h b/DLGPlayer/view/DLGPlayerView.h index 6b1efc5..fccf851 100644 --- a/DLGPlayer/view/DLGPlayerView.h +++ b/DLGPlayer/view/DLGPlayerView.h @@ -19,5 +19,6 @@ - (void)render:(DLGPlayerVideoFrame *)frame; - (void)clear; +- (UIImage *)snapshot; @end diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index 2136eaf..cd98a4f 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -359,6 +359,43 @@ - (void)render:(DLGPlayerVideoFrame *)frame { if (_keepLastFrame) self.lastFrame = frame; } +- (UIImage *)snapshot { + NSInteger width = _backingWidth, height = _backingHeight; + NSInteger dataLength = width * height * 4; + GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte)); + + glPixelStorei(GL_PACK_ALIGNMENT, 4); + glReadPixels(0, 0, _backingWidth, _backingHeight, GL_RGBA, GL_UNSIGNED_BYTE, data); + + CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL); + CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); + CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast, + ref, NULL, true, kCGRenderingIntentDefault); + + NSInteger widthInPoints, heightInPoints; + CGFloat scale = _eaglLayer.contentsScale; + widthInPoints = width / scale; + heightInPoints = height / scale; + + UIGraphicsBeginImageContextWithOptions(CGSizeMake(widthInPoints, heightInPoints), NO, scale); + + CGContextRef cgcontext = UIGraphicsGetCurrentContext(); + + CGContextSetBlendMode(cgcontext, kCGBlendModeCopy); + CGContextDrawImage(cgcontext, CGRectMake(0.0, 0.0, widthInPoints, heightInPoints), iref); + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + + UIGraphicsEndImageContext(); + + free(data); + CFRelease(ref); + CFRelease(colorspace); + CGImageRelease(iref); + + return image; +} + #pragma mark - Utils + (GLuint)loadShader:(GLenum)type withString:(NSString *)shaderString { // 1. Create shader diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index ebfc798..4462551 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -44,12 +44,21 @@ - + + + + + @@ -60,6 +69,7 @@ + diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index a91217f..8ad497a 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -14,8 +14,7 @@ class ViewController: UIViewController { private var playerViewController: DLGSimplePlayerViewController! { didSet { playerViewController.delegate = self - playerViewController.autoplay = true - playerViewController.repeat = true + playerViewController.isAutoplay = true playerViewController.preventFromScreenLock = true playerViewController.restorePlayAfterAppEnterForeground = true } @@ -49,9 +48,16 @@ class ViewController: UIViewController { print("player.position", playerViewController.player.position) } - @IBAction private func clicked(_ sender: UIButton) { + @IBAction private func captureButtonClicked() { + playerViewController.player.snapshot() + .map { UIImageView(image: $0) } + .map { [weak self] in + self?.view.addSubview($0) + } + } + @IBAction private func muteButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected - playerViewController.player.audio.mute = sender.isSelected + playerViewController.isMute = sender.isSelected } @IBAction private func valueChanged(_ sender: UISlider) { playerViewController.player.brightness = sender.value From 2e581a1692a6df0998a8aada29068679d154acbe Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sat, 15 Dec 2018 20:29:03 +0900 Subject: [PATCH 036/215] Write comment: Reference site for snapshot function. --- DLGPlayer/view/DLGPlayerView.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index cd98a4f..6a53ee2 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -359,6 +359,9 @@ - (void)render:(DLGPlayerVideoFrame *)frame { if (_keepLastFrame) self.lastFrame = frame; } +/* + * https://developer.apple.com/library/archive/qa/qa1704/_index.html + */ - (UIImage *)snapshot { NSInteger width = _backingWidth, height = _backingHeight; NSInteger dataLength = width * height * 4; From 3235914e83378eb780908343429df52210fc0d6a Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sun, 16 Dec 2018 00:51:23 +0900 Subject: [PATCH 037/215] Bug fix: Solved playing value is not valid when buffer state changed. --- DLGPlayer/DLGPlayer.m | 1 + 1 file changed, 1 insertion(+) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index b6d1f32..9c4ae0b 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -384,6 +384,7 @@ - (void)render { [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationBufferStateChanged object:self userInfo:userInfo]; } else if (!noframes && self.notifiedBufferStart && self.bufferedDuration >= self.minBufferDuration) { self.notifiedBufferStart = NO; + self.playing = YES; NSDictionary *userInfo = @{ DLGPlayerNotificationBufferStateKey : @(self.notifiedBufferStart) }; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationBufferStateChanged object:self userInfo:userInfo]; } From 32e07b8724fc1467a1806908bfef5595b23ea02d Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sun, 16 Dec 2018 01:01:41 +0900 Subject: [PATCH 038/215] Revert "Bug fix: Solved playing value is not valid when buffer state changed." This reverts commit 3235914e83378eb780908343429df52210fc0d6a. --- DLGPlayer/DLGPlayer.m | 1 - 1 file changed, 1 deletion(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 9c4ae0b..b6d1f32 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -384,7 +384,6 @@ - (void)render { [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationBufferStateChanged object:self userInfo:userInfo]; } else if (!noframes && self.notifiedBufferStart && self.bufferedDuration >= self.minBufferDuration) { self.notifiedBufferStart = NO; - self.playing = YES; NSDictionary *userInfo = @{ DLGPlayerNotificationBufferStateKey : @(self.notifiedBufferStart) }; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationBufferStateChanged object:self userInfo:userInfo]; } From bd480b093105b6dd6041cb37f23ca107c22633ac Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sun, 16 Dec 2018 01:02:44 +0900 Subject: [PATCH 039/215] Bug fix: Solved playing value is not valid when state changed. --- DLGPlayer/DLGSimplePlayerViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 57de157..6a8f53e 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -121,9 +121,9 @@ - (void)play { _status != DLGPlayerStatusEOF) { return; } - self.status = DLGPlayerStatusPlaying; [UIApplication sharedApplication].idleTimerDisabled = _preventFromScreenLock; [_player play]; + self.status = DLGPlayerStatusPlaying; } - (void)replay { From 926cc565a58640f19efc7954e5177d9a109f145f Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sun, 16 Dec 2018 01:55:47 +0900 Subject: [PATCH 040/215] Added: function to reset status. --- DLGPlayer/DLGSimplePlayerViewController.h | 1 + DLGPlayer/DLGSimplePlayerViewController.m | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index 9caac5d..8bcb6b9 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -34,6 +34,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)close; - (void)play; - (void)pause; +- (void)reset; @end NS_ASSUME_NONNULL_END diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 6a8f53e..7b6b8de 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -141,6 +141,13 @@ - (void)pause { [UIApplication sharedApplication].idleTimerDisabled = NO; [_player pause]; } + +- (void)reset { + [self close]; + + _status = DLGPlayerStatusNone; + self.nextOperation = DLGPlayerOperationNone; +} - (BOOL)doNextOperation { if (self.nextOperation == DLGPlayerOperationNone) return NO; From cbbb42107915a4b6796bec78690d04f464e47d2e Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sun, 16 Dec 2018 02:09:12 +0900 Subject: [PATCH 041/215] Modified: function to reset status. --- DLGPlayer/DLGSimplePlayerViewController.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 7b6b8de..afe18d7 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -143,8 +143,6 @@ - (void)pause { } - (void)reset { - [self close]; - _status = DLGPlayerStatusNone; self.nextOperation = DLGPlayerOperationNone; } From 90cedd72ab31bfcc831fd648f48184be7521dacc Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 17 Dec 2018 14:03:53 +0900 Subject: [PATCH 042/215] Bug fix: mute property was invalid. --- DLGPlayer/DLGSimplePlayerViewController.m | 9 ++++----- DLGPlayerDemo/ViewController.swift | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index afe18d7..47f8902 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -27,7 +27,7 @@ @interface DLGSimplePlayerViewController () { @end @implementation DLGSimplePlayerViewController - + - (void)viewDidLoad { [super viewDidLoad]; @@ -71,11 +71,8 @@ - (void)setStatus:(DLGPlayerStatus)status { } } -- (BOOL)isMute { - return _player.audio.mute; -} - - (void)setIsMute:(BOOL)isMute { + _isMute = isMute; _player.audio.mute = isMute; } @@ -173,6 +170,8 @@ - (BOOL)doNextOperation { #pragma mark - UI - (void)initPlayer { _player = [[DLGPlayer alloc] init]; + _player.audio.mute = _isMute; + UIView *v = _player.playerView; v.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:v]; diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 8ad497a..6719eb6 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -15,6 +15,7 @@ class ViewController: UIViewController { didSet { playerViewController.delegate = self playerViewController.isAutoplay = true + playerViewController.isMute = true playerViewController.preventFromScreenLock = true playerViewController.restorePlayAfterAppEnterForeground = true } From 1a9b66659a53f0a5c0cf9a5703cf962c0e479d41 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 17 Dec 2018 17:50:29 +0900 Subject: [PATCH 043/215] Remove define NS_ASSUME_NONNULL_BEGIN --- DLGPlayer/DLGSimplePlayerViewController.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index 8bcb6b9..e975a8e 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -11,8 +11,6 @@ @class DLGPlayer; -NS_ASSUME_NONNULL_BEGIN - @class DLGSimplePlayerViewController; @protocol DLGSimplePlayerViewControllerDelegate @@ -36,5 +34,3 @@ NS_ASSUME_NONNULL_BEGIN - (void)pause; - (void)reset; @end - -NS_ASSUME_NONNULL_END From c10b2e05dcfc6edb8c3fc6df9077374ad19ae21f Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 17 Dec 2018 17:54:59 +0900 Subject: [PATCH 044/215] Added properties: hasUrl, isPlaying --- DLGPlayer/DLGSimplePlayerViewController.h | 5 +++-- DLGPlayer/DLGSimplePlayerViewController.m | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index e975a8e..b6f8072 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -10,7 +10,6 @@ #import "DLGPlayer.h" @class DLGPlayer; - @class DLGSimplePlayerViewController; @protocol DLGSimplePlayerViewControllerDelegate @@ -19,12 +18,14 @@ @end @interface DLGSimplePlayerViewController : UIViewController -@property (nonatomic, copy) NSString *url; +@property (nonatomic, readonly) BOOL hasUrl; @property (nonatomic) BOOL isAutoplay; @property (nonatomic) BOOL isMute; +@property (nonatomic, readonly) BOOL isPlaying; @property (nonatomic) BOOL isRepeat; @property (nonatomic) BOOL preventFromScreenLock; @property (nonatomic) BOOL restorePlayAfterAppEnterForeground; +@property (nullable, nonatomic, copy) NSString *url; @property (nonatomic, readonly) DLGPlayerStatus status; @property (nonatomic, readonly) DLGPlayer *player; @property (nonatomic, weak) id delegate; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 47f8902..073111f 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -62,6 +62,14 @@ - (void)registerNotification { - (void)unregisterNotification { [[NSNotificationCenter defaultCenter] removeObserver:self]; } + +- (BOOL)hasUrl { + return _url == nil; +} + +- (BOOL)isPlaying { + return _player.playing; +} - (void)setStatus:(DLGPlayerStatus)status { _status = status; From 6c9cead6537c10f871b09f46dafff4aa0cf6114d Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 17 Dec 2018 18:36:24 +0900 Subject: [PATCH 045/215] Added properties: minBufferDuration, maxBufferDuration. Change property type: nonnull to nullable optional. --- DLGPlayer/DLGSimplePlayerViewController.h | 6 ++++-- DLGPlayer/DLGSimplePlayerViewController.m | 12 ++++++++++++ DLGPlayerDemo/ViewController.swift | 10 ++++------ 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index b6f8072..fe2f99c 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -25,10 +25,12 @@ @property (nonatomic) BOOL isRepeat; @property (nonatomic) BOOL preventFromScreenLock; @property (nonatomic) BOOL restorePlayAfterAppEnterForeground; +@property (nonatomic) double minBufferDuration; +@property (nonatomic) double maxBufferDuration; @property (nullable, nonatomic, copy) NSString *url; @property (nonatomic, readonly) DLGPlayerStatus status; -@property (nonatomic, readonly) DLGPlayer *player; -@property (nonatomic, weak) id delegate; +@property (nullable, nonatomic, readonly) DLGPlayer *player; +@property (nullable, nonatomic, weak) id delegate; - (void)open; - (void)close; - (void)play; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 073111f..651ca40 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -83,6 +83,16 @@ - (void)setIsMute:(BOOL)isMute { _isMute = isMute; _player.audio.mute = isMute; } + +- (void)setMinBufferDuration:(double)minBufferDuration { + _minBufferDuration = minBufferDuration; + _player.minBufferDuration = minBufferDuration; +} + +- (void)setMaxBufferDuration:(double)maxBufferDuration { + _maxBufferDuration = maxBufferDuration; + _player.maxBufferDuration = maxBufferDuration; +} #pragma mark - Init - (void)initAll { @@ -178,6 +188,8 @@ - (BOOL)doNextOperation { #pragma mark - UI - (void)initPlayer { _player = [[DLGPlayer alloc] init]; + _player.minBufferDuration = _minBufferDuration; + _player.maxBufferDuration = _maxBufferDuration; _player.audio.mute = _isMute; UIView *v = _player.playerView; diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 6719eb6..6ce088b 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -25,7 +25,7 @@ class ViewController: UIViewController { super.viewDidLoad() playerViewController.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" - playerViewController.player.minBufferDuration = 1 + playerViewController.minBufferDuration = 1 playerViewController.open() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { @@ -46,11 +46,11 @@ class ViewController: UIViewController { } @objc private func timerCompletion() { - print("player.position", playerViewController.player.position) + print("player.position", playerViewController.player?.position ?? 0) } @IBAction private func captureButtonClicked() { - playerViewController.player.snapshot() + playerViewController.player?.snapshot() .map { UIImageView(image: $0) } .map { [weak self] in self?.view.addSubview($0) @@ -61,7 +61,7 @@ class ViewController: UIViewController { playerViewController.isMute = sender.isSelected } @IBAction private func valueChanged(_ sender: UISlider) { - playerViewController.player.brightness = sender.value + playerViewController.player?.brightness = sender.value } } @@ -77,8 +77,6 @@ extension ViewController: DLGSimplePlayerViewControllerDelegate { startTimer() case .closed: stopTimer() -// case .playing: -// print("player.audio.volume", playerViewController.player.audio.volume) default: () } } From f4f230eb03634c2ff2d56a2a05b2b1df865c964a Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 17 Dec 2018 18:53:51 +0900 Subject: [PATCH 046/215] Bug fix: property hasUrl in DLGSimplePlayerViewController --- DLGPlayer/DLGSimplePlayerViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 651ca40..9c41fdf 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -64,7 +64,7 @@ - (void)unregisterNotification { } - (BOOL)hasUrl { - return _url == nil; + return _url != nil && [_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet].length > 0; } - (BOOL)isPlaying { From 6e6ba2f5a30089d84859933018c385708fc7986b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 17 Dec 2018 20:07:34 +0900 Subject: [PATCH 047/215] Bug fix: Change to set properties according to life cycle of view controller. --- DLGPlayer/DLGSimplePlayerViewController.h | 2 +- DLGPlayer/DLGSimplePlayerViewController.m | 94 +++++++++++++++-------- DLGPlayerDemo/ViewController.swift | 6 +- 3 files changed, 66 insertions(+), 36 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index fe2f99c..4c934e1 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -29,7 +29,7 @@ @property (nonatomic) double maxBufferDuration; @property (nullable, nonatomic, copy) NSString *url; @property (nonatomic, readonly) DLGPlayerStatus status; -@property (nullable, nonatomic, readonly) DLGPlayer *player; +@property (nonnull, nonatomic, readonly) DLGPlayer *player; @property (nullable, nonatomic, weak) id delegate; - (void)open; - (void)close; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 9c41fdf..d979860 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -28,10 +28,36 @@ @interface DLGSimplePlayerViewController () { @implementation DLGSimplePlayerViewController +#pragma mark - Constructors +- (instancetype)init { + self = [super init]; + if (self) { + [self initAll]; + } + return self; +} + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + if (self) { + [self initAll]; + } + return self; +} + +- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + [self initAll]; + } + return self; +} + +#pragma mark - View controller life cycle - (void)viewDidLoad { [super viewDidLoad]; - [self initAll]; + [self addPlayerView]; } - (void)viewWillAppear:(BOOL)animated { @@ -45,24 +71,8 @@ - (void)viewWillDisappear:(BOOL)animated { [self unregisterNotification]; } - -- (void)registerNotification { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self selector:@selector(notifyAppDidEnterBackground:) - name:UIApplicationDidEnterBackgroundNotification object:nil]; - [nc addObserver:self selector:@selector(notifyAppWillEnterForeground:) - name:UIApplicationWillEnterForegroundNotification object:nil]; - [nc addObserver:self selector:@selector(notifyPlayerOpened:) name:DLGPlayerNotificationOpened object:_player]; - [nc addObserver:self selector:@selector(notifyPlayerClosed:) name:DLGPlayerNotificationClosed object:_player]; - [nc addObserver:self selector:@selector(notifyPlayerEOF:) name:DLGPlayerNotificationEOF object:_player]; - [nc addObserver:self selector:@selector(notifyPlayerBufferStateChanged:) name:DLGPlayerNotificationBufferStateChanged object:_player]; - [nc addObserver:self selector:@selector(notifyPlayerError:) name:DLGPlayerNotificationError object:_player]; -} - -- (void)unregisterNotification { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} +#pragma mark - getter/setter - (BOOL)hasUrl { return _url != nil && [_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet].length > 0; } @@ -79,25 +89,33 @@ - (void)setStatus:(DLGPlayerStatus)status { } } +- (BOOL)isMute { + return _player.audio.mute; +} + - (void)setIsMute:(BOOL)isMute { - _isMute = isMute; _player.audio.mute = isMute; } +- (double)minBufferDuration { + return _player.minBufferDuration; +} + - (void)setMinBufferDuration:(double)minBufferDuration { - _minBufferDuration = minBufferDuration; _player.minBufferDuration = minBufferDuration; } +- (double)maxBufferDuration { + return _player.maxBufferDuration; +} + - (void)setMaxBufferDuration:(double)maxBufferDuration { - _maxBufferDuration = maxBufferDuration; _player.maxBufferDuration = maxBufferDuration; } #pragma mark - Init - (void)initAll { - [self initPlayer]; - + _player = [[DLGPlayer alloc] init]; _status = DLGPlayerStatusNone; self.nextOperation = DLGPlayerOperationNone; } @@ -186,18 +204,13 @@ - (BOOL)doNextOperation { #pragma mark - UI -- (void)initPlayer { - _player = [[DLGPlayer alloc] init]; - _player.minBufferDuration = _minBufferDuration; - _player.maxBufferDuration = _maxBufferDuration; - _player.audio.mute = _isMute; +- (void)addPlayerView { + _player.playerView.translatesAutoresizingMaskIntoConstraints = NO; - UIView *v = _player.playerView; - v.translatesAutoresizingMaskIntoConstraints = NO; - [self.view addSubview:v]; + [self.view addSubview:_player.playerView]; // Add constraints - NSDictionary *views = NSDictionaryOfVariableBindings(v); + NSDictionary *views = NSDictionaryOfVariableBindings(_player.playerView); NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" options:0 metrics:nil @@ -211,6 +224,23 @@ - (void)initPlayer { } #pragma mark - Notifications +- (void)registerNotification { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self selector:@selector(notifyAppDidEnterBackground:) + name:UIApplicationDidEnterBackgroundNotification object:nil]; + [nc addObserver:self selector:@selector(notifyAppWillEnterForeground:) + name:UIApplicationWillEnterForegroundNotification object:nil]; + [nc addObserver:self selector:@selector(notifyPlayerOpened:) name:DLGPlayerNotificationOpened object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerClosed:) name:DLGPlayerNotificationClosed object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerEOF:) name:DLGPlayerNotificationEOF object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerBufferStateChanged:) name:DLGPlayerNotificationBufferStateChanged object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerError:) name:DLGPlayerNotificationError object:_player]; +} + +- (void)unregisterNotification { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + - (void)notifyAppDidEnterBackground:(NSNotification *)notif { if (_player.playing) { [self pause]; diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 6ce088b..e6234b4 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -46,11 +46,11 @@ class ViewController: UIViewController { } @objc private func timerCompletion() { - print("player.position", playerViewController.player?.position ?? 0) + print("player.position", playerViewController.player.position) } @IBAction private func captureButtonClicked() { - playerViewController.player?.snapshot() + playerViewController.player.snapshot() .map { UIImageView(image: $0) } .map { [weak self] in self?.view.addSubview($0) @@ -61,7 +61,7 @@ class ViewController: UIViewController { playerViewController.isMute = sender.isSelected } @IBAction private func valueChanged(_ sender: UISlider) { - playerViewController.player?.brightness = sender.value + playerViewController.player.brightness = sender.value } } From d7c16cbe16c0745ad75a747d2b81aa498a6ed7a3 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 17 Dec 2018 22:04:30 +0900 Subject: [PATCH 048/215] Rollback: Method to add view in superview and layout. --- DLGPlayer/DLGSimplePlayerViewController.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index d979860..34df9d0 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -205,12 +205,13 @@ - (BOOL)doNextOperation { #pragma mark - UI - (void)addPlayerView { - _player.playerView.translatesAutoresizingMaskIntoConstraints = NO; + UIView *v = _player.playerView; + v.translatesAutoresizingMaskIntoConstraints = NO; - [self.view addSubview:_player.playerView]; + [self.view addSubview:v]; // Add constraints - NSDictionary *views = NSDictionaryOfVariableBindings(_player.playerView); + NSDictionary *views = NSDictionaryOfVariableBindings(v); NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" options:0 metrics:nil From 9c8a8db6142061ff8bb6899103baefdc68c8d263 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 18 Dec 2018 11:11:14 +0900 Subject: [PATCH 049/215] Bug fix: Solved wrong status when player paused. --- DLGPlayer/DLGSimplePlayerViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 34df9d0..a4b8346 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -170,9 +170,9 @@ - (void)pause { _status != DLGPlayerStatusEOF) { return; } - self.status = DLGPlayerStatusPaused; [UIApplication sharedApplication].idleTimerDisabled = NO; [_player pause]; + self.status = DLGPlayerStatusPaused; } - (void)reset { From cffcf2acf3ccd4fb29bc7a83460fa53e8fc7d1c4 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 18 Dec 2018 21:40:11 +0900 Subject: [PATCH 050/215] Modified: Change member instance to global instance context variable is type of EAGLContext. It can play multiple players. --- DLGPlayer/DLGSimplePlayerViewController.m | 5 +- DLGPlayer/view/DLGPlayerView.m | 16 ++- DLGPlayerDemo/Base.lproj/Main.storyboard | 120 +++++++++++++++++++++- DLGPlayerDemo/ViewController.swift | 21 +++- 4 files changed, 147 insertions(+), 15 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index a4b8346..9454d4a 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -58,18 +58,19 @@ - (void)viewDidLoad { [super viewDidLoad]; [self addPlayerView]; + [self registerNotification]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - [self registerNotification]; +// [self registerNotification]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; - [self unregisterNotification]; +// [self unregisterNotification]; } #pragma mark - getter/setter diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index 6a53ee2..48548ec 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -17,7 +17,6 @@ @interface DLGPlayerView () { CAEAGLLayer *_eaglLayer; - EAGLContext *_context; GLuint _frameBuffer; GLuint _renderBuffer; GLuint _programHandle; @@ -49,6 +48,8 @@ @interface DLGPlayerView () { @end +static EAGLContext *_context; + @implementation DLGPlayerView - (id)init { @@ -110,9 +111,16 @@ - (BOOL)initVars { _eaglLayer.drawableProperties = @{ kEAGLDrawablePropertyRetainedBacking : @(NO), kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8 }; - _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; - if (_context == nil) return NO; - if (![EAGLContext setCurrentContext:_context]) return NO; + + if (!_context) { + if ((_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]) == nil) { + return NO; + } + + if (![EAGLContext setCurrentContext:_context]) { + return NO; + } + } [self initVertex]; [self initTexCord]; diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index 4462551..a4dfec4 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -10,6 +10,22 @@ + + + + + + + + + + + + + + + + @@ -28,19 +44,19 @@ - + + @@ -67,6 +90,8 @@ + + @@ -74,6 +99,7 @@ + @@ -93,5 +119,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index e6234b4..5057c72 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -18,16 +18,29 @@ class ViewController: UIViewController { playerViewController.isMute = true playerViewController.preventFromScreenLock = true playerViewController.restorePlayAfterAppEnterForeground = true + playerViewController.minBufferDuration = 1 } } override func viewDidLoad() { super.viewDidLoad() - playerViewController.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" - playerViewController.minBufferDuration = 1 + } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + if !playerViewController.hasUrl { + playerViewController.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" + } + playerViewController.open() } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + stopTimer() + playerViewController.close() + } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segue.destination { case let vc as DLGSimplePlayerViewController: @@ -46,7 +59,7 @@ class ViewController: UIViewController { } @objc private func timerCompletion() { - print("player.position", playerViewController.player.position) +// print("player.position", playerViewController.player.position) } @IBAction private func captureButtonClicked() { @@ -70,7 +83,7 @@ extension ViewController: DLGSimplePlayerViewControllerDelegate { print("didReceiveError", error) } func viewController(_ viewController: DLGSimplePlayerViewController, didChange status: DLGPlayerStatus) { - print("didChange", status.rawValue) + print("didChange", viewController.hash, status.rawValue) switch status { case .opened: From d09607256ee3e4775bec7fd6adbbbc67d276bb9c Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 18 Dec 2018 21:47:25 +0900 Subject: [PATCH 051/215] Added: class method to clear context variable and clear currentContext in EAGLContext. --- DLGPlayer/view/DLGPlayerView.h | 1 + DLGPlayer/view/DLGPlayerView.m | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/DLGPlayer/view/DLGPlayerView.h b/DLGPlayer/view/DLGPlayerView.h index fccf851..ed8dc85 100644 --- a/DLGPlayer/view/DLGPlayerView.h +++ b/DLGPlayer/view/DLGPlayerView.h @@ -17,6 +17,7 @@ @property (nonatomic) BOOL isYUV; @property (nonatomic) BOOL keepLastFrame; ++ (void)clearContext; - (void)render:(DLGPlayerVideoFrame *)frame; - (void)clear; - (UIImage *)snapshot; diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index 48548ec..0f044e9 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -78,6 +78,11 @@ - (void)dealloc { NSLog(@"DLGPlayerView dealloc"); } ++ (void)clearContext { + [EAGLContext setCurrentContext:nil]; + _context = nil; +} + + (Class)layerClass { return [CAEAGLLayer class]; } From 82cab2e210eff4c0809f29979bda5becace8b79c Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 18 Dec 2018 22:29:11 +0900 Subject: [PATCH 052/215] Remove temp comment. --- DLGPlayer/DLGSimplePlayerViewController.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 9454d4a..a4b8346 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -58,19 +58,18 @@ - (void)viewDidLoad { [super viewDidLoad]; [self addPlayerView]; - [self registerNotification]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; -// [self registerNotification]; + [self registerNotification]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; -// [self unregisterNotification]; + [self unregisterNotification]; } #pragma mark - getter/setter From 3d8d6e133b6718b2c87d4628de1ee05083378ae4 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 19 Dec 2018 12:18:26 +0900 Subject: [PATCH 053/215] Added: property renderQueue is dispatch serial queue to render view. Added: new status DLGPlayerStatusRenderBegan will set to start view rendering. --- DLGPlayer/DLGPlayer.h | 1 + DLGPlayer/DLGPlayer.m | 25 ++++++++++++-- DLGPlayer/DLGSimplePlayerViewController.m | 5 +++ DLGPlayer/common/DLGPlayerDef.h | 2 ++ DLGPlayerDemo/Base.lproj/Main.storyboard | 11 ++++++ DLGPlayerDemo/ViewController.swift | 42 +++++++++++++++++++---- 6 files changed, 78 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index e4c3f02..d3c52f3 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -34,6 +34,7 @@ typedef void (^onPauseComplete)(void); @property (nonatomic) BOOL playing; @property (nonatomic) BOOL buffering; @property (nonatomic) float brightness; +@property (nonatomic, strong) dispatch_queue_t renderQueue; @property (nonatomic, strong) NSDictionary *metadata; @property (nonatomic, readonly) DLGPlayerAudioManager *audio; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index b6d1f32..67d5f56 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -35,6 +35,7 @@ @interface DLGPlayer () @property (nonatomic) BOOL requestSeek; @property (nonatomic) double requestSeekPosition; @property (nonatomic) BOOL opening; +@property (nonatomic) BOOL renderBegan; @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; @@ -77,10 +78,12 @@ - (void)initVars { _playing = NO; _opened = NO; _requestSeek = NO; + _renderBegan = NO; _requestSeekPosition = 0; _frameReaderThread = nil; _aFramesLock = dispatch_semaphore_create(1); _vFramesLock = dispatch_semaphore_create(1); + _renderQueue = dispatch_queue_create("DLGPlayer.renderQueue", DISPATCH_QUEUE_SERIAL); } - (void)initView { @@ -105,6 +108,7 @@ - (void)clearVars { self.buffering = NO; self.playing = NO; self.opened = NO; + self.renderBegan = NO; self.bufferedDuration = 0; self.mediaPosition = 0; self.mediaSyncTime = 0; @@ -394,7 +398,7 @@ - (void)render { frame.brightness = _brightness; self.view.contentSize = CGSizeMake(frame.width, frame.height); [self.vframes removeObjectAtIndex:0]; - [self.view render:frame]; + [self renderView:frame]; } // Check whether render is neccessary @@ -419,7 +423,8 @@ - (void)render { dispatch_semaphore_signal(self.vFramesLock); } } - [self.view render:frame]; + + [self renderView:frame]; // Sync audio with video double syncTime = [self syncTime]; @@ -431,6 +436,22 @@ - (void)render { }); } +- (void)renderView:(DLGPlayerVideoFrame *)frame { + __weak typeof(self)weakSelf = self; + + dispatch_sync(_renderQueue, ^{ + [weakSelf.view render:frame]; + + if (!weakSelf.renderBegan && frame.width > 0 && frame.height > 0) { + weakSelf.renderBegan = YES; + + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationRenderBegan object:weakSelf]; + }); + } + }); +} + - (double)syncTime { const double now = [NSDate timeIntervalSinceReferenceDate]; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index a4b8346..c86449f 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -235,6 +235,7 @@ - (void)registerNotification { [nc addObserver:self selector:@selector(notifyPlayerClosed:) name:DLGPlayerNotificationClosed object:_player]; [nc addObserver:self selector:@selector(notifyPlayerEOF:) name:DLGPlayerNotificationEOF object:_player]; [nc addObserver:self selector:@selector(notifyPlayerBufferStateChanged:) name:DLGPlayerNotificationBufferStateChanged object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerRenderBegan:) name:DLGPlayerNotificationRenderBegan object:_player]; [nc addObserver:self selector:@selector(notifyPlayerError:) name:DLGPlayerNotificationError object:_player]; } @@ -285,6 +286,10 @@ - (void)notifyPlayerBufferStateChanged:(NSNotification *)notif { self.status = DLGPlayerStatusPlaying; } } + +- (void)notifyPlayerRenderBegan:(NSNotification *)notif { + self.status = DLGPlayerStatusRenderBegan; +} - (void)notifyPlayerError:(NSNotification *)notif { NSDictionary *userInfo = notif.userInfo; diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index 74e9626..f5237e4 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -43,6 +43,7 @@ #define DLGPlayerNotificationClosed @"DLGPlayerNotificationClosed" #define DLGPlayerNotificationEOF @"DLGPlayerNotificationEOF" #define DLGPlayerNotificationBufferStateChanged @"DLGPlayerNotificationBufferStateChanged" +#define DLGPlayerNotificationRenderBegan @"DLGPlayerNotificationRenderBegan" #define DLGPlayerNotificationError @"DLGPlayerNotificationError" #pragma mark - Notification Key @@ -57,6 +58,7 @@ typedef NS_ENUM(NSUInteger, DLGPlayerStatus) { DLGPlayerStatusOpened, DLGPlayerStatusPlaying, DLGPlayerStatusBuffering, + DLGPlayerStatusRenderBegan, DLGPlayerStatusPaused, DLGPlayerStatusEOF, DLGPlayerStatusClosing, diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index a4dfec4..522ed77 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -43,6 +43,10 @@ + + + + diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 67c53c5..717df55 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -69,6 +69,8 @@ - (void)initVars { - (void)dealloc { NSLog(@"DLGPlayerAudioManager dealloc"); + [self unregisterNotifications]; + if (_audioData != NULL) { free(_audioData); _audioData = NULL; @@ -260,7 +262,6 @@ - (BOOL)close:(NSArray **)errors { if (_opened && _audioUnit != NULL) { [self pause]; - [self unregisterNotifications]; OSStatus status = AudioUnitUninitialize(_audioUnit); diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index bcd81b1..baa642d 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -15,14 +15,16 @@ class ViewController: UIViewController { @IBOutlet private weak var playOrPauseButton: UIButton! private var timer: Timer? - private var playerViewController: DLGSimplePlayerViewController! { + private var playerViewController: DLGSimplePlayerViewController? { didSet { - playerViewController.delegate = self - playerViewController.isAutoplay = true -// playerViewController.isMute = true - playerViewController.preventFromScreenLock = true - playerViewController.restorePlayAfterAppEnterForeground = true - playerViewController.minBufferDuration = 1 + playerViewController.map { + $0.delegate = self + $0.isAutoplay = true + // $0.isMute = true + $0.preventFromScreenLock = true + $0.restorePlayAfterAppEnterForeground = true + $0.minBufferDuration = 1 + } } } @@ -39,7 +41,7 @@ class ViewController: UIViewController { super.viewWillDisappear(animated) stopTimer() - playerViewController.close() + playerViewController?.close() coverView?.isHidden = false } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { @@ -51,8 +53,8 @@ class ViewController: UIViewController { } private func play() { - playerViewController.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" - playerViewController.open() + playerViewController?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" + playerViewController?.open() } private func startTimer() { stopTimer() @@ -68,7 +70,7 @@ class ViewController: UIViewController { } @IBAction private func captureButtonClicked() { - playerViewController.player.snapshot() + playerViewController?.player.snapshot() .map { UIImageView(image: $0) } .map { [weak self] in self?.view.addSubview($0) @@ -76,7 +78,7 @@ class ViewController: UIViewController { } @IBAction private func muteButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected - playerViewController.isMute = !sender.isSelected + playerViewController?.isMute = !sender.isSelected } @IBAction private func playOrPauseButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected @@ -84,15 +86,15 @@ class ViewController: UIViewController { if sender.isSelected { play() } else { - playerViewController.pause() + playerViewController?.pause() } } @IBAction private func refreshButtonClicked(_ sender: UIButton) { - playerViewController.close() + playerViewController?.close() play() } @IBAction private func valueChanged(_ sender: UISlider) { - playerViewController.player.brightness = sender.value + playerViewController?.player.brightness = sender.value } } From f387012ddce7d74a7b22dda790a1cde195e7f22b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 10 Jan 2019 17:03:40 +0900 Subject: [PATCH 074/215] Solved: crash to create snapshot image when gl is not ready. --- DLGPlayer/view/DLGPlayerView.m | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index 577bdd7..fc1aaf9 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -382,6 +382,11 @@ - (UIImage *)snapshot { glReadPixels(0, 0, _backingWidth, _backingHeight, GL_RGBA, GL_UNSIGNED_BYTE, data); CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL); + + if (ref == NULL) { + return nil; + } + CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); CGImageRef iref = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast, ref, NULL, true, kCGRenderingIntentDefault); From 819ceca8e4191a2755b12a44e53cf6228f906b2a Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 11 Jan 2019 15:25:20 +0900 Subject: [PATCH 075/215] Added: log in audioManager. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 717df55..2121c7a 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -259,7 +259,8 @@ - (BOOL)close:(NSArray **)errors { if (errors != nil) errs = [NSMutableArray array]; BOOL closed = YES; - + + NSLog(@"%@::close -> _opened: %d, _audioUnit is NULL: %d", NSStringFromClass(DLGPlayerAudioManager.class), _opened, _audioUnit != NULL); if (_opened && _audioUnit != NULL) { [self pause]; [self unregisterNotifications]; @@ -327,6 +328,7 @@ - (BOOL)play:(NSError **)error { return _playing; } + NSLog(@"%@::play -> _opened: %d, _audioUnit is NULL: %d", NSStringFromClass(DLGPlayerAudioManager.class), _opened, _audioUnit != NULL); if (_opened && _audioUnit != NULL) { OSStatus status = AudioOutputUnitStart(_audioUnit); _playing = (status == noErr); @@ -347,6 +349,7 @@ - (BOOL)pause { } - (BOOL)pause:(NSError **)error { + NSLog(@"%@::pause -> _playing: %d, _audioUnit is NULL: %d", NSStringFromClass(DLGPlayerAudioManager.class), _playing, _audioUnit != NULL); if (_playing && _audioUnit != NULL) { OSStatus status = AudioOutputUnitStop(_audioUnit); _playing = !(status == noErr); From 404a832bf9d6099791a30ce2faf04a8634fd229a Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 11 Jan 2019 15:41:15 +0900 Subject: [PATCH 076/215] Revert "Added: log in audioManager." This reverts commit 819ceca8e4191a2755b12a44e53cf6228f906b2a. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 2121c7a..717df55 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -259,8 +259,7 @@ - (BOOL)close:(NSArray **)errors { if (errors != nil) errs = [NSMutableArray array]; BOOL closed = YES; - - NSLog(@"%@::close -> _opened: %d, _audioUnit is NULL: %d", NSStringFromClass(DLGPlayerAudioManager.class), _opened, _audioUnit != NULL); + if (_opened && _audioUnit != NULL) { [self pause]; [self unregisterNotifications]; @@ -328,7 +327,6 @@ - (BOOL)play:(NSError **)error { return _playing; } - NSLog(@"%@::play -> _opened: %d, _audioUnit is NULL: %d", NSStringFromClass(DLGPlayerAudioManager.class), _opened, _audioUnit != NULL); if (_opened && _audioUnit != NULL) { OSStatus status = AudioOutputUnitStart(_audioUnit); _playing = (status == noErr); @@ -349,7 +347,6 @@ - (BOOL)pause { } - (BOOL)pause:(NSError **)error { - NSLog(@"%@::pause -> _playing: %d, _audioUnit is NULL: %d", NSStringFromClass(DLGPlayerAudioManager.class), _playing, _audioUnit != NULL); if (_playing && _audioUnit != NULL) { OSStatus status = AudioOutputUnitStop(_audioUnit); _playing = !(status == noErr); From 373816f39ab793431f8a5a9a2568a3c115d0fcae Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sun, 13 Jan 2019 19:42:38 +0900 Subject: [PATCH 077/215] Modified: audioUnit set as atomic. --- .../xcschemes/DLGPlayerDemo.xcscheme | 2 +- DLGPlayer/codec/DLGPlayerAudioManager.m | 21 +++++++++---------- DLGPlayerDemo/ViewController.swift | 2 +- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme index 0590862..9ea6c65 100644 --- a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme +++ b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme @@ -77,7 +77,7 @@ diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 717df55..a8d5af5 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -34,10 +34,9 @@ @interface DLGPlayerAudioManager () { double _sampleRate; UInt32 _bitsPerChannel; UInt32 _channelsPerFrame; - AudioUnit _audioUnit; float *_audioData; } - +@property (atomic) AudioUnit audioUnit; @end @implementation DLGPlayerAudioManager @@ -61,7 +60,7 @@ - (void)initVars { _bitsPerChannel = 0; _channelsPerFrame = 0; _bufferDuration = 1; - _audioUnit = NULL; + self.audioUnit = NULL; _audioData = (float *)calloc(MAX_FRAME_SIZE * MAX_CHANNEL, sizeof(float)); _frameReaderBlock = nil; } @@ -242,7 +241,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } - _audioUnit = audioUnit; + self.audioUnit = audioUnit; return YES; } @@ -260,11 +259,11 @@ - (BOOL)close:(NSArray **)errors { BOOL closed = YES; - if (_opened && _audioUnit != NULL) { + if (_opened && self.audioUnit != NULL) { [self pause]; [self unregisterNotifications]; - OSStatus status = AudioUnitUninitialize(_audioUnit); + OSStatus status = AudioUnitUninitialize(self.audioUnit); if (status != noErr) { closed = NO; if (errs != nil) { @@ -279,7 +278,7 @@ - (BOOL)close:(NSArray **)errors { } } - status = AudioComponentInstanceDispose(_audioUnit); + status = AudioComponentInstanceDispose(self.audioUnit); if (status != noErr) { closed = NO; if (errs != nil) { @@ -327,8 +326,8 @@ - (BOOL)play:(NSError **)error { return _playing; } - if (_opened && _audioUnit != NULL) { - OSStatus status = AudioOutputUnitStart(_audioUnit); + if (_opened && self.audioUnit != NULL) { + OSStatus status = AudioOutputUnitStart(self.audioUnit); _playing = (status == noErr); if (!_playing) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -347,8 +346,8 @@ - (BOOL)pause { } - (BOOL)pause:(NSError **)error { - if (_playing && _audioUnit != NULL) { - OSStatus status = AudioOutputUnitStop(_audioUnit); + if (_playing && self.audioUnit != NULL) { + OSStatus status = AudioOutputUnitStop(self.audioUnit); _playing = !(status == noErr); if (_playing) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index baa642d..eead337 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -53,7 +53,7 @@ class ViewController: UIViewController { } private func play() { - playerViewController?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACNZM?token=1234567890" + playerViewController?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACOPP?token=1234567890" playerViewController?.open() } private func startTimer() { From d61607d754e055638883f4cef2227eb7547aad89 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 14 Jan 2019 09:30:42 +0900 Subject: [PATCH 078/215] Changed: dispatch queue to open or close the sound. --- DLGPlayer/DLGPlayer.m | 59 ++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index da71cca..a9fbbd5 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -110,17 +110,14 @@ - (void)clearVars { self.playing = NO; self.opened = NO; self.renderBegan = NO; + self.mediaPosition = 0; + self.bufferedDuration = 0; + self.mediaSyncTime = 0; + self.closing = NO; + self.opening = NO; __weak typeof(self)weakSelf = self; - dispatch_async(_processingQueue, ^{ - weakSelf.mediaPosition = 0; - weakSelf.bufferedDuration = 0; - weakSelf.mediaSyncTime = 0; - weakSelf.closing = NO; - weakSelf.opening = NO; - }); - dispatch_async(_renderingQueue, ^{ [weakSelf.view clear]; }); @@ -136,23 +133,24 @@ - (void)open:(NSString *)url { weakSelf.opening = YES; - dispatch_async(dispatch_get_main_queue(), ^{ - NSError *error = nil; - if ([weakSelf.audio open:&error]) { - weakSelf.decoder.audioChannels = [weakSelf.audio channels]; - weakSelf.decoder.audioSampleRate = [weakSelf.audio sampleRate]; - } else { - [weakSelf handleError:error]; - } - }); - NSError *error = nil; + if ([weakSelf.audio open:&error]) { + weakSelf.decoder.audioChannels = [weakSelf.audio channels]; + weakSelf.decoder.audioSampleRate = [weakSelf.audio sampleRate]; + } else { + [weakSelf handleError:error]; + } + if (![weakSelf.decoder open:url error:&error]) { weakSelf.opening = NO; [weakSelf handleError:error]; return; } + weakSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [weakSelf readAudioFrame:data frames:frames channels:channels]; + }; + dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf.view setCurrentEAGLContext]; @@ -170,12 +168,8 @@ - (void)open:(NSString *)url { weakSelf.bufferedDuration = 0; weakSelf.mediaPosition = 0; weakSelf.mediaSyncTime = 0; - - weakSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [weakSelf readAudioFrame:data frames:frames channels:channels]; - }; - weakSelf.opened = YES; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:weakSelf]; }); }); @@ -195,17 +189,18 @@ - (void)close { [weakSelf.decoder prepareClose]; [weakSelf.decoder close]; - dispatch_async(dispatch_get_main_queue(), ^{ - NSArray *errors = nil; - if ([weakSelf.audio close:&errors]) { - [weakSelf clearVars]; + NSArray *errors = nil; + if ([weakSelf.audio close:&errors]) { + [weakSelf clearVars]; + + dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:weakSelf]; - } else { - for (NSError *error in errors) { - [weakSelf handleError:error]; - } + }); + } else { + for (NSError *error in errors) { + [weakSelf handleError:error]; } - }); + } }); } From 88b7ff1b6ad72596a35f405dd00cfd1633798c65 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 14 Jan 2019 13:33:00 +0900 Subject: [PATCH 079/215] Revert "Changed: dispatch queue to open or close the sound." This reverts commit d61607d754e055638883f4cef2227eb7547aad89. --- DLGPlayer/DLGPlayer.m | 59 +++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index a9fbbd5..da71cca 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -110,14 +110,17 @@ - (void)clearVars { self.playing = NO; self.opened = NO; self.renderBegan = NO; - self.mediaPosition = 0; - self.bufferedDuration = 0; - self.mediaSyncTime = 0; - self.closing = NO; - self.opening = NO; __weak typeof(self)weakSelf = self; + dispatch_async(_processingQueue, ^{ + weakSelf.mediaPosition = 0; + weakSelf.bufferedDuration = 0; + weakSelf.mediaSyncTime = 0; + weakSelf.closing = NO; + weakSelf.opening = NO; + }); + dispatch_async(_renderingQueue, ^{ [weakSelf.view clear]; }); @@ -133,24 +136,23 @@ - (void)open:(NSString *)url { weakSelf.opening = YES; - NSError *error = nil; - if ([weakSelf.audio open:&error]) { - weakSelf.decoder.audioChannels = [weakSelf.audio channels]; - weakSelf.decoder.audioSampleRate = [weakSelf.audio sampleRate]; - } else { - [weakSelf handleError:error]; - } + dispatch_async(dispatch_get_main_queue(), ^{ + NSError *error = nil; + if ([weakSelf.audio open:&error]) { + weakSelf.decoder.audioChannels = [weakSelf.audio channels]; + weakSelf.decoder.audioSampleRate = [weakSelf.audio sampleRate]; + } else { + [weakSelf handleError:error]; + } + }); + NSError *error = nil; if (![weakSelf.decoder open:url error:&error]) { weakSelf.opening = NO; [weakSelf handleError:error]; return; } - weakSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [weakSelf readAudioFrame:data frames:frames channels:channels]; - }; - dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf.view setCurrentEAGLContext]; @@ -168,8 +170,12 @@ - (void)open:(NSString *)url { weakSelf.bufferedDuration = 0; weakSelf.mediaPosition = 0; weakSelf.mediaSyncTime = 0; - weakSelf.opened = YES; + + weakSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [weakSelf readAudioFrame:data frames:frames channels:channels]; + }; + weakSelf.opened = YES; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:weakSelf]; }); }); @@ -189,18 +195,17 @@ - (void)close { [weakSelf.decoder prepareClose]; [weakSelf.decoder close]; - NSArray *errors = nil; - if ([weakSelf.audio close:&errors]) { - [weakSelf clearVars]; - - dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_async(dispatch_get_main_queue(), ^{ + NSArray *errors = nil; + if ([weakSelf.audio close:&errors]) { + [weakSelf clearVars]; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:weakSelf]; - }); - } else { - for (NSError *error in errors) { - [weakSelf handleError:error]; + } else { + for (NSError *error in errors) { + [weakSelf handleError:error]; + } } - } + }); }); } From 4c983e4792cd53f46d118ec9bf204e1a39b701c8 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 14 Jan 2019 13:38:16 +0900 Subject: [PATCH 080/215] Added: test code. --- DLGPlayerDemo/Base.lproj/Main.storyboard | 2 +- DLGPlayerDemo/ViewController.swift | 39 ++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index d308c84..793aa34 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -95,7 +95,7 @@ - + diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index eead337..5e86e81 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -27,7 +27,7 @@ class ViewController: UIViewController { } } } - + override func viewDidLoad() { super.viewDidLoad() @@ -35,8 +35,36 @@ class ViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + playerViewController?.close() play() } + private func refresh() { + playerViewController?.close() + play() + + let rand1 = CGFloat(arc4random_uniform(2)) + let rand2 = CGFloat(arc4random_uniform(3) + 1) + let delay: TimeInterval = TimeInterval(rand1 + (1 / rand2)) + + print("delay", delay) + + DispatchQueue.main.asyncAfter(deadline: .now() + delay) { + self.refresh() + } + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + +// refresh() + +// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { +// if self.coverView == nil { +// self.navigationController?.popViewController(animated: true) +// } else { +// self.performSegue(withIdentifier: "NextView", sender: nil) +// } +// } + } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) @@ -66,7 +94,7 @@ class ViewController: UIViewController { } @objc private func timerCompletion() { -// print("player.position", playerViewController.player.position) + // print("player.position", playerViewController.player.position) } @IBAction private func captureButtonClicked() { @@ -84,7 +112,11 @@ class ViewController: UIViewController { sender.isSelected = !sender.isSelected if sender.isSelected { - play() + if playerViewController?.status == .paused { + playerViewController?.play() + } else { + play() + } } else { playerViewController?.pause() } @@ -101,6 +133,7 @@ class ViewController: UIViewController { extension ViewController: DLGSimplePlayerViewControllerDelegate { func didBeginRender(in viewController: DLGSimplePlayerViewController) { coverView?.isHidden = true +// viewController.pause() } func viewController(_ viewController: DLGSimplePlayerViewController, didReceiveError error: Error) { print("didReceiveError", error) From c46b6b2f857df305758079d90b8c5c72b62c84c9 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 12 Feb 2019 15:35:25 +0900 Subject: [PATCH 081/215] Modified: clear variables when dealloc called in player view. --- DLGPlayer/DLGPlayer.m | 2 +- DLGPlayer/codec/DLGPlayerAudioManager.m | 2 -- DLGPlayer/codec/DLGPlayerDecoder.m | 1 - DLGPlayer/view/DLGPlayerView.m | 1 - DLGPlayerDemo/ViewController.swift | 8 +++++--- Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj | 2 ++ 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index da71cca..db5f5d1 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -53,7 +53,7 @@ - (id)init { } - (void)dealloc { - NSLog(@"DLGPlayer dealloc"); + [self clearVars]; } - (void)initAll { diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index a8d5af5..3f604a2 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -66,8 +66,6 @@ - (void)initVars { } - (void)dealloc { - NSLog(@"DLGPlayerAudioManager dealloc"); - [self unregisterNotifications]; if (_audioData != NULL) { diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index e67c9cc..17ac8c3 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -58,7 +58,6 @@ @interface DLGPlayerDecoder () { @implementation DLGPlayerDecoder - (void)dealloc { - NSLog(@"DLGPlayerDecoder dealloc"); } - (BOOL)open:(NSString *)url error:(NSError **)error { diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index fc1aaf9..39eb826 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -74,7 +74,6 @@ - (id)initWithFrame:(CGRect)frame { } - (void)dealloc { - NSLog(@"DLGPlayerView dealloc"); } + (Class)layerClass { diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 5e86e81..aa93d20 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -35,8 +35,10 @@ class ViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - playerViewController?.close() - play() + if (navigationController?.viewControllers.count ?? 0) > 1 { + playerViewController?.close() + play() + } } private func refresh() { playerViewController?.close() @@ -81,7 +83,7 @@ class ViewController: UIViewController { } private func play() { - playerViewController?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACOPP?token=1234567890" + playerViewController?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPOS?token=1234567890" playerViewController?.open() } private func startTimer() { diff --git a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj index 4a9da0f..bcb05a2 100644 --- a/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj +++ b/Example-Carthage/DLGPlayerDemo.xcodeproj/project.pbxproj @@ -391,6 +391,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = F5NU2PA3PK; + ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", @@ -414,6 +415,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = F5NU2PA3PK; + ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Carthage/Build/iOS", From 49f5b1185b72ec16e1aa0fc15ca11b7701e809e8 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 12 Feb 2019 16:17:51 +0900 Subject: [PATCH 082/215] Bug fix: change weak reference to strong in close function. --- DLGPlayer/DLGPlayer.m | 20 ++++++++++---------- DLGPlayer/codec/DLGPlayerAudioManager.m | 1 + DLGPlayer/codec/DLGPlayerDecoder.m | 1 + 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index db5f5d1..8d8fb09 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -53,7 +53,7 @@ - (id)init { } - (void)dealloc { - [self clearVars]; + NSLog(@"DLGPlayer dealloc"); } - (void)initAll { @@ -184,25 +184,25 @@ - (void)open:(NSString *)url { - (void)close { [self pause]; - __weak typeof(self)weakSelf = self; + __strong typeof(self)strongSelf = self; dispatch_async(_processingQueue, ^{ - if (weakSelf.closing) { + if (strongSelf.closing) { return; } - weakSelf.closing = YES; - [weakSelf.decoder prepareClose]; - [weakSelf.decoder close]; + strongSelf.closing = YES; + [strongSelf.decoder prepareClose]; + [strongSelf.decoder close]; dispatch_async(dispatch_get_main_queue(), ^{ NSArray *errors = nil; - if ([weakSelf.audio close:&errors]) { - [weakSelf clearVars]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:weakSelf]; + if ([strongSelf.audio close:&errors]) { + [strongSelf clearVars]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; } else { for (NSError *error in errors) { - [weakSelf handleError:error]; + [strongSelf handleError:error]; } } }); diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 3f604a2..601fb53 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -66,6 +66,7 @@ - (void)initVars { } - (void)dealloc { + NSLog(@"DLGPlayerAudioManager dealloc"); [self unregisterNotifications]; if (_audioData != NULL) { diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index 17ac8c3..e67c9cc 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -58,6 +58,7 @@ @interface DLGPlayerDecoder () { @implementation DLGPlayerDecoder - (void)dealloc { + NSLog(@"DLGPlayerDecoder dealloc"); } - (BOOL)open:(NSString *)url error:(NSError **)error { From 82602b6dc6b8f62f1c068e8b1f9df8e115cc0afb Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 12 Feb 2019 16:37:30 +0900 Subject: [PATCH 083/215] Bug fix --- DLGPlayer/DLGPlayer.m | 1 + 1 file changed, 1 insertion(+) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 8d8fb09..9302212 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -54,6 +54,7 @@ - (id)init { - (void)dealloc { NSLog(@"DLGPlayer dealloc"); + [self.decoder prepareClose]; } - (void)initAll { From 85bc8f3e565e30abf90b2ae7257a28315c98abda Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 12 Feb 2019 16:56:02 +0900 Subject: [PATCH 084/215] Modified: callback function for interrupt static to instance. --- DLGPlayer/DLGPlayer.m | 1 - DLGPlayer/codec/DLGPlayerDecoder.m | 20 ++++++++++---------- DLGPlayerDemo/ViewController.swift | 7 ++----- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 9302212..8d8fb09 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -54,7 +54,6 @@ - (id)init { - (void)dealloc { NSLog(@"DLGPlayer dealloc"); - [self.decoder prepareClose]; } - (void)initAll { diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index e67c9cc..5e80e30 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -23,16 +23,6 @@ #define DLGPlayerIOTimeout 30 -static NSTimeInterval g_dIOStartTime = 0; -static bool g_bPrepareClose = FALSE; - -static int interruptCallback(void *context) { - NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate]; - NSTimeInterval dt = t - g_dIOStartTime; - if (g_bPrepareClose || dt > DLGPlayerIOTimeout) return 1; - return 0; -} - @interface DLGPlayerDecoder () { AVFormatContext *m_pFormatContext; @@ -57,6 +47,16 @@ @interface DLGPlayerDecoder () { @implementation DLGPlayerDecoder +NSTimeInterval g_dIOStartTime = 0; +bool g_bPrepareClose = FALSE; + +int interruptCallback(void *context) { + NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate]; + NSTimeInterval dt = t - g_dIOStartTime; + if (g_bPrepareClose || dt > DLGPlayerIOTimeout) return 1; + return 0; +} + - (void)dealloc { NSLog(@"DLGPlayerDecoder dealloc"); } diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index aa93d20..f11a915 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -35,10 +35,7 @@ class ViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - if (navigationController?.viewControllers.count ?? 0) > 1 { - playerViewController?.close() - play() - } + play() } private func refresh() { playerViewController?.close() @@ -83,7 +80,7 @@ class ViewController: UIViewController { } private func play() { - playerViewController?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPOS?token=1234567890" + playerViewController?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" playerViewController?.open() } private func startTimer() { From 5a129310f71093b174dedfb20d89fbad8f0907af Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 12 Feb 2019 17:08:47 +0900 Subject: [PATCH 085/215] Rollback: callback function for interrupt static to instance. --- DLGPlayer/codec/DLGPlayerDecoder.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index 5e80e30..e67c9cc 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -23,6 +23,16 @@ #define DLGPlayerIOTimeout 30 +static NSTimeInterval g_dIOStartTime = 0; +static bool g_bPrepareClose = FALSE; + +static int interruptCallback(void *context) { + NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate]; + NSTimeInterval dt = t - g_dIOStartTime; + if (g_bPrepareClose || dt > DLGPlayerIOTimeout) return 1; + return 0; +} + @interface DLGPlayerDecoder () { AVFormatContext *m_pFormatContext; @@ -47,16 +57,6 @@ @interface DLGPlayerDecoder () { @implementation DLGPlayerDecoder -NSTimeInterval g_dIOStartTime = 0; -bool g_bPrepareClose = FALSE; - -int interruptCallback(void *context) { - NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate]; - NSTimeInterval dt = t - g_dIOStartTime; - if (g_bPrepareClose || dt > DLGPlayerIOTimeout) return 1; - return 0; -} - - (void)dealloc { NSLog(@"DLGPlayerDecoder dealloc"); } From 97bb8d577f0f895db8fd8c5c03866d4aaacaa8b2 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 25 Feb 2019 20:32:34 +0900 Subject: [PATCH 086/215] Added: function to frameDrop. --- DLGPlayer/DLGPlayer.h | 1 + DLGPlayer/DLGPlayer.m | 26 ++++++++++++++++++++++- DLGPlayer/DLGSimplePlayerViewController.h | 1 + DLGPlayer/DLGSimplePlayerViewController.m | 8 +++++++ DLGPlayer/common/DLGPlayerDef.h | 1 + DLGPlayerDemo/ViewController.swift | 8 +++---- 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 8293581..e94fffc 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -27,6 +27,7 @@ typedef void (^onPauseComplete)(void); @property (readonly, strong) UIView *playerView; +@property (nonatomic) double frameDropDuration; @property (nonatomic) double minBufferDuration; @property (nonatomic) double maxBufferDuration; @property (nonatomic) double position; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 8d8fb09..4ec1dd9 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -64,6 +64,7 @@ - (void)initAll { } - (void)initVars { + _frameDropDuration = DLGPlayerFrameDropDuration; _minBufferDuration = DLGPlayerMinBufferDuration; _maxBufferDuration = DLGPlayerMaxBufferDuration; _bufferedDuration = 0; @@ -282,6 +283,8 @@ - (void)readFrame { if (tempVFrames.count > 0) { self.bufferedDuration += tempDuration; tempDuration = 0; + + [self dropFrames:self.vframes allowsBufferDurationReducing:YES]; [self.vframes addObjectsFromArray:tempVFrames]; [tempVFrames removeAllObjects]; } @@ -303,6 +306,7 @@ - (void)readFrame { self.bufferedDuration += tempDuration; tempDuration = 0; } + [self dropFrames:self.aframes allowsBufferDurationReducing:!self.decoder.hasVideo]; [self.aframes addObjectsFromArray:tempAFrames]; [tempAFrames removeAllObjects]; } @@ -343,6 +347,26 @@ - (void)readFrame { self.buffering = NO; } +- (void)dropFrames:(NSMutableArray *)frames allowsBufferDurationReducing:(BOOL)allowsBufferDurationReducing { + if (!(self.frameDropDuration > 0)) { + return; + } + + NSInteger limit = self.frameDropDuration * _decoder.videoFPS; + + if (frames.count > limit) { + for (NSInteger i=0; i Date: Tue, 26 Feb 2019 12:12:59 +0900 Subject: [PATCH 087/215] Add: logic to drop audio frames in buffer for frame drop function. --- DLGPlayer/DLGPlayer.m | 60 ++++++++++++++++++++++++------ DLGPlayer/codec/DLGPlayerDecoder.m | 3 +- DLGPlayer/common/DLGPlayerDef.h | 2 +- DLGPlayerDemo/ViewController.swift | 2 +- 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 4ec1dd9..cb284e1 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -284,7 +284,7 @@ - (void)readFrame { self.bufferedDuration += tempDuration; tempDuration = 0; - [self dropFrames:self.vframes allowsBufferDurationReducing:YES]; + [self dropVideoFrames]; [self.vframes addObjectsFromArray:tempVFrames]; [tempVFrames removeAllObjects]; } @@ -306,7 +306,7 @@ - (void)readFrame { self.bufferedDuration += tempDuration; tempDuration = 0; } - [self dropFrames:self.aframes allowsBufferDurationReducing:!self.decoder.hasVideo]; + [self dropAudioFrames]; [self.aframes addObjectsFromArray:tempAFrames]; [tempAFrames removeAllObjects]; } @@ -347,22 +347,58 @@ - (void)readFrame { self.buffering = NO; } -- (void)dropFrames:(NSMutableArray *)frames allowsBufferDurationReducing:(BOOL)allowsBufferDurationReducing { - if (!(self.frameDropDuration > 0)) { +- (void)dropAudioFrames { + if (self.frameDropDuration < 0) { + return; + } + if (self.frameDropDuration == 0) { + for (DLGPlayerFrame *frame in self.aframes) { + if (!self.decoder.hasVideo) { + self.bufferedDuration -= frame.duration; + } + } + [self.aframes removeAllObjects]; return; } - NSInteger limit = self.frameDropDuration * _decoder.videoFPS; + __block double total = 0; + __block NSInteger count = self.aframes.count; - if (frames.count > limit) { - for (NSInteger i=0; i=0; i--) { + DLGPlayerFrame *frame = (DLGPlayerFrame *) self.aframes[i]; + total += frame.duration; + + if (total > self.frameDropDuration) { + if (!self.decoder.hasVideo) { + self.bufferedDuration -= total; } + + [self.aframes removeObjectsInRange:NSMakeRange(0, i)]; + return; + } + } +} - [frames removeLastObject]; +- (void)dropVideoFrames { + if (self.frameDropDuration < 0) { + return; + } + if (self.frameDropDuration == 0) { + for (DLGPlayerFrame *frame in self.vframes) { + self.bufferedDuration -= frame.duration; + } + [self.vframes removeAllObjects]; + return; + } + + NSInteger limit = (NSInteger) floor(self.frameDropDuration * self.decoder.videoFPS); + NSInteger count = self.vframes.count; + + if (count > limit) { + for (NSInteger i=0; i<(count - self.decoder.videoFPS); i++) { + DLGPlayerFrame *frame = (DLGPlayerFrame *) self.vframes.firstObject; + self.bufferedDuration -= frame.duration; + [self.vframes removeObjectAtIndex:0]; } } } diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index e67c9cc..63cdc7d 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -142,7 +142,6 @@ - (BOOL)open:(NSString *)url error:(NSError **)error { if (astream >= 0 && acodectx != NULL) { aframe = av_frame_alloc(); [DLGPlayerDecoder stream:fmtctx->streams[astream] fps:NULL timebase:&_audioTimebase default:0.025]; - if (aframe == NULL) { astream = -1; if (acodectx != NULL) avcodec_free_context(&acodectx); @@ -358,7 +357,7 @@ - (void)flush:(AVCodecContext *)codectx frame:(AVFrame *)frame { #pragma mark - Handle Frames - (NSArray *)readFrames { - if ((m_nVideoStream < 0 && m_nAudioStream < 0) || _isEOF) return nil; + if ((m_nVideoStream < 0 && m_nAudioStream < 0) || self.isEOF) return nil; AVFormatContext *fmtctx = m_pFormatContext; const int vstream = m_nVideoStream; diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index 5020950..c78018c 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -11,7 +11,7 @@ #define DLGPlayerLocalizedStringTable @"DLGPlayerStrings" -#define DLGPlayerFrameDropDuration 0 +#define DLGPlayerFrameDropDuration -1 #define DLGPlayerMinBufferDuration 2 #define DLGPlayerMaxBufferDuration 5 diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 190f6bd..a24f3ce 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -79,7 +79,7 @@ class ViewController: UIViewController { } private func play() { - playerViewController?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" + playerViewController?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" // playerViewController?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" playerViewController?.open() } From 777a274d0515a5f2500e1c526508183b0c6b67c7 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 26 Feb 2019 15:07:52 +0900 Subject: [PATCH 088/215] Revert "Rollback: callback function for interrupt static to instance." This reverts commit 5a129310f71093b174dedfb20d89fbad8f0907af. --- DLGPlayer/codec/DLGPlayerDecoder.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index 63cdc7d..ca80f24 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -23,16 +23,6 @@ #define DLGPlayerIOTimeout 30 -static NSTimeInterval g_dIOStartTime = 0; -static bool g_bPrepareClose = FALSE; - -static int interruptCallback(void *context) { - NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate]; - NSTimeInterval dt = t - g_dIOStartTime; - if (g_bPrepareClose || dt > DLGPlayerIOTimeout) return 1; - return 0; -} - @interface DLGPlayerDecoder () { AVFormatContext *m_pFormatContext; @@ -57,6 +47,16 @@ @interface DLGPlayerDecoder () { @implementation DLGPlayerDecoder +NSTimeInterval g_dIOStartTime = 0; +bool g_bPrepareClose = FALSE; + +int interruptCallback(void *context) { + NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate]; + NSTimeInterval dt = t - g_dIOStartTime; + if (g_bPrepareClose || dt > DLGPlayerIOTimeout) return 1; + return 0; +} + - (void)dealloc { NSLog(@"DLGPlayerDecoder dealloc"); } From 501a07a83da8a8f6c8b12cdf6b36332bfea3d9cb Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 26 Feb 2019 15:11:16 +0900 Subject: [PATCH 089/215] Rollback: frame drop function. --- DLGPlayer/DLGPlayer.h | 1 - DLGPlayer/DLGPlayer.m | 59 ----------------------- DLGPlayer/DLGSimplePlayerViewController.h | 1 - DLGPlayer/DLGSimplePlayerViewController.m | 8 --- DLGPlayer/codec/DLGPlayerDecoder.m | 20 ++++---- DLGPlayer/common/DLGPlayerDef.h | 1 - DLGPlayerDemo/ViewController.swift | 1 - 7 files changed, 10 insertions(+), 81 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index e94fffc..8293581 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -27,7 +27,6 @@ typedef void (^onPauseComplete)(void); @property (readonly, strong) UIView *playerView; -@property (nonatomic) double frameDropDuration; @property (nonatomic) double minBufferDuration; @property (nonatomic) double maxBufferDuration; @property (nonatomic) double position; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index cb284e1..eb4f7be 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -64,7 +64,6 @@ - (void)initAll { } - (void)initVars { - _frameDropDuration = DLGPlayerFrameDropDuration; _minBufferDuration = DLGPlayerMinBufferDuration; _maxBufferDuration = DLGPlayerMaxBufferDuration; _bufferedDuration = 0; @@ -284,7 +283,6 @@ - (void)readFrame { self.bufferedDuration += tempDuration; tempDuration = 0; - [self dropVideoFrames]; [self.vframes addObjectsFromArray:tempVFrames]; [tempVFrames removeAllObjects]; } @@ -306,7 +304,6 @@ - (void)readFrame { self.bufferedDuration += tempDuration; tempDuration = 0; } - [self dropAudioFrames]; [self.aframes addObjectsFromArray:tempAFrames]; [tempAFrames removeAllObjects]; } @@ -347,62 +344,6 @@ - (void)readFrame { self.buffering = NO; } -- (void)dropAudioFrames { - if (self.frameDropDuration < 0) { - return; - } - if (self.frameDropDuration == 0) { - for (DLGPlayerFrame *frame in self.aframes) { - if (!self.decoder.hasVideo) { - self.bufferedDuration -= frame.duration; - } - } - [self.aframes removeAllObjects]; - return; - } - - __block double total = 0; - __block NSInteger count = self.aframes.count; - - for (NSInteger i=count - 1; i>=0; i--) { - DLGPlayerFrame *frame = (DLGPlayerFrame *) self.aframes[i]; - total += frame.duration; - - if (total > self.frameDropDuration) { - if (!self.decoder.hasVideo) { - self.bufferedDuration -= total; - } - - [self.aframes removeObjectsInRange:NSMakeRange(0, i)]; - return; - } - } -} - -- (void)dropVideoFrames { - if (self.frameDropDuration < 0) { - return; - } - if (self.frameDropDuration == 0) { - for (DLGPlayerFrame *frame in self.vframes) { - self.bufferedDuration -= frame.duration; - } - [self.vframes removeAllObjects]; - return; - } - - NSInteger limit = (NSInteger) floor(self.frameDropDuration * self.decoder.videoFPS); - NSInteger count = self.vframes.count; - - if (count > limit) { - for (NSInteger i=0; i<(count - self.decoder.videoFPS); i++) { - DLGPlayerFrame *frame = (DLGPlayerFrame *) self.vframes.firstObject; - self.bufferedDuration -= frame.duration; - [self.vframes removeObjectAtIndex:0]; - } - } -} - - (void)seekPositionInFrameReader { [self.decoder seek:self.requestSeekPosition]; diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index aa263d6..00529d7 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -26,7 +26,6 @@ @property (nonatomic) BOOL isRepeat; @property (nonatomic) BOOL preventFromScreenLock; @property (nonatomic) BOOL restorePlayAfterAppEnterForeground; -@property (nonatomic) double frameDropDuration; @property (nonatomic) double minBufferDuration; @property (nonatomic) double maxBufferDuration; @property (nullable, nonatomic, copy) NSString *url; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index a0052e7..b51c863 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -97,14 +97,6 @@ - (void)setIsMute:(BOOL)isMute { _player.audio.mute = isMute; } -- (double)frameDropDuration { - return _player.frameDropDuration; -} - -- (void)setFrameDropDuration:(double)frameDropDuration { - _player.frameDropDuration = frameDropDuration; -} - - (double)minBufferDuration { return _player.minBufferDuration; } diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index ca80f24..63cdc7d 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -23,6 +23,16 @@ #define DLGPlayerIOTimeout 30 +static NSTimeInterval g_dIOStartTime = 0; +static bool g_bPrepareClose = FALSE; + +static int interruptCallback(void *context) { + NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate]; + NSTimeInterval dt = t - g_dIOStartTime; + if (g_bPrepareClose || dt > DLGPlayerIOTimeout) return 1; + return 0; +} + @interface DLGPlayerDecoder () { AVFormatContext *m_pFormatContext; @@ -47,16 +57,6 @@ @interface DLGPlayerDecoder () { @implementation DLGPlayerDecoder -NSTimeInterval g_dIOStartTime = 0; -bool g_bPrepareClose = FALSE; - -int interruptCallback(void *context) { - NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate]; - NSTimeInterval dt = t - g_dIOStartTime; - if (g_bPrepareClose || dt > DLGPlayerIOTimeout) return 1; - return 0; -} - - (void)dealloc { NSLog(@"DLGPlayerDecoder dealloc"); } diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index c78018c..1aeb04e 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -11,7 +11,6 @@ #define DLGPlayerLocalizedStringTable @"DLGPlayerStrings" -#define DLGPlayerFrameDropDuration -1 #define DLGPlayerMinBufferDuration 2 #define DLGPlayerMaxBufferDuration 5 diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index a24f3ce..f79374a 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -23,7 +23,6 @@ class ViewController: UIViewController { // $0.isMute = true $0.preventFromScreenLock = true $0.restorePlayAfterAppEnterForeground = true - $0.frameDropDuration = 1 $0.minBufferDuration = 0 } } From 49e5ec201f20c8867a86e866d497d2b8f215bf40 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 28 Feb 2019 17:59:54 +0900 Subject: [PATCH 090/215] Improvement: make it is able to play when audio frame not ready. --- DLGPlayer/DLGPlayer.m | 3 ++- DLGPlayerDemo/ViewController.swift | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index eb4f7be..d731990 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -266,6 +266,7 @@ - (void)readFrame { && (self.bufferedDuration + tempDuration) < self.maxBufferDuration) { @autoreleasepool { NSArray *fs = [self.decoder readFrames]; + if (fs == nil) { break; } if (fs.count == 0) { continue; } @@ -368,7 +369,7 @@ - (void)render { if (!self.playing) return; BOOL eof = self.decoder.isEOF; - BOOL noframes = ((self.decoder.hasVideo && self.vframes.count <= 0) || + BOOL noframes = ((self.decoder.hasVideo && self.vframes.count <= 0) && (self.decoder.hasAudio && self.aframes.count <= 0)); // Check if reach the end and play all frames. diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index f79374a..d0e187d 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -24,6 +24,7 @@ class ViewController: UIViewController { $0.preventFromScreenLock = true $0.restorePlayAfterAppEnterForeground = true $0.minBufferDuration = 0 + $0.maxBufferDuration = 2 } } } @@ -78,7 +79,7 @@ class ViewController: UIViewController { } private func play() { - playerViewController?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" + playerViewController?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" // playerViewController?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" playerViewController?.open() } From c30762337799d765accb4f44d7a251f4c35472c1 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 6 Mar 2019 20:31:21 +0900 Subject: [PATCH 091/215] Modified: change private access limiter to public. --- DLGPlayer/DLGPlayer.h | 1 + DLGPlayer/DLGPlayer.m | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 8293581..6209661 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -35,6 +35,7 @@ typedef void (^onPauseComplete)(void); @property (nonatomic) BOOL playing; @property (nonatomic) BOOL buffering; @property (nonatomic) float brightness; +@property (nonatomic, strong) dispatch_queue_t processingQueue; @property (nonatomic, strong) dispatch_queue_t renderingQueue; @property (nonatomic, strong) NSDictionary *metadata; @property (nonatomic, readonly) DLGPlayerAudioManager *audio; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index d731990..4c37cef 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -39,7 +39,6 @@ @interface DLGPlayer () @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; -@property (nonatomic, strong) dispatch_queue_t processingQueue; @end @implementation DLGPlayer From 05e83ff5d99f403c8a4fc38b58df65fbce1a180b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 7 Mar 2019 13:33:50 +0900 Subject: [PATCH 092/215] Modified: set video url as atomic. --- DLGPlayer/DLGSimplePlayerViewController.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index 00529d7..d9cd915 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -28,7 +28,7 @@ @property (nonatomic) BOOL restorePlayAfterAppEnterForeground; @property (nonatomic) double minBufferDuration; @property (nonatomic) double maxBufferDuration; -@property (nullable, nonatomic, copy) NSString *url; +@property (nullable, atomic, copy) NSString *url; @property (nonnull, nonatomic, readonly) DLGPlayerControlStatus *controlStatus; @property (nonatomic, readonly) DLGPlayerStatus status; @property (nonnull, nonatomic, readonly) DLGPlayer *player; From ab7d4d81e9740f14996db7ec74cdffa216b70f17 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 7 Mar 2019 16:09:30 +0900 Subject: [PATCH 093/215] Modified: url is synchronized on processing queue. --- DLGPlayer/DLGSimplePlayerViewController.h | 2 +- DLGPlayer/DLGSimplePlayerViewController.m | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index d9cd915..00529d7 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -28,7 +28,7 @@ @property (nonatomic) BOOL restorePlayAfterAppEnterForeground; @property (nonatomic) double minBufferDuration; @property (nonatomic) double maxBufferDuration; -@property (nullable, atomic, copy) NSString *url; +@property (nullable, nonatomic, copy) NSString *url; @property (nonnull, nonatomic, readonly) DLGPlayerControlStatus *controlStatus; @property (nonatomic, readonly) DLGPlayerStatus status; @property (nonnull, nonatomic, readonly) DLGPlayer *player; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index b51c863..f7c25cc 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -20,7 +20,7 @@ @interface DLGSimplePlayerViewController () { BOOL restorePlay; } - + @property (nonatomic, readwrite) DLGPlayer *player; @property (nonatomic, readwrite) DLGPlayerStatus status; @end @@ -73,7 +73,19 @@ - (void)viewWillDisappear:(BOOL)animated { #pragma mark - getter/setter - (BOOL)hasUrl { - return _url != nil && [_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet].length > 0; + __block BOOL flag; + __strong typeof(self)strongSelf = self; + dispatch_sync(_player.processingQueue, ^{ + flag = strongSelf->_url != nil && [strongSelf->_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet].length > 0; + }); + return flag; +} + +- (void)setUrl:(NSString *)url { + __strong typeof(self)strongSelf = self; + dispatch_sync(_player.processingQueue, ^{ + strongSelf->_url = url; + }); } - (BOOL)isPlaying { From 89bd6a464f9fd41d2a7c692dff2903141384a827 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 7 Mar 2019 18:00:08 +0900 Subject: [PATCH 094/215] Freezing fixed. --- DLGPlayer/DLGSimplePlayerViewController.m | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index f7c25cc..1a56bf0 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -73,17 +73,12 @@ - (void)viewWillDisappear:(BOOL)animated { #pragma mark - getter/setter - (BOOL)hasUrl { - __block BOOL flag; - __strong typeof(self)strongSelf = self; - dispatch_sync(_player.processingQueue, ^{ - flag = strongSelf->_url != nil && [strongSelf->_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet].length > 0; - }); - return flag; + return _url != nil && [_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet].length > 0; } - (void)setUrl:(NSString *)url { __strong typeof(self)strongSelf = self; - dispatch_sync(_player.processingQueue, ^{ + dispatch_async(_player.processingQueue, ^{ strongSelf->_url = url; }); } From 3e51bd30f993de0003dbe3fe1a8b9671e8bacee2 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 7 Mar 2019 20:18:00 +0900 Subject: [PATCH 095/215] Bug fix --- DLGPlayer/DLGSimplePlayerViewController.h | 2 +- DLGPlayer/DLGSimplePlayerViewController.m | 7 ----- DLGPlayerDemo/ViewController.swift | 35 ++++++++++++++++++++++- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index 00529d7..d9cd915 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -28,7 +28,7 @@ @property (nonatomic) BOOL restorePlayAfterAppEnterForeground; @property (nonatomic) double minBufferDuration; @property (nonatomic) double maxBufferDuration; -@property (nullable, nonatomic, copy) NSString *url; +@property (nullable, atomic, copy) NSString *url; @property (nonnull, nonatomic, readonly) DLGPlayerControlStatus *controlStatus; @property (nonatomic, readonly) DLGPlayerStatus status; @property (nonnull, nonatomic, readonly) DLGPlayer *player; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 1a56bf0..6db11ae 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -76,13 +76,6 @@ - (BOOL)hasUrl { return _url != nil && [_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet].length > 0; } -- (void)setUrl:(NSString *)url { - __strong typeof(self)strongSelf = self; - dispatch_async(_player.processingQueue, ^{ - strongSelf->_url = url; - }); -} - - (BOOL)isPlaying { return _player.playing; } diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index d0e187d..9e276d1 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -36,6 +36,7 @@ class ViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + playCount = 0 play() } private func refresh() { @@ -127,18 +128,50 @@ class ViewController: UIViewController { @IBAction private func valueChanged(_ sender: UISlider) { playerViewController?.player.brightness = sender.value } + + private var playCount: Int = 0 } extension ViewController: DLGSimplePlayerViewControllerDelegate { + + private func playTest(_ count: Int) { + let url = count % 2 == 0 ? + "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : + "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" + + playerViewController?.close() + + print(") ------------------------------------------------------------------------------------") + print(") open", url) + playerViewController?.url = url + playerViewController?.open() + print(") opening", playerViewController?.url) + } + + func didBeginRender(in viewController: DLGSimplePlayerViewController) { coverView?.isHidden = true // viewController.pause() + print(") opened", viewController.url) + + if #available(iOS 10.0, *), playCount < 5 { + var count = 0 + + Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { + self.playTest(count) + count += 1 + + if count > 5 { + $0.invalidate() + } + } + } } func viewController(_ viewController: DLGSimplePlayerViewController, didReceiveError error: Error) { print("didReceiveError", error) } func viewController(_ viewController: DLGSimplePlayerViewController, didChange status: DLGPlayerStatus) { - print("didChange", viewController.hash, status.stringValue) +// print("didChange", viewController.hash, status.stringValue) playOrPauseButton.isSelected = viewController.controlStatus.playing muteButton.isSelected = !viewController.isMute From 0affc52e09f42614067d082954d725bc47633246 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 15 Mar 2019 10:19:35 +0900 Subject: [PATCH 096/215] Fixed: reference relationship bugs. --- DLGPlayer/DLGPlayer.m | 78 ++++++++++++++++++------------ DLGPlayerDemo/ViewController.swift | 24 ++++----- 2 files changed, 58 insertions(+), 44 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 4c37cef..79504f7 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -113,15 +113,17 @@ - (void)clearVars { __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ - weakSelf.mediaPosition = 0; - weakSelf.bufferedDuration = 0; - weakSelf.mediaSyncTime = 0; - weakSelf.closing = NO; - weakSelf.opening = NO; + __strong typeof(weakSelf)strongSelf = weakSelf; + strongSelf.mediaPosition = 0; + strongSelf.bufferedDuration = 0; + strongSelf.mediaSyncTime = 0; + strongSelf.closing = NO; + strongSelf.opening = NO; }); dispatch_async(_renderingQueue, ^{ - [weakSelf.view clear]; + __strong typeof(weakSelf)strongSelf = weakSelf; + [strongSelf.view clear]; }); } @@ -129,19 +131,23 @@ - (void)open:(NSString *)url { __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ - if (weakSelf.opening) { + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf.opening) { return; } weakSelf.opening = YES; dispatch_async(dispatch_get_main_queue(), ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + NSError *error = nil; - if ([weakSelf.audio open:&error]) { - weakSelf.decoder.audioChannels = [weakSelf.audio channels]; - weakSelf.decoder.audioSampleRate = [weakSelf.audio sampleRate]; + if ([strongSelf.audio open:&error]) { + strongSelf.decoder.audioChannels = [weakSelf.audio channels]; + strongSelf.decoder.audioSampleRate = [weakSelf.audio sampleRate]; } else { - [weakSelf handleError:error]; + [strongSelf handleError:error]; } }); @@ -153,29 +159,32 @@ - (void)open:(NSString *)url { } dispatch_async(dispatch_get_main_queue(), ^{ - [weakSelf.view setCurrentEAGLContext]; + __strong typeof(weakSelf)strongSelf = weakSelf; - weakSelf.view.isYUV = [weakSelf.decoder isYUV]; - weakSelf.view.keepLastFrame = [weakSelf.decoder hasPicture] && ![weakSelf.decoder hasVideo]; - weakSelf.view.rotation = weakSelf.decoder.rotation; - weakSelf.view.contentSize = CGSizeMake([weakSelf.decoder videoWidth], [weakSelf.decoder videoHeight]); - weakSelf.view.contentMode = UIViewContentModeScaleAspectFit; + [strongSelf.view setCurrentEAGLContext]; - weakSelf.duration = weakSelf.decoder.duration; - weakSelf.metadata = weakSelf.decoder.metadata; - weakSelf.opening = NO; - weakSelf.buffering = NO; - weakSelf.playing = NO; - weakSelf.bufferedDuration = 0; - weakSelf.mediaPosition = 0; - weakSelf.mediaSyncTime = 0; - - weakSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [weakSelf readAudioFrame:data frames:frames channels:channels]; + strongSelf.view.isYUV = [weakSelf.decoder isYUV]; + strongSelf.view.keepLastFrame = [weakSelf.decoder hasPicture] && ![weakSelf.decoder hasVideo]; + strongSelf.view.rotation = weakSelf.decoder.rotation; + strongSelf.view.contentSize = CGSizeMake([weakSelf.decoder videoWidth], [weakSelf.decoder videoHeight]); + strongSelf.view.contentMode = UIViewContentModeScaleAspectFit; + + strongSelf.duration = weakSelf.decoder.duration; + strongSelf.metadata = weakSelf.decoder.metadata; + strongSelf.opening = NO; + strongSelf.buffering = NO; + strongSelf.playing = NO; + strongSelf.bufferedDuration = 0; + strongSelf.mediaPosition = 0; + strongSelf.mediaSyncTime = 0; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; }; - weakSelf.opened = YES; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:weakSelf]; + strongSelf.opened = YES; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; }); }); } @@ -183,9 +192,11 @@ - (void)open:(NSString *)url { - (void)close { [self pause]; - __strong typeof(self)strongSelf = self; + __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ + __strong typeof(self)strongSelf = self; + if (strongSelf.closing) { return; } @@ -195,6 +206,8 @@ - (void)close { [strongSelf.decoder close]; dispatch_async(dispatch_get_main_queue(), ^{ + __strong typeof(self)strongSelf = weakSelf; + NSArray *errors = nil; if ([strongSelf.audio close:&errors]) { [strongSelf clearVars]; @@ -218,7 +231,8 @@ - (void)play { __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ - [weakSelf runFrameReader]; + __strong typeof(weakSelf)strongSelf = weakSelf; + [strongSelf runFrameReader]; }); NSError *error = nil; diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 9e276d1..9fa4ef5 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -154,18 +154,18 @@ extension ViewController: DLGSimplePlayerViewControllerDelegate { // viewController.pause() print(") opened", viewController.url) - if #available(iOS 10.0, *), playCount < 5 { - var count = 0 - - Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { - self.playTest(count) - count += 1 - - if count > 5 { - $0.invalidate() - } - } - } +// if #available(iOS 10.0, *), playCount < 5 { +// var count = 0 +// +// Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { +// self.playTest(count) +// count += 1 +// +// if count > 5 { +// $0.invalidate() +// } +// } +// } } func viewController(_ viewController: DLGSimplePlayerViewController, didReceiveError error: Error) { print("didReceiveError", error) From b5c89faf8b75364f8bb80fed6da1db722a10c3a5 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 21 Mar 2019 09:48:15 +0900 Subject: [PATCH 097/215] Fixed: Made disable audio playing and stoping when application is in background. --- DLGPlayer/DLGPlayer.m | 8 ++++---- DLGPlayer/codec/DLGPlayerAudioManager.m | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 79504f7..ae46e2b 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -152,9 +152,9 @@ - (void)open:(NSString *)url { }); NSError *error = nil; - if (![weakSelf.decoder open:url error:&error]) { - weakSelf.opening = NO; - [weakSelf handleError:error]; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + [strongSelf handleError:error]; return; } @@ -195,7 +195,7 @@ - (void)close { __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ - __strong typeof(self)strongSelf = self; + __strong typeof(self)strongSelf = weakSelf; if (strongSelf.closing) { return; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 601fb53..d349254 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -12,6 +12,7 @@ #import #import #import +#import #define MAX_FRAME_SIZE 4096 #define MAX_CHANNEL 2 @@ -37,6 +38,7 @@ @interface DLGPlayerAudioManager () { float *_audioData; } @property (atomic) AudioUnit audioUnit; +@property (nonatomic, readonly) BOOL isBackground; @end @implementation DLGPlayerAudioManager @@ -87,6 +89,10 @@ - (void)setMute:(BOOL)mute { } } +- (BOOL)isBackground { + return [UIApplication sharedApplication].applicationState == UIApplicationStateBackground; +} + /* * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ @@ -253,6 +259,12 @@ - (BOOL)close:(NSArray **)errors { if (_closing) return NO; _closing = YES; + if (self.isBackground) { + _closing = NO; + [self unregisterNotifications]; + return YES; + } + NSMutableArray *errs = nil; if (errors != nil) errs = [NSMutableArray array]; @@ -325,6 +337,11 @@ - (BOOL)play:(NSError **)error { return _playing; } + if (self.isBackground) { + _playing = NO; + return _playing; + } + if (_opened && self.audioUnit != NULL) { OSStatus status = AudioOutputUnitStart(self.audioUnit); _playing = (status == noErr); From b742682939b0b35706430673795b0730159bde08 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 11 Apr 2019 21:03:29 +0900 Subject: [PATCH 098/215] Updated: Added defense code for bad access in memory. --- DLGPlayer/DLGPlayer.m | 53 ++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index ae46e2b..4e2d991 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -114,34 +114,44 @@ - (void)clearVars { dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - strongSelf.mediaPosition = 0; - strongSelf.bufferedDuration = 0; - strongSelf.mediaSyncTime = 0; - strongSelf.closing = NO; - strongSelf.opening = NO; + + if (strongSelf) { + strongSelf.mediaPosition = 0; + strongSelf.bufferedDuration = 0; + strongSelf.mediaSyncTime = 0; + strongSelf.closing = NO; + strongSelf.opening = NO; + } }); dispatch_async(_renderingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - [strongSelf.view clear]; + + if (strongSelf) { + [strongSelf.view clear]; + } }); } - (void)open:(NSString *)url { __weak typeof(self)weakSelf = self; - + dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - if (strongSelf.opening) { + if (strongSelf == nil || strongSelf.opening) { return; } - + weakSelf.opening = YES; dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(weakSelf)strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + NSError *error = nil; if ([strongSelf.audio open:&error]) { strongSelf.decoder.audioChannels = [weakSelf.audio channels]; @@ -161,6 +171,10 @@ - (void)open:(NSString *)url { dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(weakSelf)strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + [strongSelf.view setCurrentEAGLContext]; strongSelf.view.isYUV = [weakSelf.decoder isYUV]; @@ -177,7 +191,7 @@ - (void)open:(NSString *)url { strongSelf.bufferedDuration = 0; strongSelf.mediaPosition = 0; strongSelf.mediaSyncTime = 0; - + __weak typeof(strongSelf)ws = strongSelf; strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { [ws readAudioFrame:data frames:frames channels:channels]; @@ -197,7 +211,7 @@ - (void)close { dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; - if (strongSelf.closing) { + if (strongSelf == nil || strongSelf.closing) { return; } @@ -208,6 +222,10 @@ - (void)close { dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(self)strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + NSArray *errors = nil; if ([strongSelf.audio close:&errors]) { [strongSelf clearVars]; @@ -232,7 +250,10 @@ - (void)play { dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - [strongSelf runFrameReader]; + + if (strongSelf != nil) { + [strongSelf runFrameReader]; + } }); NSError *error = nil; @@ -360,7 +381,7 @@ - (void)readFrame { - (void)seekPositionInFrameReader { [self.decoder seek:self.requestSeekPosition]; - + { dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_FOREVER); [self.vframes removeAllObjects]; @@ -371,7 +392,7 @@ - (void)seekPositionInFrameReader { [self.aframes removeAllObjects]; dispatch_semaphore_signal(self.aFramesLock); } - + self.bufferedDuration = 0; self.requestSeek = NO; self.mediaSyncTime = 0; @@ -380,7 +401,7 @@ - (void)seekPositionInFrameReader { - (void)render { if (!self.playing) return; - + BOOL eof = self.decoder.isEOF; BOOL noframes = ((self.decoder.hasVideo && self.vframes.count <= 0) && (self.decoder.hasAudio && self.aframes.count <= 0)); @@ -488,7 +509,7 @@ - (double)syncTime { */ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)channels { if (!self.playing) return; - + while(frames > 0) { @autoreleasepool { if (self.playingAudioFrame == nil) { From 2667f4e2f67d35e5fc490b2aded634e83a63ee15 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sat, 13 Apr 2019 16:14:09 +0900 Subject: [PATCH 099/215] Updated: Bug fix. --- .../xcschemes/DLGPlayerDemo.xcscheme | 2 +- DLGPlayer/DLGPlayer.m | 24 +++---------------- DLGPlayer/codec/DLGPlayerAudioManager.m | 2 +- 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme index 9ea6c65..6f28cbe 100644 --- a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme +++ b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme @@ -85,7 +85,7 @@ *errors = nil; if ([strongSelf.audio close:&errors]) { [strongSelf clearVars]; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index d349254..e8625f4 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -128,7 +128,7 @@ - (BOOL)open:(NSError **)error { } AVAudioSessionRouteDescription *route = session.currentRoute; - if (route.outputs.count == 0) { + if (session.currentRoute.outputs.count == 0) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager andCode:DLGPlayerErrorCodeNoAudioOuput From 1f6f6d730d6992a302c02d8950fb48bcf6f202e0 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 15 Apr 2019 14:00:11 +0900 Subject: [PATCH 100/215] Updated: Added defense code. --- DLGPlayer/codec/DLGPlayerDecoder.m | 1 + 1 file changed, 1 insertion(+) diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index 63cdc7d..ed7a70a 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -159,6 +159,7 @@ - (BOOL)open:(NSString *)url error:(NSError **)error { astream = -1; if (acodectx != NULL) avcodec_free_context(&acodectx); if (aframe != NULL) av_frame_free(&aframe); + return; } ret = swr_init(aswrctx); From 3889ccef5f8017b46015ff7b80d30408e2db53b4 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 15 Apr 2019 15:55:38 +0900 Subject: [PATCH 101/215] Updated: Compile error solved. --- DLGPlayer/codec/DLGPlayerDecoder.m | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index ed7a70a..1e920cd 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -159,15 +159,14 @@ - (BOOL)open:(NSString *)url error:(NSError **)error { astream = -1; if (acodectx != NULL) avcodec_free_context(&acodectx); if (aframe != NULL) av_frame_free(&aframe); - return; - } - - ret = swr_init(aswrctx); - if (ret < 0) { - astream = -1; - if (aswrctx != NULL) swr_free(&aswrctx); - if (acodectx != NULL) avcodec_free_context(&acodectx); - if (aframe != NULL) av_frame_free(&aframe); + } else { + ret = swr_init(aswrctx); + if (ret < 0) { + astream = -1; + if (aswrctx != NULL) swr_free(&aswrctx); + if (acodectx != NULL) avcodec_free_context(&acodectx); + if (aframe != NULL) av_frame_free(&aframe); + } } } From a0ee0d631735d802021eed5856f02b14f2e79247 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 18 Apr 2019 22:29:51 +0900 Subject: [PATCH 102/215] Updated: Bug fix. --- DLGPlayer/DLGPlayer.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 0620a91..45fdf54 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -123,14 +123,6 @@ - (void)clearVars { strongSelf.opening = NO; } }); - - dispatch_async(_renderingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf) { - [strongSelf.view clear]; - } - }); } - (void)open:(NSString *)url { @@ -196,6 +188,14 @@ - (void)close { __weak typeof(self)weakSelf = self; + dispatch_async(_renderingQueue, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf) { + [strongSelf.view clear]; + } + }); + dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; From 6f365a5c05a461fb1ecbeee7281f70dc737a09f9 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 18 Apr 2019 22:40:25 +0900 Subject: [PATCH 103/215] Revert "Updated: Bug fix." This reverts commit a0ee0d631735d802021eed5856f02b14f2e79247. --- DLGPlayer/DLGPlayer.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 45fdf54..0620a91 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -123,6 +123,14 @@ - (void)clearVars { strongSelf.opening = NO; } }); + + dispatch_async(_renderingQueue, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf) { + [strongSelf.view clear]; + } + }); } - (void)open:(NSString *)url { @@ -188,14 +196,6 @@ - (void)close { __weak typeof(self)weakSelf = self; - dispatch_async(_renderingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf) { - [strongSelf.view clear]; - } - }); - dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; From 5f05a6542542a404c5dd54919d25d47746029b47 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 19 Apr 2019 23:45:00 +0900 Subject: [PATCH 104/215] Updated: Bug fix. --- DLGPlayer/DLGPlayer.m | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 0620a91..d0d4543 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -123,14 +123,6 @@ - (void)clearVars { strongSelf.opening = NO; } }); - - dispatch_async(_renderingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf) { - [strongSelf.view clear]; - } - }); } - (void)open:(NSString *)url { @@ -207,6 +199,10 @@ - (void)close { [strongSelf.decoder prepareClose]; [strongSelf.decoder close]; + dispatch_async(strongSelf.renderingQueue, ^{ + [strongSelf.view clear]; + }); + dispatch_async(dispatch_get_main_queue(), ^{ NSArray *errors = nil; if ([strongSelf.audio close:&errors]) { From 44d8ebf9c8999627698070a9b4ccef9d3ac25c98 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 24 Apr 2019 18:55:18 +0900 Subject: [PATCH 105/215] Updated: Change category to AVAudioSessionCategoryAmbient on audio session. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index e8625f4..3276687 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -100,7 +100,7 @@ - (BOOL)open:(NSError **)error { AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *rawError = nil; - if (![session setCategory:AVAudioSessionCategoryPlayback error:&rawError]) { + if (![session setCategory:AVAudioSessionCategoryAmbient error:&rawError]) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager andCode:DLGPlayerErrorCodeCannotSetAudioCategory From 40a475a3e87806fdd3b6918baa1cefdd0b43299a Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 25 Apr 2019 11:19:53 +0900 Subject: [PATCH 106/215] Updated: Set AVAudioSessionCategory by mute. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 3276687..ebf0697 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -77,11 +77,17 @@ - (void)dealloc { } } -#pragma mark - Added by KKH to mute sound. +#pragma mark - Added by Steve Kim. + +- (BOOL)isBackground { + return [UIApplication sharedApplication].applicationState == UIApplicationStateBackground; +} - (void)setMute:(BOOL)mute { _mute = mute; + [[AVAudioSession sharedInstance] setCategory:self.category error:nil]; + if (_mute) { [self pause]; } else { @@ -89,8 +95,8 @@ - (void)setMute:(BOOL)mute { } } -- (BOOL)isBackground { - return [UIApplication sharedApplication].applicationState == UIApplicationStateBackground; +- (AVAudioSessionCategory)category { + return _mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient } /* @@ -98,9 +104,9 @@ - (BOOL)isBackground { */ - (BOOL)open:(NSError **)error { AVAudioSession *session = [AVAudioSession sharedInstance]; - NSError *rawError = nil; - if (![session setCategory:AVAudioSessionCategoryAmbient error:&rawError]) { + + if (![session setCategory:self.category error:&rawError]) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager andCode:DLGPlayerErrorCodeCannotSetAudioCategory @@ -127,7 +133,6 @@ - (BOOL)open:(NSError **)error { return NO; } - AVAudioSessionRouteDescription *route = session.currentRoute; if (session.currentRoute.outputs.count == 0) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager From a521b8f9d6d6cb950816d307f2cf0c374e83ab3f Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 25 Apr 2019 11:22:41 +0900 Subject: [PATCH 107/215] Updated: Compile error solved. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index ebf0697..b621b21 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -96,7 +96,7 @@ - (void)setMute:(BOOL)mute { } - (AVAudioSessionCategory)category { - return _mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient + return _mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; } /* From 13802d608d2f5af838ea59ea5368dee3e67a806b Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 25 Apr 2019 17:58:56 +0900 Subject: [PATCH 108/215] Updated: AudioUnitUninitialize added in dealloc. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index b621b21..bf74e6f 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -71,7 +71,12 @@ - (void)dealloc { NSLog(@"DLGPlayerAudioManager dealloc"); [self unregisterNotifications]; - if (_audioData != NULL) { + if (self.audioUnit) { + AudioUnitUninitialize(self.audioUnit); + self.audioUnit = NULL; + } + + if (_audioData) { free(_audioData); _audioData = NULL; } From 74797d43045d8426168d4e9c7bc58672cafd2d99 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 26 Apr 2019 13:32:08 +0900 Subject: [PATCH 109/215] Updated: Logic for closing is changed. Updated: Test code is changed. --- DLGPlayer/DLGPlayer.m | 90 ++++++++++------- DLGPlayer/codec/DLGPlayerAudioManager.m | 31 ++---- DLGPlayerDemo/ViewController.swift | 122 ++++++++---------------- 3 files changed, 102 insertions(+), 141 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index d0d4543..220d776 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -110,19 +110,19 @@ - (void)clearVars { self.opened = NO; self.renderBegan = NO; - __weak typeof(self)weakSelf = self; - - dispatch_async(_processingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf) { - strongSelf.mediaPosition = 0; - strongSelf.bufferedDuration = 0; - strongSelf.mediaSyncTime = 0; - strongSelf.closing = NO; - strongSelf.opening = NO; - } - }); +// __weak typeof(self)weakSelf = self; + +// dispatch_async(_processingQueue, ^{ +// __strong typeof(weakSelf)strongSelf = weakSelf; + +// if (strongSelf) { + self.mediaPosition = 0; + self.bufferedDuration = 0; + self.mediaSyncTime = 0; + self.closing = NO; + self.opening = NO; +// } +// }); } - (void)open:(NSString *)url { @@ -184,37 +184,55 @@ - (void)open:(NSString *)url { } - (void)close { + if (self.closing) { + return; + } + [self pause]; + self.closing = YES; + __weak typeof(self)weakSelf = self; - dispatch_async(_processingQueue, ^{ - __strong typeof(self)strongSelf = weakSelf; - - if (!strongSelf || strongSelf.closing) { - return; - } - - strongSelf.closing = YES; - [strongSelf.decoder prepareClose]; - [strongSelf.decoder close]; + NSArray *errors = nil; + + void (^clear)(DLGPlayer *) = ^(DLGPlayer *player) { + [player.decoder prepareClose]; + [player.decoder close]; + [player clearVars]; - dispatch_async(strongSelf.renderingQueue, ^{ - [strongSelf.view clear]; + dispatch_async(player.renderingQueue, ^{ + [player.view clear]; }); - - dispatch_async(dispatch_get_main_queue(), ^{ - NSArray *errors = nil; - if ([strongSelf.audio close:&errors]) { - [strongSelf clearVars]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; - } else { - for (NSError *error in errors) { - [strongSelf handleError:error]; - } + }; + + if ([self.audio close:&errors]) { + dispatch_async(_processingQueue, ^{ + __strong typeof(self)strongSelf = weakSelf; + + if (strongSelf) { + clear(strongSelf); + + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; + }); } }); - }); + } else { + dispatch_async(_processingQueue, ^{ + __strong typeof(self)strongSelf = weakSelf; + + if (strongSelf) { + clear(strongSelf); + + dispatch_async(dispatch_get_main_queue(), ^{ + for (NSError *error in errors) { + [strongSelf handleError:error]; + } + }); + } + }); + } } - (void)play { diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index bf74e6f..cefe1f0 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -38,7 +38,6 @@ @interface DLGPlayerAudioManager () { float *_audioData; } @property (atomic) AudioUnit audioUnit; -@property (nonatomic, readonly) BOOL isBackground; @end @implementation DLGPlayerAudioManager @@ -71,11 +70,6 @@ - (void)dealloc { NSLog(@"DLGPlayerAudioManager dealloc"); [self unregisterNotifications]; - if (self.audioUnit) { - AudioUnitUninitialize(self.audioUnit); - self.audioUnit = NULL; - } - if (_audioData) { free(_audioData); _audioData = NULL; @@ -84,10 +78,6 @@ - (void)dealloc { #pragma mark - Added by Steve Kim. -- (BOOL)isBackground { - return [UIApplication sharedApplication].applicationState == UIApplicationStateBackground; -} - - (void)setMute:(BOOL)mute { _mute = mute; @@ -206,6 +196,8 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } + self.audioUnit = audioUnit; + AudioStreamBasicDescription streamDescr = {0}; UInt32 size = sizeof(AudioStreamBasicDescription); status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, @@ -256,8 +248,6 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } - self.audioUnit = audioUnit; - return YES; } @@ -269,18 +259,12 @@ - (BOOL)close:(NSArray **)errors { if (_closing) return NO; _closing = YES; - if (self.isBackground) { - _closing = NO; - [self unregisterNotifications]; - return YES; - } - NSMutableArray *errs = nil; if (errors != nil) errs = [NSMutableArray array]; BOOL closed = YES; - if (_opened && self.audioUnit != NULL) { + if (_opened && self.audioUnit) { [self pause]; [self unregisterNotifications]; @@ -330,7 +314,9 @@ - (BOOL)close:(NSArray **)errors { } } - if (closed) _opened = NO; + if (closed) { + _opened = NO; + } } _closing = NO; @@ -347,11 +333,6 @@ - (BOOL)play:(NSError **)error { return _playing; } - if (self.isBackground) { - _playing = NO; - return _playing; - } - if (_opened && self.audioUnit != NULL) { OSStatus status = AudioOutputUnitStart(self.audioUnit); _playing = (status == noErr); diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 9fa4ef5..9b67733 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -14,7 +14,7 @@ class ViewController: UIViewController { @IBOutlet private weak var muteButton: UIButton! @IBOutlet private weak var playOrPauseButton: UIButton! - private var timer: Timer? + private var isFirstViewAppearance = true private var playerViewController: DLGSimplePlayerViewController? { didSet { playerViewController.map { @@ -36,38 +36,18 @@ class ViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - playCount = 0 - play() - } - private func refresh() { - playerViewController?.close() - play() - - let rand1 = CGFloat(arc4random_uniform(2)) - let rand2 = CGFloat(arc4random_uniform(3) + 1) - let delay: TimeInterval = TimeInterval(rand1 + (1 / rand2)) - - DispatchQueue.main.asyncAfter(deadline: .now() + delay) { - self.refresh() + if isFirstViewAppearance { + startHardTest() } } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) -// refresh() - -// DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { -// if self.coverView == nil { -// self.navigationController?.popViewController(animated: true) -// } else { -// self.performSegue(withIdentifier: "NextView", sender: nil) -// } -// } + isFirstViewAppearance = false } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - stopTimer() playerViewController?.close() coverView?.isHidden = false } @@ -79,23 +59,46 @@ class ViewController: UIViewController { } } - private func play() { + // MARK: - RTMP Test + + private func playRTMP() { playerViewController?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" -// playerViewController?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" playerViewController?.open() } - private func startTimer() { - stopTimer() - timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(timerCompletion), userInfo: nil, repeats: true) + + // MARK: - Hard Test + + private let hardTestCount: Int = 100 + private var playCount: Int = 0 + private func startHardTest() { + if #available(iOS 10.0, *), playCount < hardTestCount { + var count = 0 + + Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { + self.playTest(count) + count += 1 + + if count > self.hardTestCount { + $0.invalidate() + } + } + } } - private func stopTimer() { - timer?.invalidate() - timer = nil + private func playTest(_ count: Int) { + let url = count % 2 == 0 ? + "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : + "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" + + playerViewController?.close() + + print("[playTest] ------------------------------------------------------------------------------------") + print("[playTest] will open -> ", url) + playerViewController?.url = url + playerViewController?.open() + print("[playTest] opening -> ", playerViewController?.url) } - @objc private func timerCompletion() { - // print("player.position", playerViewController.player.position) - } + // MARK: - Private Selectors @IBAction private func captureButtonClicked() { playerViewController?.player.snapshot() @@ -115,7 +118,7 @@ class ViewController: UIViewController { if playerViewController?.status == .paused { playerViewController?.play() } else { - play() + playRTMP() } } else { playerViewController?.pause() @@ -123,66 +126,25 @@ class ViewController: UIViewController { } @IBAction private func refreshButtonClicked(_ sender: UIButton) { playerViewController?.close() - play() + playRTMP() } @IBAction private func valueChanged(_ sender: UISlider) { playerViewController?.player.brightness = sender.value } - - private var playCount: Int = 0 } extension ViewController: DLGSimplePlayerViewControllerDelegate { - - private func playTest(_ count: Int) { - let url = count % 2 == 0 ? - "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : - "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" - - playerViewController?.close() - - print(") ------------------------------------------------------------------------------------") - print(") open", url) - playerViewController?.url = url - playerViewController?.open() - print(") opening", playerViewController?.url) - } - - func didBeginRender(in viewController: DLGSimplePlayerViewController) { + print("didBeginRender -> ", viewController.url) coverView?.isHidden = true -// viewController.pause() - print(") opened", viewController.url) - -// if #available(iOS 10.0, *), playCount < 5 { -// var count = 0 -// -// Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { -// self.playTest(count) -// count += 1 -// -// if count > 5 { -// $0.invalidate() -// } -// } -// } } func viewController(_ viewController: DLGSimplePlayerViewController, didReceiveError error: Error) { - print("didReceiveError", error) + print("didReceiveError -> ", error) } func viewController(_ viewController: DLGSimplePlayerViewController, didChange status: DLGPlayerStatus) { // print("didChange", viewController.hash, status.stringValue) playOrPauseButton.isSelected = viewController.controlStatus.playing muteButton.isSelected = !viewController.isMute - - switch status { - case .opened: - startTimer() - case .paused, - .closed: - stopTimer() - default: () - } } } From 98d36dae36e48f80f92e0e31b5dff1d527e4adbb Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 1 May 2019 23:19:31 +0900 Subject: [PATCH 110/215] Updated: Remove comments. --- DLGPlayer/DLGPlayer.m | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 220d776..9943ff1 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -103,26 +103,18 @@ - (void)initAudio { - (void)clearVars { [self.vframes removeAllObjects]; [self.aframes removeAllObjects]; + self.playingAudioFrame = nil; self.playingAudioFrameDataPosition = 0; self.buffering = NO; self.playing = NO; self.opened = NO; self.renderBegan = NO; - -// __weak typeof(self)weakSelf = self; - -// dispatch_async(_processingQueue, ^{ -// __strong typeof(weakSelf)strongSelf = weakSelf; - -// if (strongSelf) { - self.mediaPosition = 0; - self.bufferedDuration = 0; - self.mediaSyncTime = 0; - self.closing = NO; - self.opening = NO; -// } -// }); + self.mediaPosition = 0; + self.bufferedDuration = 0; + self.mediaSyncTime = 0; + self.closing = NO; + self.opening = NO; } - (void)open:(NSString *)url { @@ -188,10 +180,6 @@ - (void)close { return; } - [self pause]; - - self.closing = YES; - __weak typeof(self)weakSelf = self; NSArray *errors = nil; @@ -206,6 +194,8 @@ - (void)close { }); }; + self.closing = YES; + if ([self.audio close:&errors]) { dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; From 63bc2519dd2cae7177c1a846521bd66150f8bd24 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 1 May 2019 23:43:10 +0900 Subject: [PATCH 111/215] Updated: Crash solving. --- DLGPlayer/DLGPlayer.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 9943ff1..6cd0084 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -200,7 +200,7 @@ - (void)close { dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; - if (strongSelf) { + if (strongSelf && !strongSelf.closing) { clear(strongSelf); dispatch_async(dispatch_get_main_queue(), ^{ @@ -212,7 +212,7 @@ - (void)close { dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; - if (strongSelf) { + if (strongSelf && !strongSelf.closing) { clear(strongSelf); dispatch_async(dispatch_get_main_queue(), ^{ From 0969aa6072ee41ac8330aeab35fbe3390761e949 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 00:04:23 +0900 Subject: [PATCH 112/215] Updated: Crash solving. --- DLGPlayer/DLGPlayer.m | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 6cd0084..9814bb0 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -180,8 +180,6 @@ - (void)close { return; } - __weak typeof(self)weakSelf = self; - NSArray *errors = nil; void (^clear)(DLGPlayer *) = ^(DLGPlayer *player) { @@ -194,13 +192,13 @@ - (void)close { }); }; + __strong typeof(self)strongSelf = self; + self.closing = YES; if ([self.audio close:&errors]) { dispatch_async(_processingQueue, ^{ - __strong typeof(self)strongSelf = weakSelf; - - if (strongSelf && !strongSelf.closing) { + if (strongSelf) { clear(strongSelf); dispatch_async(dispatch_get_main_queue(), ^{ @@ -210,9 +208,7 @@ - (void)close { }); } else { dispatch_async(_processingQueue, ^{ - __strong typeof(self)strongSelf = weakSelf; - - if (strongSelf && !strongSelf.closing) { + if (strongSelf) { clear(strongSelf); dispatch_async(dispatch_get_main_queue(), ^{ From 507557f0195c41776faab404224dd104b07b3ffe Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 00:14:06 +0900 Subject: [PATCH 113/215] Updated: Crash solving. --- DLGPlayer/DLGPlayer.m | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 9814bb0..6b8f986 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -180,8 +180,6 @@ - (void)close { return; } - NSArray *errors = nil; - void (^clear)(DLGPlayer *) = ^(DLGPlayer *player) { [player.decoder prepareClose]; [player.decoder close]; @@ -192,33 +190,30 @@ - (void)close { }); }; - __strong typeof(self)strongSelf = self; - - self.closing = YES; + __weak typeof(self)weakSelf = self; - if ([self.audio close:&errors]) { - dispatch_async(_processingQueue, ^{ - if (strongSelf) { - clear(strongSelf); + dispatch_async(_processingQueue, ^{ + __strong typeof(self)strongSelf = weakSelf; + + if (strongSelf && !strongSelf.closing) { + strongSelf.closing = YES; + + dispatch_async(dispatch_get_main_queue(), ^{ + NSArray *errors = nil; - dispatch_async(dispatch_get_main_queue(), ^{ + if ([self.audio close:&errors]) { + clear(strongSelf); [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; - }); - } - }); - } else { - dispatch_async(_processingQueue, ^{ - if (strongSelf) { - clear(strongSelf); - - dispatch_async(dispatch_get_main_queue(), ^{ + } else { + clear(strongSelf); + for (NSError *error in errors) { [strongSelf handleError:error]; } - }); - } - }); - } + } + }); + } + }); } - (void)play { From 932e8ecf8d3216a138d2488dd76360c6da1b5658 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 00:30:08 +0900 Subject: [PATCH 114/215] Updated: Crash solving. --- DLGPlayer/DLGPlayer.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 6b8f986..70359b7 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -118,10 +118,12 @@ - (void)clearVars { } - (void)open:(NSString *)url { + NSLog(@"open") __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; + NSLog(@"open strongSelf -> %d", strongSelf != nil) if (!strongSelf || strongSelf.opening) { return; @@ -176,10 +178,7 @@ - (void)open:(NSString *)url { } - (void)close { - if (self.closing) { - return; - } - + NSLog(@"close") void (^clear)(DLGPlayer *) = ^(DLGPlayer *player) { [player.decoder prepareClose]; [player.decoder close]; @@ -194,6 +193,7 @@ - (void)close { dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; + NSLog(@"close strongSelf -> %d", strongSelf != nil) if (strongSelf && !strongSelf.closing) { strongSelf.closing = YES; From b075784e793628ffea053798feab7fbc119a9d00 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 00:42:52 +0900 Subject: [PATCH 115/215] Updated: Crash solving. --- DLGPlayer/DLGPlayer.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 70359b7..e642879 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -118,12 +118,12 @@ - (void)clearVars { } - (void)open:(NSString *)url { - NSLog(@"open") + NSLog(@"open"); __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - NSLog(@"open strongSelf -> %d", strongSelf != nil) + NSLog(@"open strongSelf -> %d", strongSelf != nil); if (!strongSelf || strongSelf.opening) { return; @@ -178,7 +178,7 @@ - (void)open:(NSString *)url { } - (void)close { - NSLog(@"close") + NSLog(@"close"); void (^clear)(DLGPlayer *) = ^(DLGPlayer *player) { [player.decoder prepareClose]; [player.decoder close]; @@ -193,7 +193,7 @@ - (void)close { dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; - NSLog(@"close strongSelf -> %d", strongSelf != nil) + NSLog(@"close strongSelf -> %d", strongSelf != nil); if (strongSelf && !strongSelf.closing) { strongSelf.closing = YES; From 2aacc38dc10311c0b5f872509fa86abd25d23b70 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 01:03:37 +0900 Subject: [PATCH 116/215] Updated: Crash solving. --- DLGPlayer/DLGPlayer.m | 85 ++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index e642879..7dc0d49 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -118,12 +118,10 @@ - (void)clearVars { } - (void)open:(NSString *)url { - NSLog(@"open"); __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - NSLog(@"open strongSelf -> %d", strongSelf != nil); if (!strongSelf || strongSelf.opening) { return; @@ -178,65 +176,68 @@ - (void)open:(NSString *)url { } - (void)close { - NSLog(@"close"); - void (^clear)(DLGPlayer *) = ^(DLGPlayer *player) { - [player.decoder prepareClose]; - [player.decoder close]; - [player clearVars]; - - dispatch_async(player.renderingQueue, ^{ - [player.view clear]; - }); - }; - __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; - NSLog(@"close strongSelf -> %d", strongSelf != nil); - if (strongSelf && !strongSelf.closing) { - strongSelf.closing = YES; + if (!strongSelf || strongSelf.opening) { + return; + } + + strongSelf.closing = YES; + + dispatch_async(dispatch_get_main_queue(), ^{ + void (^clear)(void) = ^(void) { + [strongSelf.decoder prepareClose]; + [strongSelf.decoder close]; + [strongSelf clearVars]; + + dispatch_async(strongSelf.renderingQueue, ^{ + [strongSelf.view clear]; + }); + }; - dispatch_async(dispatch_get_main_queue(), ^{ - NSArray *errors = nil; + NSArray *errors = nil; + + if ([self.audio close:&errors]) { + clear(); + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; + } else { + clear(); - if ([self.audio close:&errors]) { - clear(strongSelf); - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; - } else { - clear(strongSelf); - - for (NSError *error in errors) { - [strongSelf handleError:error]; - } + for (NSError *error in errors) { + [strongSelf handleError:error]; } - }); - } + } + }); }); } - (void)play { - if (!self.opened || self.playing) return; - - self.playing = YES; - - [self render]; - __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - if (strongSelf != nil) { - [strongSelf runFrameReader]; + if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { + return; } + + strongSelf.playing = YES; + + dispatch_async(dispatch_get_main_queue(), ^{ + [strongSelf render]; + + NSError *error = nil; + + if (![strongSelf.audio play:&error]) { + [strongSelf handleError:error]; + } + }); + + [strongSelf runFrameReader]; }); - - NSError *error = nil; - if (![self.audio play:&error]) { - [self handleError:error]; - } } - (void)pause { From 9fd507f262fde25eeb475d1e834192fe47a4235d Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 01:30:36 +0900 Subject: [PATCH 117/215] Updated: Crash solving. --- DLGPlayer/DLGPlayer.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 7dc0d49..3622518 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -118,6 +118,7 @@ - (void)clearVars { } - (void)open:(NSString *)url { + NSLog(@"open"); __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ @@ -127,6 +128,7 @@ - (void)open:(NSString *)url { return; } + NSLog(@"opening"); strongSelf.opening = YES; dispatch_async(dispatch_get_main_queue(), ^{ @@ -176,15 +178,17 @@ - (void)open:(NSString *)url { } - (void)close { + NSLog(@"close"); __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; - if (!strongSelf || strongSelf.opening) { + if (!strongSelf || strongSelf.closing) { return; } + NSLog(@"closing"); strongSelf.closing = YES; dispatch_async(dispatch_get_main_queue(), ^{ @@ -200,7 +204,7 @@ - (void)close { NSArray *errors = nil; - if ([self.audio close:&errors]) { + if ([strongSelf.audio close:&errors]) { clear(); [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; } else { From ca4f9562421d88665b31e29ad75958fb64a356bc Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 01:46:44 +0900 Subject: [PATCH 118/215] Updated: Crash solving. --- DLGPlayer/DLGPlayer.m | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 3622518..3f33af9 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -184,6 +184,8 @@ - (void)close { dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; + NSLog(@"strongSelf -> %d", strongSelf != nil); + if (!strongSelf || strongSelf.closing) { return; } @@ -191,10 +193,11 @@ - (void)close { NSLog(@"closing"); strongSelf.closing = YES; + [strongSelf.decoder prepareClose]; + [strongSelf.decoder close]; + dispatch_async(dispatch_get_main_queue(), ^{ void (^clear)(void) = ^(void) { - [strongSelf.decoder prepareClose]; - [strongSelf.decoder close]; [strongSelf clearVars]; dispatch_async(strongSelf.renderingQueue, ^{ From 533e42eac98306b2d414d09b0850dee4d5eac6f3 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 12:06:19 +0900 Subject: [PATCH 119/215] Updated: Crash solved. --- DLGPlayer/DLGPlayer.m | 69 ++++++++++++------------- DLGPlayer/codec/DLGPlayerAudioManager.m | 5 +- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 3f33af9..99a672d 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -118,7 +118,10 @@ - (void)clearVars { } - (void)open:(NSString *)url { - NSLog(@"open"); + if (self.opening) { + return; + } + __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ @@ -128,20 +131,16 @@ - (void)open:(NSString *)url { return; } - NSLog(@"opening"); strongSelf.opening = YES; - dispatch_async(dispatch_get_main_queue(), ^{ - NSError *error = nil; - if ([strongSelf.audio open:&error]) { - strongSelf.decoder.audioChannels = [weakSelf.audio channels]; - strongSelf.decoder.audioSampleRate = [weakSelf.audio sampleRate]; - } else { - [strongSelf handleError:error]; - } - }); - NSError *error = nil; + if ([strongSelf.audio open:&error]) { + strongSelf.decoder.audioChannels = [weakSelf.audio channels]; + strongSelf.decoder.audioSampleRate = [weakSelf.audio sampleRate]; + } else { + [strongSelf handleError:error]; + } + if (![strongSelf.decoder open:url error:&error]) { strongSelf.opening = NO; [strongSelf handleError:error]; @@ -172,52 +171,52 @@ - (void)open:(NSString *)url { }; strongSelf.opened = YES; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; }); }); } - (void)close { - NSLog(@"close"); + if (self.closing || !self.opened) { + return; + } + + [self pause]; + [self.decoder prepareClose]; + __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; - NSLog(@"strongSelf -> %d", strongSelf != nil); - - if (!strongSelf || strongSelf.closing) { + if (!strongSelf || strongSelf.closing || !strongSelf.opened) { return; } - NSLog(@"closing"); strongSelf.closing = YES; - [strongSelf.decoder prepareClose]; [strongSelf.decoder close]; - dispatch_async(dispatch_get_main_queue(), ^{ - void (^clear)(void) = ^(void) { - [strongSelf clearVars]; - - dispatch_async(strongSelf.renderingQueue, ^{ - [strongSelf.view clear]; - }); - }; - - NSArray *errors = nil; + dispatch_sync(strongSelf.renderingQueue, ^{ + [strongSelf.view clear]; + }); + + NSArray *errors = nil; + + if ([strongSelf.audio close:&errors]) { + [strongSelf clearVars]; - if ([strongSelf.audio close:&errors]) { - clear(); + dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; - } else { - clear(); - + }); + } else { + dispatch_async(dispatch_get_main_queue(), ^{ for (NSError *error in errors) { [strongSelf handleError:error]; } - } - }); + }); + } }); } diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index cefe1f0..3ea0150 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -256,7 +256,10 @@ - (BOOL)close { } - (BOOL)close:(NSArray **)errors { - if (_closing) return NO; + if (_closing) { + return NO; + } + _closing = YES; NSMutableArray *errs = nil; From 747485a1538511350f25e2611403b9ff11b4ad61 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 13:31:02 +0900 Subject: [PATCH 120/215] Updated: Bug fix. --- DLGPlayer/DLGPlayer.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 99a672d..aae5bbe 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -178,7 +178,7 @@ - (void)open:(NSString *)url { } - (void)close { - if (self.closing || !self.opened) { + if (self.closing) { return; } @@ -190,7 +190,7 @@ - (void)close { dispatch_async(_processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; - if (!strongSelf || strongSelf.closing || !strongSelf.opened) { + if (!strongSelf || strongSelf.closing) { return; } From eda920d23bba9eb2b88f1fc105b9352690655d08 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 2 May 2019 23:32:30 +0900 Subject: [PATCH 121/215] Updated: Logic for guard added. --- DLGPlayer/DLGPlayer.m | 4 ++++ DLGPlayerDemo/ViewController.swift | 21 ++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index aae5bbe..79504bb 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -221,6 +221,10 @@ - (void)close { } - (void)play { + if (!self.opened || self.playing || self.closing) { + return; + } + __weak typeof(self)weakSelf = self; dispatch_async(_processingQueue, ^{ diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 9b67733..dc8655e 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -29,6 +29,13 @@ class ViewController: UIViewController { } } + deinit { + + + print("deinit") + + } + override func viewDidLoad() { super.viewDidLoad() @@ -36,8 +43,8 @@ class ViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - if isFirstViewAppearance { - startHardTest() + if isFirstViewAppearance, (navigationController?.viewControllers.count ?? 0) > 1 { + playRTMP() } } override func viewDidAppear(_ animated: Bool) { @@ -68,14 +75,14 @@ class ViewController: UIViewController { // MARK: - Hard Test - private let hardTestCount: Int = 100 + private let hardTestCount: Int = 10 private var playCount: Int = 0 private func startHardTest() { if #available(iOS 10.0, *), playCount < hardTestCount { var count = 0 Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { - self.playTest(count) + self.playTest(0) count += 1 if count > self.hardTestCount { @@ -91,11 +98,11 @@ class ViewController: UIViewController { playerViewController?.close() - print("[playTest] ------------------------------------------------------------------------------------") - print("[playTest] will open -> ", url) +// print("[playTest] ------------------------------------------------------------------------------------") +// print("[playTest] will open -> ", url) playerViewController?.url = url playerViewController?.open() - print("[playTest] opening -> ", playerViewController?.url) +// print("[playTest] opening -> ", playerViewController?.url) } // MARK: - Private Selectors From 21818aa1348f8e0a253e776f20f37884579ccad1 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 21 May 2019 10:20:11 +0900 Subject: [PATCH 122/215] Updated: Change thread to render. --- DLGPlayer/DLGPlayer.m | 5 +---- DLGPlayerDemo/Base.lproj/Main.storyboard | 12 +++++++++++- DLGPlayerDemo/ViewController.swift | 17 ++++++++++++++--- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 79504bb..f46a78d 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -197,10 +197,7 @@ - (void)close { strongSelf.closing = YES; [strongSelf.decoder close]; - - dispatch_sync(strongSelf.renderingQueue, ^{ - [strongSelf.view clear]; - }); + [strongSelf.view clear]; NSArray *errors = nil; diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index 793aa34..5213f4c 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -24,7 +24,7 @@ - + @@ -91,6 +91,14 @@ + @@ -180,19 +180,19 @@ - + + + @@ -241,6 +249,7 @@ + diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index 4c89299..20d4ddd 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -44,9 +44,9 @@ class ViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - if isFirstViewAppearance { - playDownload() - } +// if isFirstViewAppearance { + playRTMP() +// } } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) @@ -119,6 +119,9 @@ class ViewController: UIViewController { self?.view.addSubview($0) } } + @IBAction private func closeButtonClicked() { + dismiss(animated: true) + } @IBAction private func leftBarButtonItemClicked() { dismiss(animated: true) } From 60968cee22f797ed5ff194a876551e542786bc56 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 31 May 2019 11:07:20 +0900 Subject: [PATCH 124/215] Updated: examples. --- DLGPlayer.xcodeproj/project.pbxproj | 16 +- DLGPlayerDemo/Base.lproj/Main.storyboard | 8 +- ...troller.swift => RootViewController.swift} | 22 +-- DLGPlayerDemo/SecondViewController.swift | 167 ++++++++++++++++++ 4 files changed, 189 insertions(+), 24 deletions(-) rename DLGPlayerDemo/{ViewController.swift => RootViewController.swift} (90%) create mode 100644 DLGPlayerDemo/SecondViewController.swift diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index b7b4c87..74f6552 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 23241CAE22A0B45400871C58 /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23241CAD22A0B45400871C58 /* SecondViewController.swift */; }; 235409B421BA05A100533B9B /* DLGPlayerDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291821B810B40012243A /* DLGPlayerDecoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; 235409B521BA05A400533B9B /* DLGPlayerAudioManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC291921B810B40012243A /* DLGPlayerAudioManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 235409B621BA05A900533B9B /* DLGPlayerDef.h in Headers */ = {isa = PBXBuildFile; fileRef = 23DC293621B810B50012243A /* DLGPlayerDef.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -22,7 +23,7 @@ 237758B421CA5658000B6B7F /* DLGPlayerControlStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 237758B221CA5658000B6B7F /* DLGPlayerControlStatus.h */; settings = {ATTRIBUTES = (Public, ); }; }; 237758B521CA5658000B6B7F /* DLGPlayerControlStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 237758B321CA5658000B6B7F /* DLGPlayerControlStatus.m */; }; 239BC97121C234CF00DEEC73 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 239BC97021C234CF00DEEC73 /* AppDelegate.swift */; }; - 239BC97321C234CF00DEEC73 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 239BC97221C234CF00DEEC73 /* ViewController.swift */; }; + 239BC97321C234CF00DEEC73 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 239BC97221C234CF00DEEC73 /* RootViewController.swift */; }; 239BC97621C234CF00DEEC73 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 239BC97421C234CF00DEEC73 /* Main.storyboard */; }; 239BC97821C234D000DEEC73 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 239BC97721C234D000DEEC73 /* Assets.xcassets */; }; 239BC97B21C234D000DEEC73 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 239BC97921C234D000DEEC73 /* LaunchScreen.storyboard */; }; @@ -63,13 +64,14 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 23241CAD22A0B45400871C58 /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = ""; }; 235409C421BA177A00533B9B /* DLGSimplePlayerViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DLGSimplePlayerViewController.h; sourceTree = ""; }; 235409C521BA177A00533B9B /* DLGSimplePlayerViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DLGSimplePlayerViewController.m; sourceTree = ""; }; 237758B221CA5658000B6B7F /* DLGPlayerControlStatus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DLGPlayerControlStatus.h; sourceTree = ""; }; 237758B321CA5658000B6B7F /* DLGPlayerControlStatus.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DLGPlayerControlStatus.m; sourceTree = ""; }; 239BC96E21C234CF00DEEC73 /* DLGPlayerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DLGPlayerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 239BC97021C234CF00DEEC73 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 239BC97221C234CF00DEEC73 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 239BC97221C234CF00DEEC73 /* RootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; }; 239BC97521C234CF00DEEC73 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 239BC97721C234D000DEEC73 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 239BC97A21C234D000DEEC73 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; @@ -142,12 +144,13 @@ 239BC96F21C234CF00DEEC73 /* DLGPlayerDemo */ = { isa = PBXGroup; children = ( + 239BC97C21C234D000DEEC73 /* Info.plist */, 239BC97021C234CF00DEEC73 /* AppDelegate.swift */, - 239BC97221C234CF00DEEC73 /* ViewController.swift */, - 239BC97421C234CF00DEEC73 /* Main.storyboard */, + 239BC97221C234CF00DEEC73 /* RootViewController.swift */, + 23241CAD22A0B45400871C58 /* SecondViewController.swift */, 239BC97721C234D000DEEC73 /* Assets.xcassets */, 239BC97921C234D000DEEC73 /* LaunchScreen.storyboard */, - 239BC97C21C234D000DEEC73 /* Info.plist */, + 239BC97421C234CF00DEEC73 /* Main.storyboard */, ); path = DLGPlayerDemo; sourceTree = ""; @@ -425,7 +428,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 239BC97321C234CF00DEEC73 /* ViewController.swift in Sources */, + 23241CAE22A0B45400871C58 /* SecondViewController.swift in Sources */, + 239BC97321C234CF00DEEC73 /* RootViewController.swift in Sources */, 239BC97121C234CF00DEEC73 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index 6b9f670..d230beb 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -26,10 +26,10 @@ - + - + @@ -162,10 +162,10 @@ - + - + diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/RootViewController.swift similarity index 90% rename from DLGPlayerDemo/ViewController.swift rename to DLGPlayerDemo/RootViewController.swift index 20d4ddd..57ccc57 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -1,5 +1,5 @@ // -// ViewController.swift +// RootViewController.swift // DLGPlayerDemo // // Created by KWANG HYOUN KIM on 07/12/2018. @@ -8,7 +8,7 @@ import UIKit -class ViewController: UIViewController { +class RootViewController: UIViewController { @IBOutlet private weak var coverView: UIView? @IBOutlet private weak var muteButton: UIButton! @@ -20,7 +20,7 @@ class ViewController: UIViewController { playerViewController.map { $0.delegate = self $0.isAutoplay = true - // $0.isMute = true + $0.isMute = true $0.preventFromScreenLock = true $0.restorePlayAfterAppEnterForeground = true $0.minBufferDuration = 0 @@ -74,7 +74,7 @@ class ViewController: UIViewController { playerViewController?.open() } private func playRTMP() { - playerViewController?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" + playerViewController?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" playerViewController?.open() } @@ -98,7 +98,7 @@ class ViewController: UIViewController { } private func playTest(_ count: Int) { let url = count % 2 == 0 ? - "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : + "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" playerViewController?.close() @@ -119,12 +119,6 @@ class ViewController: UIViewController { self?.view.addSubview($0) } } - @IBAction private func closeButtonClicked() { - dismiss(animated: true) - } - @IBAction private func leftBarButtonItemClicked() { - dismiss(animated: true) - } @IBAction private func muteButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected playerViewController?.isMute = !sender.isSelected @@ -154,13 +148,13 @@ class ViewController: UIViewController { } } -extension ViewController: DLGSimplePlayerViewControllerDelegate { +extension RootViewController: DLGSimplePlayerViewControllerDelegate { func didBeginRender(in viewController: DLGSimplePlayerViewController) { - print("didBeginRender -> ", viewController.url) +// print("didBeginRender -> ", viewController.url) coverView?.isHidden = true } func viewController(_ viewController: DLGSimplePlayerViewController, didReceiveError error: Error) { - print("didReceiveError -> ", error) +// print("didReceiveError -> ", error) } func viewController(_ viewController: DLGSimplePlayerViewController, didChange status: DLGPlayerStatus) { // print("didChange", viewController.hash, status.stringValue) diff --git a/DLGPlayerDemo/SecondViewController.swift b/DLGPlayerDemo/SecondViewController.swift new file mode 100644 index 0000000..b8ad39a --- /dev/null +++ b/DLGPlayerDemo/SecondViewController.swift @@ -0,0 +1,167 @@ +// +// SecondViewController.swift +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 31/05/2019. +// Copyright © 2019 KWANG HYOUN KIM. All rights reserved. +// + +import UIKit + +class SecondViewController: UIViewController { + + @IBOutlet private weak var muteButton: UIButton! + @IBOutlet private weak var playOrPauseButton: UIButton! + + private var isFirstViewAppearance = true + private var playerViewController: DLGSimplePlayerViewController? { + didSet { + playerViewController.map { + $0.delegate = self + $0.isAutoplay = true + $0.isMute = false + $0.preventFromScreenLock = true + $0.restorePlayAfterAppEnterForeground = true + $0.minBufferDuration = 0 + $0.maxBufferDuration = 2 + } + } + } + + deinit { + + + print("deinit") + + } + + override func viewDidLoad() { + super.viewDidLoad() + + // navigationItem.leftBarButtonItem = .init(title: "close", style: .plain, target: self, action: #selector(leftBarButtonItemClicked)) + } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // if isFirstViewAppearance { + playRTMP() + // } + } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + isFirstViewAppearance = false + } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + + playerViewController?.close() + } + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + switch segue.destination { + case let vc as DLGSimplePlayerViewController: + playerViewController = vc + default: () + } + } + + // MARK: - Play Test + + private func playDownload() { + playerViewController?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" + playerViewController?.open() + } + private func playRTMP() { + playerViewController?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" + playerViewController?.open() + } + + // MARK: - Hard Test + + private let hardTestCount: Int = 10 + private var playCount: Int = 0 + private func startHardTest() { + if #available(iOS 10.0, *), playCount < hardTestCount { + var count = 0 + + Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { + self.playTest(0) + count += 1 + + if count > self.hardTestCount { + $0.invalidate() + } + } + } + } + private func playTest(_ count: Int) { + let url = count % 2 == 0 ? + "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : + "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" + + playerViewController?.close() + + // print("[playTest] ------------------------------------------------------------------------------------") + // print("[playTest] will open -> ", url) + playerViewController?.url = url + playerViewController?.open() + // print("[playTest] opening -> ", playerViewController?.url) + } + + // MARK: - Private Selectors + + @IBAction private func captureButtonClicked() { + playerViewController?.player.snapshot() + .map { UIImageView(image: $0) } + .map { [weak self] in + self?.view.addSubview($0) + } + } + @IBAction private func closeButtonClicked() { + dismiss(animated: true) + } + @IBAction private func leftBarButtonItemClicked() { + dismiss(animated: true) + } + @IBAction private func muteButtonClicked(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + playerViewController?.isMute = !sender.isSelected + } + @IBAction private func playOrPauseButtonClicked(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + + if sender.isSelected { + if playerViewController?.status == .paused { + playerViewController?.play() + } else { + playRTMP() + } + } else { + playerViewController?.pause() + } + } + @IBAction private func refreshButtonClicked(_ sender: UIButton) { + playerViewController?.close() + playRTMP() + } + @IBAction private func stopButtonClicked() { + playerViewController?.close() + } + @IBAction private func valueChanged(_ sender: UISlider) { + playerViewController?.player.brightness = sender.value + } +} + +extension SecondViewController: DLGSimplePlayerViewControllerDelegate { + func didBeginRender(in viewController: DLGSimplePlayerViewController) { +// print("didBeginRender -> ", viewController.url) + } + func viewController(_ viewController: DLGSimplePlayerViewController, didReceiveError error: Error) { +// print("didReceiveError -> ", error) + } + func viewController(_ viewController: DLGSimplePlayerViewController, didChange status: DLGPlayerStatus) { + // print("didChange", viewController.hash, status.stringValue) + playOrPauseButton.isSelected = viewController.controlStatus.playing + muteButton.isSelected = !viewController.isMute + } +} From c513608be7eaf29dbe3adf4c5878e23ccecbf31d Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 31 May 2019 13:40:50 +0900 Subject: [PATCH 125/215] Fixed: a bug when playing multiple players. --- DLGPlayer/DLGPlayer.h | 2 -- DLGPlayer/DLGPlayer.m | 25 ++++++++++++++++++------- DLGPlayer/codec/DLGPlayerAudioManager.m | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 6209661..e5fd21b 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -35,8 +35,6 @@ typedef void (^onPauseComplete)(void); @property (nonatomic) BOOL playing; @property (nonatomic) BOOL buffering; @property (nonatomic) float brightness; -@property (nonatomic, strong) dispatch_queue_t processingQueue; -@property (nonatomic, strong) dispatch_queue_t renderingQueue; @property (nonatomic, strong) NSDictionary *metadata; @property (nonatomic, readonly) DLGPlayerAudioManager *audio; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 7f7a5f7..4120088 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -41,6 +41,9 @@ @interface DLGPlayer () @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; @end +static dispatch_queue_t processingQueue; +static dispatch_queue_t renderingQueue; + @implementation DLGPlayer - (id)init { @@ -83,8 +86,13 @@ - (void)initVars { _requestSeekPosition = 0; _aFramesLock = dispatch_semaphore_create(1); _vFramesLock = dispatch_semaphore_create(1); - _renderingQueue = dispatch_queue_create("DLGPlayer.renderingQueue", DISPATCH_QUEUE_SERIAL); - _processingQueue = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); + + if (!processingQueue) { + processingQueue = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); + } + if (!renderingQueue) { + renderingQueue = dispatch_queue_create("DLGPlayer.renderingQueue", DISPATCH_QUEUE_SERIAL); + } } - (void)initView { @@ -120,7 +128,7 @@ - (void)clearVars { - (void)open:(NSString *)url { __weak typeof(self)weakSelf = self; - dispatch_async(_processingQueue, ^{ + dispatch_async(processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || strongSelf.opening || strongSelf.closing) { @@ -187,7 +195,7 @@ - (void)close { [self pause]; - dispatch_async(_processingQueue, ^{ + dispatch_async(processingQueue, ^{ __strong typeof(self)strongSelf = weakSelf; if (!strongSelf || strongSelf.closing) { @@ -198,7 +206,10 @@ - (void)close { [strongSelf.decoder prepareClose]; [strongSelf.decoder close]; - [strongSelf.view clear]; + + dispatch_sync(renderingQueue, ^{ + [strongSelf.view clear]; + }); NSArray *errors = nil; @@ -223,7 +234,7 @@ - (void)close { - (void)play { __weak typeof(self)weakSelf = self; - dispatch_async(_processingQueue, ^{ + dispatch_async(processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { @@ -454,7 +465,7 @@ - (void)render { - (void)renderView:(DLGPlayerVideoFrame *)frame { __weak typeof(self)weakSelf = self; - dispatch_sync(_renderingQueue, ^{ + dispatch_sync(renderingQueue, ^{ [weakSelf.view render:frame]; if (!weakSelf.renderBegan && frame.width > 0 && frame.height > 0) { diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index e6053a6..cb4099b 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -301,6 +301,7 @@ - (BOOL)close:(NSArray **)errors { NSError *error = nil; AVAudioSession *session = [AVAudioSession sharedInstance]; + if (![session setActive:NO error:&error]) { closed = NO; if (errs != nil) { From 52cf9561fc6163141f430ec3bc9be54712516bb6 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 31 May 2019 15:44:34 +0900 Subject: [PATCH 126/215] Fixed: change rendering queue static to instance. --- DLGPlayer/DLGPlayer.m | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 4120088..da1e66a 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -39,10 +39,10 @@ @interface DLGPlayer () @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; +@property (nonatomic, strong) dispatch_queue_t renderingQueue; @end static dispatch_queue_t processingQueue; -static dispatch_queue_t renderingQueue; @implementation DLGPlayer @@ -86,13 +86,11 @@ - (void)initVars { _requestSeekPosition = 0; _aFramesLock = dispatch_semaphore_create(1); _vFramesLock = dispatch_semaphore_create(1); + _renderingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); if (!processingQueue) { processingQueue = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); } - if (!renderingQueue) { - renderingQueue = dispatch_queue_create("DLGPlayer.renderingQueue", DISPATCH_QUEUE_SERIAL); - } } - (void)initView { @@ -206,10 +204,7 @@ - (void)close { [strongSelf.decoder prepareClose]; [strongSelf.decoder close]; - - dispatch_sync(renderingQueue, ^{ - [strongSelf.view clear]; - }); + [strongSelf.view clear]; NSArray *errors = nil; @@ -465,7 +460,7 @@ - (void)render { - (void)renderView:(DLGPlayerVideoFrame *)frame { __weak typeof(self)weakSelf = self; - dispatch_sync(renderingQueue, ^{ + dispatch_sync(_renderingQueue, ^{ [weakSelf.view render:frame]; if (!weakSelf.renderBegan && frame.width > 0 && frame.height > 0) { From 53585c5c16767a64be0e8e5b5e4c9fea641246c0 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Thu, 13 Jun 2019 12:30:42 +0900 Subject: [PATCH 127/215] Fixed: change rendering queue from instance to static. --- DLGPlayer/DLGPlayer.m | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index da1e66a..f7af222 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -39,9 +39,9 @@ @interface DLGPlayer () @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; -@property (nonatomic, strong) dispatch_queue_t renderingQueue; @end +static dispatch_queue_t renderingQueue; static dispatch_queue_t processingQueue; @implementation DLGPlayer @@ -86,7 +86,10 @@ - (void)initVars { _requestSeekPosition = 0; _aFramesLock = dispatch_semaphore_create(1); _vFramesLock = dispatch_semaphore_create(1); - _renderingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); + + if (!renderingQueue) { + renderingQueue = dispatch_queue_create("DLGPlayer.renderingQueue", DISPATCH_QUEUE_SERIAL); + } if (!processingQueue) { processingQueue = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); @@ -460,7 +463,7 @@ - (void)render { - (void)renderView:(DLGPlayerVideoFrame *)frame { __weak typeof(self)weakSelf = self; - dispatch_sync(_renderingQueue, ^{ + dispatch_sync(renderingQueue, ^{ [weakSelf.view render:frame]; if (!weakSelf.renderBegan && frame.width > 0 && frame.height > 0) { From 8d751c38f850be90811f3b3ce4c56e51f52632e0 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 18 Jun 2019 14:04:52 +0900 Subject: [PATCH 128/215] Revert "Fixed: change rendering queue from instance to static." This reverts commit 53585c5c16767a64be0e8e5b5e4c9fea641246c0. --- DLGPlayer/DLGPlayer.m | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index f7af222..da1e66a 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -39,9 +39,9 @@ @interface DLGPlayer () @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; +@property (nonatomic, strong) dispatch_queue_t renderingQueue; @end -static dispatch_queue_t renderingQueue; static dispatch_queue_t processingQueue; @implementation DLGPlayer @@ -86,10 +86,7 @@ - (void)initVars { _requestSeekPosition = 0; _aFramesLock = dispatch_semaphore_create(1); _vFramesLock = dispatch_semaphore_create(1); - - if (!renderingQueue) { - renderingQueue = dispatch_queue_create("DLGPlayer.renderingQueue", DISPATCH_QUEUE_SERIAL); - } + _renderingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); if (!processingQueue) { processingQueue = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); @@ -463,7 +460,7 @@ - (void)render { - (void)renderView:(DLGPlayerVideoFrame *)frame { __weak typeof(self)weakSelf = self; - dispatch_sync(renderingQueue, ^{ + dispatch_sync(_renderingQueue, ^{ [weakSelf.view render:frame]; if (!weakSelf.renderBegan && frame.width > 0 && frame.height > 0) { From 26d867e7578c2d501511c688600b74b80bf683d3 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 15 Jul 2019 17:41:43 +0900 Subject: [PATCH 129/215] Fixed: rename close to stop. --- DLGPlayer/DLGSimplePlayerViewController.h | 2 +- DLGPlayer/DLGSimplePlayerViewController.m | 20 ++++++++++++-------- DLGPlayerDemo/RootViewController.swift | 8 ++++---- DLGPlayerDemo/SecondViewController.swift | 8 ++++---- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index d9cd915..b8d1cd7 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -34,7 +34,7 @@ @property (nonnull, nonatomic, readonly) DLGPlayer *player; @property (nullable, nonatomic, weak) id delegate; - (void)open; -- (void)close; - (void)play; - (void)pause; +- (void)stop; @end diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 6db11ae..3b04283 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -125,12 +125,6 @@ - (void)open { [_player open:_url]; } -- (void)close { - self.status = DLGPlayerStatusClosing; - [UIApplication sharedApplication].idleTimerDisabled = NO; - [_player close]; -} - - (void)play { [UIApplication sharedApplication].idleTimerDisabled = _preventFromScreenLock; [_player play]; @@ -147,6 +141,12 @@ - (void)pause { [_player pause]; self.status = DLGPlayerStatusPaused; } + +- (void)stop { + self.status = DLGPlayerStatusClosing; + [UIApplication sharedApplication].idleTimerDisabled = NO; + [_player close]; +} #pragma mark - UI @@ -205,8 +205,12 @@ - (void)notifyAppWillEnterForeground:(NSNotification *)notif { - (void)notifyPlayerEOF:(NSNotification *)notif { self.status = DLGPlayerStatusEOF; - if (_isRepeat) [self replay]; - else [self close]; + + if (_isRepeat) { + [self replay]; + } else { + [self stop]; + } } - (void)notifyPlayerClosed:(NSNotification *)notif { diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 57ccc57..bd69673 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -56,7 +56,7 @@ class RootViewController: UIViewController { override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - playerViewController?.close() + playerViewController?.stop() coverView?.isHidden = false } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { @@ -101,7 +101,7 @@ class RootViewController: UIViewController { "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" - playerViewController?.close() + playerViewController?.stop() // print("[playTest] ------------------------------------------------------------------------------------") // print("[playTest] will open -> ", url) @@ -137,11 +137,11 @@ class RootViewController: UIViewController { } } @IBAction private func refreshButtonClicked(_ sender: UIButton) { - playerViewController?.close() + playerViewController?.stop() playRTMP() } @IBAction private func stopButtonClicked() { - playerViewController?.close() + playerViewController?.stop() } @IBAction private func valueChanged(_ sender: UISlider) { playerViewController?.player.brightness = sender.value diff --git a/DLGPlayerDemo/SecondViewController.swift b/DLGPlayerDemo/SecondViewController.swift index b8ad39a..656cb9e 100644 --- a/DLGPlayerDemo/SecondViewController.swift +++ b/DLGPlayerDemo/SecondViewController.swift @@ -55,7 +55,7 @@ class SecondViewController: UIViewController { override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - playerViewController?.close() + playerViewController?.stop() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segue.destination { @@ -99,7 +99,7 @@ class SecondViewController: UIViewController { "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" - playerViewController?.close() + playerViewController?.stop() // print("[playTest] ------------------------------------------------------------------------------------") // print("[playTest] will open -> ", url) @@ -141,11 +141,11 @@ class SecondViewController: UIViewController { } } @IBAction private func refreshButtonClicked(_ sender: UIButton) { - playerViewController?.close() + playerViewController?.stop() playRTMP() } @IBAction private func stopButtonClicked() { - playerViewController?.close() + playerViewController?.stop() } @IBAction private func valueChanged(_ sender: UISlider) { playerViewController?.player.brightness = sender.value From 66f8082ee387ea8cce67366d9dde78b68786b291 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 7 Aug 2019 10:10:56 +0900 Subject: [PATCH 130/215] Updated: change default value of minBufferDuration to 1 sec. --- DLGPlayer/common/DLGPlayerDef.h | 2 +- DLGPlayerDemo/Base.lproj/Main.storyboard | 40 ++++++++++++------------ DLGPlayerDemo/RootViewController.swift | 2 -- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index 1aeb04e..dd96ee0 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -11,7 +11,7 @@ #define DLGPlayerLocalizedStringTable @"DLGPlayerStrings" -#define DLGPlayerMinBufferDuration 2 +#define DLGPlayerMinBufferDuration 1 #define DLGPlayerMaxBufferDuration 5 #define DLGPlayerErrorDomainDecoder @"DLGPlayerDecoder" diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index d230beb..07bd73e 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -1,11 +1,11 @@ - - + + - + @@ -15,7 +15,7 @@ - + @@ -31,11 +31,11 @@ - + - + @@ -44,7 +44,7 @@ - + - + @@ -76,7 +76,7 @@ + + + + + + + + + + + + + + + + + + - + @@ -109,7 +109,7 @@ - + @@ -108,8 +108,19 @@ + + + + + + + + + + + - + @@ -100,7 +116,7 @@ - + @@ -109,7 +125,7 @@ - + diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 7a1fe66..13e01af 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -58,7 +58,6 @@ class RootViewController: UIViewController { } DLGPlayerUtils.setDebugEnabled(true) -// navigationItem.leftBarButtonItem = .init(title: "close", style: .plain, target: self, action: #selector(leftBarButtonItemClicked)) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) @@ -104,7 +103,7 @@ class RootViewController: UIViewController { playerViewController2?.open() } private func playRTMP1() { - playerViewController1?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACYMJ?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=1571796156306&speed=\(playerViewController1?.speed ?? 1)" + playerViewController1?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACYOV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" playerViewController1?.open() } private func playRTMP2() { diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift new file mode 100644 index 0000000..f355d9e --- /dev/null +++ b/DLGPlayerDemo/ViewController.swift @@ -0,0 +1,23 @@ +// +// ViewController.swift +// DLGPlayerDemo +// +// Created by KWANG HYOUN KIM on 05/12/2019. +// Copyright © 2019 KWANG HYOUN KIM. All rights reserved. +// + +import Foundation + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + guard let vc = storyboard?.instantiateViewController(withIdentifier: "RootViewController") else { + return + } + + navigationController?.pushViewController(vc, animated: false) + } + +} From 9ad94f69884e4babd32280ab96f9016aba89ea02 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 6 Dec 2019 11:43:39 +0900 Subject: [PATCH 159/215] Fixed: locks added in clear function. --- DLGPlayer/DLGPlayer.m | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index fb6ee5c..d8311b4 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -121,8 +121,16 @@ - (void)initAudio { } - (void)clearVars { - [self.vframes removeAllObjects]; - [self.aframes removeAllObjects]; + { + dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_FOREVER); + [self.vframes removeAllObjects]; + dispatch_semaphore_signal(self.vFramesLock); + } + { + dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_FOREVER); + [self.aframes removeAllObjects]; + dispatch_semaphore_signal(self.aFramesLock); + } self.playingAudioFrame = nil; self.playingAudioFrameDataPosition = 0; From ea37bbf5244ca94967cff121df580c9f35236011 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 9 Dec 2019 10:47:44 +0900 Subject: [PATCH 160/215] Fixed: clear warnings. Fixed: logic for semaphore added where it is missing. --- DLGPlayer/DLGPlayer.m | 11 +++++++---- DLGPlayer/DLGPlayerViewController.m | 5 +++-- DLGPlayerDemo/AppDelegate.swift | 4 ++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index d8311b4..0b3aecf 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -484,8 +484,12 @@ - (void)render { DLGPlayerVideoFrame *frame = self.vframes[0]; frame.brightness = _brightness; _view.contentSize = CGSizeMake(frame.width, frame.height); - [self.vframes removeObjectAtIndex:0]; - [self renderView:frame]; + + if (dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_NOW) == 0) { + [self.vframes removeObjectAtIndex:0]; + dispatch_semaphore_signal(self.vFramesLock); + [self renderView:frame]; + } } // Check whether render is neccessary @@ -504,8 +508,7 @@ - (void)render { // Render video DLGPlayerVideoFrame *frame = nil; { - long timeout = dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_NOW); - if (timeout == 0) { + if (dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_NOW) == 0) { frame = self.vframes[0]; frame.brightness = _brightness; self.mediaPosition = frame.position; diff --git a/DLGPlayer/DLGPlayerViewController.m b/DLGPlayer/DLGPlayerViewController.m index 43016f9..b3b5f2f 100644 --- a/DLGPlayer/DLGPlayerViewController.m +++ b/DLGPlayer/DLGPlayerViewController.m @@ -481,7 +481,8 @@ - (void)showHUD { strongSelf.vBottomBar.alpha = 1.0f; } completion:^(BOOL finished) { - animatingHUD = NO; + __strong typeof(weakSelf)strongSelf = weakSelf; + strongSelf->animatingHUD = NO; }]; [self startTimerForHideHUD]; } @@ -503,7 +504,7 @@ - (void)hideHUD { strongSelf.vTopBar.hidden = YES; strongSelf.vBottomBar.hidden = YES; - animatingHUD = NO; + strongSelf->animatingHUD = NO; }]; [self stopTimerForHideHUD]; } diff --git a/DLGPlayerDemo/AppDelegate.swift b/DLGPlayerDemo/AppDelegate.swift index 02d1988..ddc092a 100644 --- a/DLGPlayerDemo/AppDelegate.swift +++ b/DLGPlayerDemo/AppDelegate.swift @@ -18,6 +18,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Override point for customization after application launch. return true } + + func applicationDidReceiveMemoryWarning(_ application: UIApplication) { + print("applicationDidReceiveMemoryWarning"); + } func applicationWillResignActive(_ application: UIApplication) { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. From a6ed65875df1722f33df5ac10dfe25d898924ead Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 9 Dec 2019 14:53:12 +0900 Subject: [PATCH 161/215] Fixed: return nil if texture not ready when did request to make snapshot with metal. --- DLGPlayer/view/MetalPlayerView.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/DLGPlayer/view/MetalPlayerView.m b/DLGPlayer/view/MetalPlayerView.m index 0b69283..69071f2 100644 --- a/DLGPlayer/view/MetalPlayerView.m +++ b/DLGPlayer/view/MetalPlayerView.m @@ -175,6 +175,10 @@ - (UIImage *)snapshot { NSLog(@"[DLGPlayer] Metal will not work to make snapshot on simulator."); return nil; #else + if (!self.currentDrawable || !self.currentDrawable.texture) { + return nil; + } + const id texture = self.currentDrawable.texture; const NSInteger w = texture.width; const NSInteger h = texture.height; From a63188810017a3638fd121f648291021d1927f46 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 9 Dec 2019 15:14:35 +0900 Subject: [PATCH 162/215] Fixed: guard logic added to initialize with metal. Fixed: guard logic added to make the snapshot image with metal. --- DLGPlayer/view/MetalPlayerView.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/DLGPlayer/view/MetalPlayerView.m b/DLGPlayer/view/MetalPlayerView.m index 69071f2..8b49b34 100644 --- a/DLGPlayer/view/MetalPlayerView.m +++ b/DLGPlayer/view/MetalPlayerView.m @@ -69,6 +69,11 @@ - (void)executeMetalShader { @autoreleasepool { id commandBuffer = [_commandQueue commandBuffer]; + + if (!commandBuffer) { + return + } + id commandEncoder = [commandBuffer computeCommandEncoder]; if (commandEncoder) { @@ -175,7 +180,7 @@ - (UIImage *)snapshot { NSLog(@"[DLGPlayer] Metal will not work to make snapshot on simulator."); return nil; #else - if (!self.currentDrawable || !self.currentDrawable.texture) { + if (!self.isRenderingAvailable) { return nil; } From 14de39bd9e9ca975dcb6e9b83ea549824d965f1e Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 9 Dec 2019 15:17:33 +0900 Subject: [PATCH 163/215] Fixed: guard logic added to initialize with metal. --- DLGPlayer/view/MetalPlayerView.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/view/MetalPlayerView.m b/DLGPlayer/view/MetalPlayerView.m index 8b49b34..6328046 100644 --- a/DLGPlayer/view/MetalPlayerView.m +++ b/DLGPlayer/view/MetalPlayerView.m @@ -63,7 +63,7 @@ - (BOOL)isRenderingAvailable { #pragma mark - Private Methods - (void)executeMetalShader { - if (!self.isRenderingAvailable) { + if (!self.isRenderingAvailable || !_pipelineState) { return; } @@ -71,7 +71,7 @@ - (void)executeMetalShader { id commandBuffer = [_commandQueue commandBuffer]; if (!commandBuffer) { - return + return; } id commandEncoder = [commandBuffer computeCommandEncoder]; From 2c8ef89766cb33a99165e37cc21c2b1d49edda43 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 9 Dec 2019 19:12:16 +0900 Subject: [PATCH 164/215] Fixed: audio not working. Updated: The framedrop feature has been removed for a while. (memory issue) --- DLGPlayer/DLGPlayer.m | 27 ++------------- DLGPlayer/codec/DLGPlayerAudioManager.m | 46 +++++++++++++------------ DLGPlayer/codec/DLGPlayerDecoder.m | 11 +++--- DLGPlayerDemo/RootViewController.swift | 4 +-- 4 files changed, 34 insertions(+), 54 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 0b3aecf..09db894 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -177,7 +177,7 @@ - (void)open:(NSString *)url { NSArray *errors = nil; - [self.audio close:&errors]; + [strongSelf.audio close:&errors]; dispatch_async(dispatch_get_main_queue(), ^{ [strongSelf handleError:error]; @@ -326,29 +326,8 @@ - (void)readFrame { NSMutableArray *tempAFrames = [NSMutableArray arrayWithCapacity:8]; dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); - while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek) { - if (self.bufferedDuration + tempDuration > self.maxBufferDuration / self.speed) { - if (self.allowsFrameDrop) { - if (dispatch_semaphore_wait(self.vFramesLock, t) == 0) { - [self.vframes removeAllObjects]; - dispatch_semaphore_signal(self.vFramesLock); - } - - if (dispatch_semaphore_wait(self.aFramesLock, t) == 0) { - [self.aframes removeAllObjects]; - dispatch_semaphore_signal(self.aFramesLock); - } - - self.bufferedDuration = 0; - - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer drop frames beacuse buffer duration is over than max duration."); - } - } else { - continue; - } - } - + while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek && + (self.bufferedDuration + tempDuration < self.maxBufferDuration / self.speed)) { NSArray *fs = [self.decoder readFrames]; if (fs == nil) { break; } diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 61161c3..e0b8360 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -52,7 +52,7 @@ - (id)init { } - (void)initVars { - self.mute = NO; + _mute = NO; _registeredKVO = NO; _opened = NO; _closing = NO; @@ -84,7 +84,7 @@ - (void)dealloc { #pragma mark - Added by Steve Kim. - (AVAudioSessionCategory)category { - return self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; + return _mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; } /* @@ -126,13 +126,13 @@ - (BOOL)open:(NSError **)error { return NO; } -// if (session.currentRoute.outputs.count < 1) { -// [DLGPlayerUtils createError:error -// withDomain:DLGPlayerErrorDomainAudioManager -// andCode:DLGPlayerErrorCodeNoAudioOuput -// andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; -// return NO; -// } + if (session.currentRoute.outputs.count < 1) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioOuput + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; + return NO; + } if (session.outputNumberOfChannels < 1) { [DLGPlayerUtils createError:error @@ -183,7 +183,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend descr.componentFlagsMask = 0; AudioComponent component = AudioComponentFindNext(NULL, &descr); - OSStatus status = AudioComponentInstanceNew(component, &(self->_audioUnit)); + OSStatus status = AudioComponentInstanceNew(component, &_audioUnit); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -196,7 +196,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend AudioStreamBasicDescription streamDescr = {0}; UInt32 size = sizeof(AudioStreamBasicDescription); - status = AudioUnitGetProperty(self->_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); + status = AudioUnitGetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -208,7 +208,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend } streamDescr.mSampleRate = sampleRate; - status = AudioUnitSetProperty(self->_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); + status = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); if (status != noErr && DLGPlayerUtils.debugEnabled) { NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); } @@ -220,7 +220,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend renderCallbackStruct.inputProc = renderCallback; renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); - status = AudioUnitSetProperty(self->_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(renderCallbackStruct)); + status = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(renderCallbackStruct)); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -231,7 +231,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } - status = AudioUnitInitialize(self->_audioUnit); + status = AudioUnitInitialize(_audioUnit); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -267,7 +267,7 @@ - (BOOL)close:(NSArray **)errors { [self pause]; [self unregisterNotifications]; - OSStatus status = AudioUnitUninitialize(self->_audioUnit); + OSStatus status = AudioUnitUninitialize(_audioUnit); if (status != noErr) { closed = NO; if (errs != nil) { @@ -282,7 +282,7 @@ - (BOOL)close:(NSArray **)errors { } } - status = AudioComponentInstanceDispose(self->_audioUnit); + status = AudioComponentInstanceDispose(_audioUnit); if (status != noErr) { closed = NO; if (errs != nil) { @@ -330,12 +330,12 @@ - (BOOL)play { } - (BOOL)play:(NSError **)error { - if (self.mute) { + if (_mute) { return _playing; } - if (_opened && !_audioUnit) { - OSStatus status = AudioOutputUnitStart(self->_audioUnit); + if (_opened && _audioUnit) { + OSStatus status = AudioOutputUnitStart(_audioUnit); _playing = (status == noErr); if (!_playing) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -354,8 +354,8 @@ - (BOOL)pause { } - (BOOL)pause:(NSError **)error { - if (_playing && !_audioUnit) { - OSStatus status = AudioOutputUnitStop(self->_audioUnit); + if (_playing && _audioUnit) { + OSStatus status = AudioOutputUnitStop(_audioUnit); _playing = !(status == noErr); if (_playing) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -376,7 +376,9 @@ - (OSStatus)render:(AudioBufferList *)ioData count:(UInt32)inNumberFrames { memset(buf.mData, 0, buf.mDataByteSize); } - if (!_playing || _frameReaderBlock == nil) return noErr; + if (!_playing || _frameReaderBlock == nil) { + return noErr; + } _frameReaderBlock(_audioData, inNumberFrames, _channelsPerFrame); diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index e3472f5..0ce78c4 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -578,10 +578,9 @@ - (NSArray *)readFrames { const float sampleRate = _audioSampleRate; const UInt32 channels = _audioChannels; - void **_swrbuf = *swrbuf; void *data = NULL; NSInteger samplesPerChannel = 0; - if (swrctx != NULL && _swrbuf != NULL) { + if (swrctx != NULL && swrbuf != NULL) { float sampleRatio = sampleRate / context->sample_rate; float channelRatio = channels / context->channels; float ratio = MAX(1, sampleRatio) * MAX(1, channelRatio) * 2; @@ -591,12 +590,12 @@ - (NSArray *)readFrames { samples, AV_SAMPLE_FMT_S16, 1); - if (*_swrbuf == NULL || *swrbufsize < bufsize) { + if (*swrbuf == NULL || *swrbufsize < bufsize) { *swrbufsize = bufsize; - *_swrbuf = malloc(bufsize); + *swrbuf = realloc(*swrbuf, bufsize); } - Byte *o[2] = { *_swrbuf, 0 }; + Byte *o[2] = { *swrbuf, 0 }; samplesPerChannel = swr_convert(swrctx, o, samples, (const uint8_t **)frame->data, frame->nb_samples); if (samplesPerChannel < 0) { if (DLGPlayerUtils.debugEnabled) { @@ -605,7 +604,7 @@ - (NSArray *)readFrames { return nil; } - data = *_swrbuf; + data = *swrbuf; } else { if (context->sample_fmt != AV_SAMPLE_FMT_S16) { if (DLGPlayerUtils.debugEnabled) { diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 13e01af..fb63ac8 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -20,7 +20,7 @@ class RootViewController: UIViewController { didSet { playerViewController1.map { $0.delegate = self -// $0.isAllowsFrameDrop = true + $0.isAllowsFrameDrop = true $0.isAutoplay = true // $0.isMute = true $0.preventFromScreenLock = true @@ -103,7 +103,7 @@ class RootViewController: UIViewController { playerViewController2?.open() } private func playRTMP1() { - playerViewController1?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACYOV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" + playerViewController1?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" playerViewController1?.open() } private func playRTMP2() { From 3a03aa1d8129c7717e65efaa4fd60e2272f7c9a0 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 9 Dec 2019 20:00:40 +0900 Subject: [PATCH 165/215] Fixed: rollback framedrop function. --- DLGPlayer/DLGPlayer.m | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 09db894..5cb93da 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -326,8 +326,35 @@ - (void)readFrame { NSMutableArray *tempAFrames = [NSMutableArray arrayWithCapacity:8]; dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); - while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek && - (self.bufferedDuration + tempDuration < self.maxBufferDuration / self.speed)) { + while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek) { + if (self.bufferedDuration + tempDuration >= self.maxBufferDuration / self.speed) { + if (self.allowsFrameDrop) { + if (dispatch_semaphore_wait(self.vFramesLock, t) == 0) { + if (self.decoder.hasVideo) { + self.bufferedDuration = 0; + } + + [self.vframes removeAllObjects]; + dispatch_semaphore_signal(self.vFramesLock); + } + + if (dispatch_semaphore_wait(self.aFramesLock, t) == 0) { + if (!self.decoder.hasVideo) { + self.bufferedDuration = 0; + } + + [self.aframes removeAllObjects]; + dispatch_semaphore_signal(self.aFramesLock); + } + + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"DLGPlayer drop frames beacuse buffer duration is over than max duration."); + } + } else { + continue; + } + } + NSArray *fs = [self.decoder readFrames]; if (fs == nil) { break; } From 5799fc644e7536547b5262db5f1cba668c8ffef0 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 10 Dec 2019 18:03:13 +0900 Subject: [PATCH 166/215] Updated: improvement logic to drop frames. --- DLGPlayer/DLGPlayer.h | 1 + DLGPlayer/DLGPlayer.m | 64 +++++++++++++----------- DLGPlayer/common/DLGPlayerDef.h | 1 + DLGPlayer/frame/DLGPlayerFrame.h | 2 +- DLGPlayerDemo/Base.lproj/Main.storyboard | 23 +-------- DLGPlayerDemo/RootViewController.swift | 46 +++-------------- 6 files changed, 47 insertions(+), 90 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 0d263a0..e037268 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -30,6 +30,7 @@ typedef void (^onPauseComplete)(void); @property (atomic) BOOL buffering; @property (atomic) BOOL opened; @property (nonatomic) float brightness; +@property (nonatomic) double frameDropDuration; @property (nonatomic) double minBufferDuration; @property (nonatomic) double maxBufferDuration; @property (nonatomic) double position; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 5cb93da..ffdfd09 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -37,6 +37,7 @@ @interface DLGPlayer () @property (atomic) BOOL closing; @property (atomic) BOOL opening; @property (atomic) BOOL renderBegan; +@property (atomic) BOOL frameDropped; @property (atomic) double bufferedDuration; @property (atomic) double mediaPosition; @property (atomic) double mediaSyncTime; @@ -71,6 +72,7 @@ - (void)initAll { } - (void)initVars { + _frameDropDuration = DLGPlayerFrameDropDuration; _minBufferDuration = DLGPlayerMinBufferDuration; _maxBufferDuration = DLGPlayerMaxBufferDuration; _mediaSyncTime = 0; @@ -87,6 +89,7 @@ - (void)initVars { self.opening = NO; self.playing = NO; self.opened = NO; + self.frameDropped = NO; self.bufferedDuration = 0; self.mediaPosition = 0; self.playingAudioFrameDataPosition = 0; @@ -143,6 +146,7 @@ - (void)clearVars { self.mediaSyncTime = 0; self.closing = NO; self.opening = NO; + self.frameDropped = NO; } - (dispatch_queue_t)processingQueue { @@ -327,34 +331,6 @@ - (void)readFrame { dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek) { - if (self.bufferedDuration + tempDuration >= self.maxBufferDuration / self.speed) { - if (self.allowsFrameDrop) { - if (dispatch_semaphore_wait(self.vFramesLock, t) == 0) { - if (self.decoder.hasVideo) { - self.bufferedDuration = 0; - } - - [self.vframes removeAllObjects]; - dispatch_semaphore_signal(self.vFramesLock); - } - - if (dispatch_semaphore_wait(self.aFramesLock, t) == 0) { - if (!self.decoder.hasVideo) { - self.bufferedDuration = 0; - } - - [self.aframes removeAllObjects]; - dispatch_semaphore_signal(self.aFramesLock); - } - - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer drop frames beacuse buffer duration is over than max duration."); - } - } else { - continue; - } - } - NSArray *fs = [self.decoder readFrames]; if (fs == nil) { break; } @@ -407,6 +383,38 @@ - (void)readFrame { } } } + + // Drop frames + if (self.allowsFrameDrop && !self.frameDropped) { + if (self.bufferedDuration > self.frameDropDuration / self.speed) { + if (dispatch_semaphore_wait(self.vFramesLock, t) == 0) { + if (self.decoder.hasVideo) { + self.bufferedDuration = 0; + } + + [self.vframes removeAllObjects]; + dispatch_semaphore_signal(self.vFramesLock); + } + + if (dispatch_semaphore_wait(self.aFramesLock, t) == 0) { + if (!self.decoder.hasVideo) { + self.bufferedDuration = 0; + } + + [self.aframes removeAllObjects]; + dispatch_semaphore_signal(self.aFramesLock); + } + + self.frameDropped = YES; + + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); + } + break; + } + } else if (self.bufferedDuration >= self.maxBufferDuration / self.speed) { + break; + } } { diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index dd96ee0..7e7ab5a 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -11,6 +11,7 @@ #define DLGPlayerLocalizedStringTable @"DLGPlayerStrings" +#define DLGPlayerFrameDropDuration 4 #define DLGPlayerMinBufferDuration 1 #define DLGPlayerMaxBufferDuration 5 diff --git a/DLGPlayer/frame/DLGPlayerFrame.h b/DLGPlayer/frame/DLGPlayerFrame.h index 97f64e1..65172fd 100644 --- a/DLGPlayer/frame/DLGPlayerFrame.h +++ b/DLGPlayer/frame/DLGPlayerFrame.h @@ -17,8 +17,8 @@ typedef enum : NSUInteger { @interface DLGPlayerFrame : NSObject @property (nonatomic) DLGPlayerFrameType type; -@property (nonatomic) NSData *data; @property (nonatomic) double position; @property (nonatomic) double duration; +@property (nonatomic) NSData *data; @end diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index a557995..26273c1 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -115,15 +115,6 @@ - - - - - - - - - @@ -154,16 +145,12 @@ - - - - @@ -185,9 +172,6 @@ - - - @@ -210,7 +194,7 @@ - + @@ -218,7 +202,7 @@ - + @@ -338,7 +322,4 @@ - - - diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index fb63ac8..10524cb 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -20,25 +20,12 @@ class RootViewController: UIViewController { didSet { playerViewController1.map { $0.delegate = self - $0.isAllowsFrameDrop = true +// $0.isAllowsFrameDrop = true $0.isAutoplay = true // $0.isMute = true $0.preventFromScreenLock = true $0.restorePlayAfterAppEnterForeground = true - $0.minBufferDuration = 0 - $0.maxBufferDuration = 3 - } - } - } - private var playerViewController2: DLGSimplePlayerViewController? { - didSet { - playerViewController2.map { - $0.delegate = self - $0.isAllowsFrameDrop = true - $0.isAutoplay = true - // $0.isMute = true - $0.preventFromScreenLock = true - $0.restorePlayAfterAppEnterForeground = true + $0.speed = 2 $0.minBufferDuration = 0 $0.maxBufferDuration = 3 } @@ -74,7 +61,6 @@ class RootViewController: UIViewController { super.viewWillDisappear(animated) playerViewController1?.stop() - playerViewController2?.stop() coverView?.isHidden = false } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { @@ -83,12 +69,9 @@ class RootViewController: UIViewController { override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segue.destination { case let vc as DLGSimplePlayerViewController: - if playerViewController1 == nil { - playerViewController1 = vc - } else { - playerViewController2 = vc - } - default: () + playerViewController1 = vc + default: + () } } @@ -98,18 +81,10 @@ class RootViewController: UIViewController { playerViewController1?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" playerViewController1?.open() } - private func playDownload2() { - playerViewController2?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" - playerViewController2?.open() - } private func playRTMP1() { - playerViewController1?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" + playerViewController1?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001&speed=2" playerViewController1?.open() } - private func playRTMP2() { - playerViewController2?.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAACYMJ?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=1571796156306&speed=\(playerViewController1?.speed ?? 1)" - playerViewController2?.open() - } // MARK: - Hard Test @@ -135,13 +110,9 @@ class RootViewController: UIViewController { "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" playerViewController1?.stop() - playerViewController2?.stop() playerViewController1?.url = url playerViewController1?.open() - - playerViewController2?.url = url - playerViewController2?.open() } // MARK: - Private Selectors @@ -157,7 +128,6 @@ class RootViewController: UIViewController { @IBAction private func muteButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected playerViewController1?.isMute = !sender.isSelected - playerViewController2?.isMute = !sender.isSelected } @IBAction private func playOrPauseButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected @@ -174,17 +144,13 @@ class RootViewController: UIViewController { } @IBAction private func refreshButtonClicked(_ sender: UIButton) { playerViewController1?.stop() - playerViewController2?.stop() playRTMP1() - playRTMP2() } @IBAction private func stopButtonClicked() { playerViewController1?.stop() - playerViewController2?.stop() } @IBAction private func valueChanged(_ sender: UISlider) { playerViewController1?.player.brightness = sender.value - playerViewController2?.player.brightness = sender.value } @IBAction private func segmentValueChanged(_ sender: UISegmentedControl) { playerViewController1?.stop() From 0ec36db731bfb4718c73e76b6b429f5b255c4fd3 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 10 Dec 2019 19:03:11 +0900 Subject: [PATCH 167/215] Updated: frame drop has changed as fast playing. --- .../xcschemes/DLGPlayerDemo.xcscheme | 3 +- DLGPlayer/DLGPlayer.m | 67 +++++++++---------- DLGPlayer/frame/DLGPlayerFrame.h | 1 + DLGPlayerDemo/RootViewController.swift | 5 +- 4 files changed, 36 insertions(+), 40 deletions(-) diff --git a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme index 12cb248..a433617 100644 --- a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme +++ b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme @@ -50,6 +50,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUFrameCaptureMode = "3" allowLocationSimulation = "YES"> @@ -64,7 +65,7 @@ + isEnabled = "NO"> diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index ffdfd09..85da206 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -331,6 +331,35 @@ - (void)readFrame { dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek) { + + // Drop frames + if (self.allowsFrameDrop && !self.frameDropped) { + if (self.bufferedDuration > self.frameDropDuration / self.speed) { + if (dispatch_semaphore_wait(self.vFramesLock, t) == 0) { + for (DLGPlayerFrame *f in self.vframes) { + f.dropFrame = YES; + } + dispatch_semaphore_signal(self.vFramesLock); + } + + if (dispatch_semaphore_wait(self.aFramesLock, t) == 0) { + for (DLGPlayerFrame *f in self.aframes) { + f.dropFrame = YES; + } + dispatch_semaphore_signal(self.aFramesLock); + } + + self.frameDropped = YES; + + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); + } + break; + } + } else if (self.bufferedDuration >= self.maxBufferDuration / self.speed) { + break; + } + NSArray *fs = [self.decoder readFrames]; if (fs == nil) { break; } @@ -383,38 +412,6 @@ - (void)readFrame { } } } - - // Drop frames - if (self.allowsFrameDrop && !self.frameDropped) { - if (self.bufferedDuration > self.frameDropDuration / self.speed) { - if (dispatch_semaphore_wait(self.vFramesLock, t) == 0) { - if (self.decoder.hasVideo) { - self.bufferedDuration = 0; - } - - [self.vframes removeAllObjects]; - dispatch_semaphore_signal(self.vFramesLock); - } - - if (dispatch_semaphore_wait(self.aFramesLock, t) == 0) { - if (!self.decoder.hasVideo) { - self.bufferedDuration = 0; - } - - [self.aframes removeAllObjects]; - dispatch_semaphore_signal(self.aFramesLock); - } - - self.frameDropped = YES; - - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); - } - break; - } - } else if (self.bufferedDuration >= self.maxBufferDuration / self.speed) { - break; - } } { @@ -524,10 +521,10 @@ - (void)render { { if (dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_NOW) == 0) { frame = self.vframes[0]; + [self.vframes removeObjectAtIndex:0]; frame.brightness = _brightness; self.mediaPosition = frame.position; self.bufferedDuration -= frame.duration; - [self.vframes removeObjectAtIndex:0]; dispatch_semaphore_signal(self.vFramesLock); } } @@ -538,9 +535,7 @@ - (void)render { if (self.speed > 1) { t = frame.duration; } else { - // Sync audio with video - double syncTime = [self syncTime]; - t = MAX(frame.duration + syncTime, 0.01); + t = frame.dropFrame ? 0.01 : MAX(frame.duration + [self syncTime], 0.01); } __weak typeof(self)weakSelf = self; diff --git a/DLGPlayer/frame/DLGPlayerFrame.h b/DLGPlayer/frame/DLGPlayerFrame.h index 65172fd..1ab8d82 100644 --- a/DLGPlayer/frame/DLGPlayerFrame.h +++ b/DLGPlayer/frame/DLGPlayerFrame.h @@ -16,6 +16,7 @@ typedef enum : NSUInteger { @interface DLGPlayerFrame : NSObject +@property (nonatomic) BOOL dropFrame; @property (nonatomic) DLGPlayerFrameType type; @property (nonatomic) double position; @property (nonatomic) double duration; diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 10524cb..34b73af 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -20,12 +20,11 @@ class RootViewController: UIViewController { didSet { playerViewController1.map { $0.delegate = self -// $0.isAllowsFrameDrop = true + $0.isAllowsFrameDrop = true $0.isAutoplay = true // $0.isMute = true $0.preventFromScreenLock = true $0.restorePlayAfterAppEnterForeground = true - $0.speed = 2 $0.minBufferDuration = 0 $0.maxBufferDuration = 3 } @@ -82,7 +81,7 @@ class RootViewController: UIViewController { playerViewController1?.open() } private func playRTMP1() { - playerViewController1?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001&speed=2" + playerViewController1?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" playerViewController1?.open() } From 48fde91d20b125000b2228287811cd340580d14f Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 11 Dec 2019 16:25:49 +0900 Subject: [PATCH 168/215] Updated: set duration of frame by pts difference if pkt_duration of avframe is empty. --- DLGPlayer/codec/DLGPlayerDecoder.h | 4 ++-- DLGPlayer/codec/DLGPlayerDecoder.m | 33 +++++++++++++++++++------- DLGPlayerDemo/RootViewController.swift | 8 +++++-- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerDecoder.h b/DLGPlayer/codec/DLGPlayerDecoder.h index df54f51..63483fc 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.h +++ b/DLGPlayer/codec/DLGPlayerDecoder.h @@ -17,8 +17,8 @@ @property (nonatomic) BOOL isYUV; @property (nonatomic) double rotation; -@property (atomic) double duration; -@property (atomic) double speed; +@property (nonatomic) double duration; +@property (nonatomic) double speed; @property (nonatomic, strong) NSDictionary *metadata; @property (nonatomic) UInt32 audioChannels; diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index 0ce78c4..4d1bd99 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -43,6 +43,7 @@ @interface DLGPlayerDecoder () { AVCodecContext *m_pVideoCodecContext; struct SwsContext *m_pVideoSwsContext; int m_nPictureStream; + int64_t ptsPrevVideo; // Audio int m_nAudioStream; @@ -51,6 +52,7 @@ @interface DLGPlayerDecoder () { SwrContext *m_pAudioSwrContext; void *m_pAudioSwrBuffer; int m_nAudioSwrBufferSize; + int64_t ptsPrevAudio; } @end @@ -195,6 +197,9 @@ - (BOOL)open:(NSString *)url error:(NSError **)error { m_pAudioCodecContext = acodectx; m_pAudioSwrContext = aswrctx; + ptsPrevAudio = 0; + ptsPrevVideo = 0; + self.isYUV = isYUV; self.hasVideo = vstream >= 0; self.hasAudio = astream >= 0; @@ -204,7 +209,7 @@ - (BOOL)open:(NSString *)url error:(NSError **)error { self.rotation = rotation; int64_t duration = fmtctx->duration; self.duration = (duration == AV_NOPTS_VALUE ? -1 : ((double)duration / AV_TIME_BASE)); - self.duration /= self.speed; + self.duration /= _speed; self.metadata = [self findMetadata:fmtctx]; g_bPrepareClose = FALSE; @@ -335,6 +340,7 @@ - (void)close { - (void)closeVideoStream { m_nVideoStream = -1; + ptsPrevVideo = 0; if (m_pVideoFrame != NULL) av_frame_free(&m_pVideoFrame); if (m_pVideoCodecContext != NULL) avcodec_free_context(&m_pVideoCodecContext); if (m_pVideoSwsContext != NULL) { sws_freeContext(m_pVideoSwsContext); m_pVideoSwsContext = NULL; } @@ -342,6 +348,7 @@ - (void)closeVideoStream { - (void)closeAudioStream { m_nAudioStream = -1; + ptsPrevAudio = 0; if (m_pAudioFrame != NULL) av_frame_free(&m_pAudioFrame); if (m_pAudioCodecContext != NULL) avcodec_free_context(&m_pAudioCodecContext); if (m_pAudioSwrContext != NULL) swr_free(&m_pAudioSwrContext); @@ -537,15 +544,19 @@ - (NSArray *)readFrames { f.height = height; f.position = frame->best_effort_timestamp * _videoTimebase; - double duration = frame->pkt_duration / self.speed; + double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevVideo; + if (duration > 0) { - f.duration = duration * _videoTimebase; - f.duration += frame->repeat_pict * _videoTimebase * 0.5; + f.duration = duration * _videoTimebase / _speed; + f.duration += (frame->repeat_pict * _videoTimebase * 0.5) / _speed; } else { - f.duration = 1 / _videoFPS; + f.duration = 1 / _videoFPS / _speed; } [frames addObject:f]; + + ptsPrevVideo = frame->pts; + } while(ret == 0); return frames; @@ -628,12 +639,18 @@ - (NSArray *)readFrames { DLGPlayerAudioFrame *f = [[DLGPlayerAudioFrame alloc] init]; f.data = mdata; f.position = frame->best_effort_timestamp * _audioTimebase; - f.duration = (frame->pkt_duration / self.speed) * _audioTimebase; - if (f.duration == 0) { - f.duration = f.data.length / (sizeof(float) * channels * sampleRate); + + double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevAudio; + + if (duration > 0) { + f.duration = duration * _audioTimebase / _speed; + } else { + f.duration = f.data.length / (sizeof(float) * channels * sampleRate) / _speed; } + ptsPrevAudio = frame->pts; + [frames addObject:f]; } while(ret == 0); diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 34b73af..7c7940d 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -20,7 +20,7 @@ class RootViewController: UIViewController { didSet { playerViewController1.map { $0.delegate = self - $0.isAllowsFrameDrop = true +// $0.isAllowsFrameDrop = true $0.isAutoplay = true // $0.isMute = true $0.preventFromScreenLock = true @@ -81,7 +81,11 @@ class RootViewController: UIViewController { playerViewController1?.open() } private func playRTMP1() { - playerViewController1?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" + let now = Date().timeIntervalSince1970 + let time = Date(timeIntervalSince1970: now - 60 * 60 * 24).timeIntervalSince1970 + + playerViewController1?.speed = 2 + playerViewController1?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" playerViewController1?.open() } From 3ea4509615004ac1c6fd24a457aa87dec5f86533 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 13 Dec 2019 14:09:09 +0900 Subject: [PATCH 169/215] Fixed: guard if reference of self is null. --- DLGPlayer/DLGPlayer.m | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 85da206..7b17abf 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -172,6 +172,9 @@ - (void)open:(NSString *)url { strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; } else { dispatch_async(dispatch_get_main_queue(), ^{ + if (!strongSelf) { + return; + } [strongSelf handleError:error]; }); } @@ -184,6 +187,9 @@ - (void)open:(NSString *)url { [strongSelf.audio close:&errors]; dispatch_async(dispatch_get_main_queue(), ^{ + if (!strongSelf) { + return; + } [strongSelf handleError:error]; }); return; @@ -191,7 +197,7 @@ - (void)open:(NSString *)url { } dispatch_async(dispatch_get_main_queue(), ^{ - if (!strongSelf.opening || strongSelf.closing) { + if (!strongSelf || !strongSelf.opening || strongSelf.closing) { return; } From 1f3fe3a77f57b95ce88428d29935d4c926c30812 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 13 Dec 2019 14:30:21 +0900 Subject: [PATCH 170/215] Fixed: thread switching. --- DLGPlayer/DLGPlayer.m | 52 +++++++++-------------- DLGPlayer/DLGSimplePlayerViewController.m | 26 +++++------- 2 files changed, 31 insertions(+), 47 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 7b17abf..38d0eeb 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -171,27 +171,15 @@ - (void)open:(NSString *)url { strongSelf.decoder.audioChannels = [strongSelf.audio channels]; strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; } else { - dispatch_async(dispatch_get_main_queue(), ^{ - if (!strongSelf) { - return; - } - [strongSelf handleError:error]; - }); + [strongSelf handleError:error]; } if (![strongSelf.decoder open:url error:&error]) { strongSelf.opening = NO; NSArray *errors = nil; - [strongSelf.audio close:&errors]; - - dispatch_async(dispatch_get_main_queue(), ^{ - if (!strongSelf) { - return; - } - [strongSelf handleError:error]; - }); + [strongSelf handleError:error]; return; } } @@ -239,34 +227,32 @@ - (void)open:(NSString *)url { - (void)close { [self pause]; + __weak typeof(self)weakSelf = self; + dispatch_async(self.processingQueue, ^{ - if (self.closing) { + __strong typeof(weakSelf)strongSelf = weakSelf; + if (!strongSelf || strongSelf.closing) { return; } - self.closing = YES; + strongSelf.closing = YES; - [self.decoder prepareClose]; - [self.decoder close]; - [self.view clear]; + [strongSelf.decoder prepareClose]; + [strongSelf.decoder close]; + [strongSelf.view clear]; @autoreleasepool { NSArray *errors = nil; - if ([self.audio close:&errors]) { - [self clearVars]; - - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:self]; - }); + if ([strongSelf.audio close:&errors]) { + [strongSelf clearVars]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; } else { - [self clearVars]; + [strongSelf clearVars]; - dispatch_async(dispatch_get_main_queue(), ^{ - for (NSError *error in errors) { - [self handleError:error]; - } - }); + for (NSError *error in errors) { + [strongSelf handleError:error]; + } } } }); @@ -285,7 +271,9 @@ - (void)play { strongSelf.playing = YES; dispatch_async(dispatch_get_main_queue(), ^{ - [strongSelf render]; + if (strongSelf) { + [strongSelf render]; + } }); @autoreleasepool { diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index fd791d6..ac16c9f 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -85,7 +85,9 @@ - (void)setStatus:(DLGPlayerStatus)status { [_controlStatus setStatus:_status]; if ([_delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { - [_delegate viewController:self didChangeStatus:status]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self.delegate viewController:self didChangeStatus:status]; + }); } } @@ -259,15 +261,7 @@ - (void)notifyPlayerError:(NSNotification *)notif { NSError *error = userInfo[DLGPlayerNotificationErrorKey]; if ([error.domain isEqualToString:DLGPlayerErrorDomainDecoder]) { - __weak typeof(self)weakSelf = self; - dispatch_async(dispatch_get_main_queue(), ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - strongSelf.status = DLGPlayerStatusNone; - }); + self.status = DLGPlayerStatusNone; if (DLGPlayerUtils.debugEnabled) { NSLog(@"Player decoder error: %@", error); @@ -278,11 +272,13 @@ - (void)notifyPlayerError:(NSNotification *)notif { } } - if ([_delegate respondsToSelector:@selector(viewController:didReceiveError:)]) { - [_delegate viewController:self didReceiveError:error]; - } - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:self userInfo:notif.userInfo]; + dispatch_async(dispatch_get_main_queue(), ^{ + if ([self.delegate respondsToSelector:@selector(viewController:didReceiveError:)]) { + [self.delegate viewController:self didReceiveError:error]; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:self userInfo:notif.userInfo]; + }); } @end From 704da190e3f34712d932a860a0542a9f1a404c8e Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 13 Dec 2019 17:58:24 +0900 Subject: [PATCH 171/215] Fixed: redesign using metal view. --- .../xcschemes/DLGPlayerDemo.xcscheme | 11 -- DLGPlayer/DLGPlayer.m | 3 - DLGPlayer/view/MetalPlayerView.h | 3 +- DLGPlayer/view/MetalPlayerView.m | 149 ++++++++++-------- DLGPlayerDemo/RootViewController.swift | 2 +- 5 files changed, 87 insertions(+), 81 deletions(-) diff --git a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme index a433617..7ca084c 100644 --- a/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme +++ b/DLGPlayer.xcodeproj/xcshareddata/xcschemes/DLGPlayerDemo.xcscheme @@ -62,18 +62,7 @@ ReferencedContainer = "container:DLGPlayer.xcodeproj"> - - - - - - #import "DLGPlayerVideoFrameView.h" -@import MetalKit; NS_ASSUME_NONNULL_BEGIN API_AVAILABLE(ios(9.0)) -@interface MetalPlayerView : MTKView +@interface MetalPlayerView : UIView @end NS_ASSUME_NONNULL_END diff --git a/DLGPlayer/view/MetalPlayerView.m b/DLGPlayer/view/MetalPlayerView.m index 6328046..bf66a12 100644 --- a/DLGPlayer/view/MetalPlayerView.m +++ b/DLGPlayer/view/MetalPlayerView.m @@ -6,21 +6,27 @@ // Copyright © 2019 KWANG HYOUN KIM. All rights reserved. // +@import MetalKit; #import "MetalPlayerView.h" +#import "DLGPlayerUtils.h" #import "DLGPlayerVideoFrame.h" #import "DLGPlayerVideoYUVFrame.h" -@interface MetalPlayerView () +@interface MetalPlayerView () @property (nonatomic, readonly) BOOL isRenderingAvailable; -@property (nonatomic) MTLSize threadsPerThreadgroup; -@property (nonatomic) MTLSize threadgroupsPerGrid; -@property (nonatomic, strong) id defaultLibrary; -@property (nonatomic, strong) id commandQueue; -@property (nonatomic, strong) id pipelineState; -@property (nonatomic, strong) DLGPlayerVideoFrame *currentFrame; @end @implementation MetalPlayerView +{ +@private + MTLSize threadsPerThreadgroup; + MTLSize threadgroupsPerGrid; + id defaultLibrary; + id commandQueue; + id pipelineState; + MTKView *metalView; + DLGPlayerVideoFrame *currentFrame; +} @synthesize isYUV = _isYUV; @synthesize keepLastFrame = _keepLastFrame; @@ -29,12 +35,11 @@ @implementation MetalPlayerView #pragma mark - Constructors -- (id)init { - self = [super init]; - if (self) { - [self initProperties]; +- (void)dealloc { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"MetalPlayerView dealloc"); } - return self; + [self clear]; } - (id)initWithFrame:(CGRect)frame { @@ -45,30 +50,54 @@ - (id)initWithFrame:(CGRect)frame { return self; } -#if TARGET_IPHONE_SIMULATOR -#else - -#pragma mark - Overridden: MTKView +#pragma mark - Private Properties -- (void)drawRect:(CGRect)rect { - [self executeMetalShader]; +- (BOOL)isRenderingAvailable { + return metalView.currentDrawable != nil && currentFrame != nil && currentFrame.prepared; } -#pragma mark - Private Properties +#pragma mark - Overridden: UIView -- (BOOL)isRenderingAvailable { - return self.currentDrawable != nil && _currentFrame != nil && _currentFrame.prepared; +- (void)layoutSubviews { + [super layoutSubviews]; + + metalView.frame = self.bounds; } +#if TARGET_IPHONE_SIMULATOR +#else + #pragma mark - Private Methods + +- (void)setUpPipelineState { + @autoreleasepool { + NSString *name = _isYUV ? @"YUVColorConversion" : @"RGBColorConversion"; + id kernelFunction = [defaultLibrary newFunctionWithName:name]; + + if (!kernelFunction && DLGPlayerUtils.debugEnabled) { + NSLog(@"Error creating compute shader"); + return; + } + + pipelineState = [metalView.device newComputePipelineStateWithFunction:kernelFunction error:nil]; + + if (!pipelineState && DLGPlayerUtils.debugEnabled) { + NSLog(@"Error creating the pipeline state"); + } + } +} -- (void)executeMetalShader { - if (!self.isRenderingAvailable || !_pipelineState) { +#pragma mark - Private Methods (MTKViewDelegate) + +- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {} + +- (void)drawInMTKView:(nonnull MTKView *)view { + if (!self.isRenderingAvailable || !pipelineState) { return; } @autoreleasepool { - id commandBuffer = [_commandQueue commandBuffer]; + id commandBuffer = [commandQueue commandBuffer]; if (!commandBuffer) { return; @@ -77,64 +106,54 @@ - (void)executeMetalShader { id commandEncoder = [commandBuffer computeCommandEncoder]; if (commandEncoder) { - float brightness = _currentFrame.brightness; + float brightness = currentFrame.brightness; - [commandEncoder setComputePipelineState:_pipelineState]; + [commandEncoder setComputePipelineState:pipelineState]; [commandEncoder setBytes:&brightness length:sizeof(brightness) atIndex:0]; - [_currentFrame render:commandEncoder]; - [commandEncoder setTexture:self.currentDrawable.texture atIndex:3]; - [commandEncoder dispatchThreadgroups:_threadgroupsPerGrid threadsPerThreadgroup:_threadsPerThreadgroup]; + [currentFrame render:commandEncoder]; + [commandEncoder setTexture:metalView.currentDrawable.texture atIndex:3]; + [commandEncoder dispatchThreadgroups:threadgroupsPerGrid threadsPerThreadgroup:threadsPerThreadgroup]; [commandEncoder endEncoding]; - [commandBuffer presentDrawable:self.currentDrawable]; + [commandBuffer presentDrawable:metalView.currentDrawable]; [commandBuffer commit]; } } } - -- (void)setUpPipelineState { - NSString *name = _isYUV ? @"YUVColorConversion" : @"RGBColorConversion"; - id kernelFunction = [_defaultLibrary newFunctionWithName:name]; - - if (!kernelFunction) { - NSLog(@"Error creating compute shader"); - return; - } - - _pipelineState = [self.device newComputePipelineStateWithFunction:kernelFunction error:nil]; - - if (!_pipelineState) { - NSLog(@"Error creating the pipeline state"); - } -} + #endif - (void)initProperties { - self.framebufferOnly = NO; - self.autoResizeDrawable = NO; - self.colorPixelFormat = MTLPixelFormatBGRA8Unorm; - self.contentScaleFactor = UIScreen.mainScreen.scale; - self.clearColor = MTLClearColorMake(1, 1, 1, 1); + metalView = [MTKView new]; + metalView.autoResizeDrawable = NO; + metalView.framebufferOnly = NO; + metalView.contentScaleFactor = UIScreen.mainScreen.scale; + metalView.colorPixelFormat = MTLPixelFormatBGRA8Unorm; + metalView.clearColor = MTLClearColorMake(1, 1, 1, 1); + metalView.device = MTLCreateSystemDefaultDevice(); + metalView.delegate = self; + + [self addSubview:metalView]; + #if TARGET_IPHONE_SIMULATOR NSLog(@"[DLGPlayer] Metal will not work on simulator."); #endif - self.device = MTLCreateSystemDefaultDevice(); - _commandQueue = [self.device newCommandQueue]; + commandQueue = [metalView.device newCommandQueue]; if (@available(iOS 10.0, *)) { @autoreleasepool { NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - _defaultLibrary = [self.device newDefaultLibraryWithBundle:bundle error:nil]; + defaultLibrary = [metalView.device newDefaultLibraryWithBundle:bundle error:nil]; } } else { - _defaultLibrary = [self.device newDefaultLibrary]; + defaultLibrary = [metalView.device newDefaultLibrary]; } - _threadsPerThreadgroup = MTLSizeMake(16, 16, 1); - _threadgroupsPerGrid = MTLSizeMake(2048 / _threadsPerThreadgroup.width, 1536 / _threadsPerThreadgroup.height, 1); + threadsPerThreadgroup = MTLSizeMake(16, 16, 1); + threadgroupsPerGrid = MTLSizeMake(2048 / threadsPerThreadgroup.width, 1536 / threadsPerThreadgroup.height, 1); } -#pragma mark - Implement: DLGPlayerVideoFrame +#pragma mark - Public Methods (DLGPlayerVideoFrame) - (void)setContentSize:(CGSize)contentSize { _contentSize = contentSize; @@ -158,8 +177,10 @@ - (void)setIsYUV:(BOOL)isYUV { - (void)clear { if (!_keepLastFrame) { - _currentFrame = nil; + currentFrame = nil; } + + [metalView releaseDrawables]; } - (void)render:(DLGPlayerVideoFrame *)frame { @@ -167,10 +188,10 @@ - (void)render:(DLGPlayerVideoFrame *)frame { return; } - _currentFrame = frame; - self.drawableSize = CGSizeMake(frame.width, frame.height); + currentFrame = frame; + metalView.drawableSize = CGSizeMake(frame.width, frame.height); - if ([frame prepareDevice:self.device]) { + if ([frame prepareDevice:metalView.device]) { // TODO: - Impl scale / flip / rotation. } } @@ -184,10 +205,10 @@ - (UIImage *)snapshot { return nil; } - const id texture = self.currentDrawable.texture; + const id texture = metalView.currentDrawable.texture; const NSInteger w = texture.width; const NSInteger h = texture.height; - CIContext *context = [CIContext contextWithMTLDevice:self.device]; + CIContext *context = [CIContext contextWithMTLDevice:metalView.device]; CIImage *outputImage = [[CIImage alloc] initWithMTLTexture:texture options:@{kCIImageColorSpace: (__bridge_transfer id) CGColorSpaceCreateDeviceRGB()}]; CGImageRef cgImg = [context createCGImage:outputImage fromRect:CGRectMake(0, 0, w, h)]; UIImage *resultImg = [UIImage imageWithCGImage:cgImg scale:UIScreen.mainScreen.scale orientation:UIImageOrientationDownMirrored]; diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 7c7940d..5d07dfd 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -63,7 +63,7 @@ class RootViewController: UIViewController { coverView?.isHidden = false } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { - self.navigationController?.isNavigationBarHidden = UIDevice.current.orientation.isLandscape + navigationController?.isNavigationBarHidden = UIDevice.current.orientation.isLandscape } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segue.destination { From 4f40c337879ad3eec621c697695f41c124aaaf71 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 11:42:42 +0900 Subject: [PATCH 172/215] Fixed: issue that invalid break in loop. --- DLGPlayer/DLGPlayer.m | 7 +++---- DLGPlayerDemo/RootViewController.swift | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 12d8f67..d78eef5 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -322,7 +322,6 @@ - (void)readFrame { dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek) { - // Drop frames if (self.allowsFrameDrop && !self.frameDropped) { if (self.bufferedDuration > self.frameDropDuration / self.speed) { @@ -345,10 +344,10 @@ - (void)readFrame { if (DLGPlayerUtils.debugEnabled) { NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); } - break; + continue; } - } else if (self.bufferedDuration >= self.maxBufferDuration / self.speed) { - break; + } else if (self.bufferedDuration > self.maxBufferDuration / self.speed) { + continue; } NSArray *fs = [self.decoder readFrames]; diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 5d07dfd..94ca227 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -20,9 +20,9 @@ class RootViewController: UIViewController { didSet { playerViewController1.map { $0.delegate = self -// $0.isAllowsFrameDrop = true + $0.isAllowsFrameDrop = true $0.isAutoplay = true -// $0.isMute = true + $0.isMute = true $0.preventFromScreenLock = true $0.restorePlayAfterAppEnterForeground = true $0.minBufferDuration = 0 From 6f941be4f09fb652e18006be0df93d6f2cf1ed3f Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 15:19:59 +0900 Subject: [PATCH 173/215] Fixed: guard for crash. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 15 ++++++++++----- DLGPlayerDemo/RootViewController.swift | 8 +++++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index e0b8360..91ce2f9 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -182,8 +182,10 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend descr.componentFlags = 0; descr.componentFlagsMask = 0; + AudioUnit audioUnit = NULL; + AudioComponent component = AudioComponentFindNext(NULL, &descr); - OSStatus status = AudioComponentInstanceNew(component, &_audioUnit); + OSStatus status = AudioComponentInstanceNew(component, &audioUnit); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -196,7 +198,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend AudioStreamBasicDescription streamDescr = {0}; UInt32 size = sizeof(AudioStreamBasicDescription); - status = AudioUnitGetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); + status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -208,7 +210,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend } streamDescr.mSampleRate = sampleRate; - status = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); if (status != noErr && DLGPlayerUtils.debugEnabled) { NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); } @@ -220,7 +222,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend renderCallbackStruct.inputProc = renderCallback; renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); - status = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(renderCallbackStruct)); + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(renderCallbackStruct)); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -231,7 +233,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } - status = AudioUnitInitialize(_audioUnit); + status = AudioUnitInitialize(audioUnit); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -242,6 +244,8 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } + _audioUnit = audioUnit; + return YES; } } @@ -315,6 +319,7 @@ - (BOOL)close:(NSArray **)errors { } if (closed) { + _audioUnit = NULL; _opened = NO; } } diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 94ca227..c631ee0 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -22,7 +22,7 @@ class RootViewController: UIViewController { $0.delegate = self $0.isAllowsFrameDrop = true $0.isAutoplay = true - $0.isMute = true +// $0.isMute = true $0.preventFromScreenLock = true $0.restorePlayAfterAppEnterForeground = true $0.minBufferDuration = 0 @@ -84,8 +84,10 @@ class RootViewController: UIViewController { let now = Date().timeIntervalSince1970 let time = Date(timeIntervalSince1970: now - 60 * 60 * 24).timeIntervalSince1970 - playerViewController1?.speed = 2 - playerViewController1?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" +// playerViewController1?.speed = 2 +// playerViewController1?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" + + playerViewController1?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" playerViewController1?.open() } From 1b972b78f98157b7362188fd09f4b968bf20b910 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 16:00:29 +0900 Subject: [PATCH 174/215] Revert "Fixed: guard for crash." This reverts commit 6f941be4f09fb652e18006be0df93d6f2cf1ed3f. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 15 +++++---------- DLGPlayerDemo/RootViewController.swift | 8 +++----- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 91ce2f9..e0b8360 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -182,10 +182,8 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend descr.componentFlags = 0; descr.componentFlagsMask = 0; - AudioUnit audioUnit = NULL; - AudioComponent component = AudioComponentFindNext(NULL, &descr); - OSStatus status = AudioComponentInstanceNew(component, &audioUnit); + OSStatus status = AudioComponentInstanceNew(component, &_audioUnit); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -198,7 +196,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend AudioStreamBasicDescription streamDescr = {0}; UInt32 size = sizeof(AudioStreamBasicDescription); - status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); + status = AudioUnitGetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -210,7 +208,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend } streamDescr.mSampleRate = sampleRate; - status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); + status = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); if (status != noErr && DLGPlayerUtils.debugEnabled) { NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); } @@ -222,7 +220,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend renderCallbackStruct.inputProc = renderCallback; renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); - status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(renderCallbackStruct)); + status = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(renderCallbackStruct)); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -233,7 +231,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } - status = AudioUnitInitialize(audioUnit); + status = AudioUnitInitialize(_audioUnit); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error @@ -244,8 +242,6 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } - _audioUnit = audioUnit; - return YES; } } @@ -319,7 +315,6 @@ - (BOOL)close:(NSArray **)errors { } if (closed) { - _audioUnit = NULL; _opened = NO; } } diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index c631ee0..94ca227 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -22,7 +22,7 @@ class RootViewController: UIViewController { $0.delegate = self $0.isAllowsFrameDrop = true $0.isAutoplay = true -// $0.isMute = true + $0.isMute = true $0.preventFromScreenLock = true $0.restorePlayAfterAppEnterForeground = true $0.minBufferDuration = 0 @@ -84,10 +84,8 @@ class RootViewController: UIViewController { let now = Date().timeIntervalSince1970 let time = Date(timeIntervalSince1970: now - 60 * 60 * 24).timeIntervalSince1970 -// playerViewController1?.speed = 2 -// playerViewController1?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" - - playerViewController1?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" + playerViewController1?.speed = 2 + playerViewController1?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" playerViewController1?.open() } From d6a8cdbe981d8f99f9c6db145cd25deca36b6781 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 16:54:12 +0900 Subject: [PATCH 175/215] Fixed: crash when audio closing. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index e0b8360..be1a6c9 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -41,7 +41,6 @@ @interface DLGPlayerAudioManager () { @end @implementation DLGPlayerAudioManager -@synthesize mute = _mute; - (id)init { self = [super init]; @@ -52,7 +51,7 @@ - (id)init { } - (void)initVars { - _mute = NO; + self.mute = NO; _registeredKVO = NO; _opened = NO; _closing = NO; @@ -84,13 +83,17 @@ - (void)dealloc { #pragma mark - Added by Steve Kim. - (AVAudioSessionCategory)category { - return _mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; + return self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; } /* * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ - (BOOL)open:(NSError **)error { + if (self.mute) { + return NO; + } + @autoreleasepool { AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *rawError = nil; @@ -251,13 +254,13 @@ - (BOOL)close { } - (BOOL)close:(NSArray **)errors { + if (_closing) { + return NO; + } + + _closing = YES; + @autoreleasepool { - if (_closing) { - return NO; - } - - _closing = YES; - NSMutableArray *errs = nil; if (errors != nil) errs = [NSMutableArray array]; @@ -330,7 +333,7 @@ - (BOOL)play { } - (BOOL)play:(NSError **)error { - if (_mute) { + if (self.mute) { return _playing; } From 5b7101aa2cd5e4f20348950eb20d027c66dd548c Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 17:08:49 +0900 Subject: [PATCH 176/215] Fixed: crash when audio closing. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index be1a6c9..8083b4c 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -254,7 +254,7 @@ - (BOOL)close { } - (BOOL)close:(NSArray **)errors { - if (_closing) { + if (_closing || self.mute) { return NO; } From f4382803105efeb0ac36bbb4db4c482d4a999496 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 17:30:00 +0900 Subject: [PATCH 177/215] Fixed: new serial queue to process audio. --- DLGPlayer/DLGPlayer.m | 87 ++++++++++++++++--------- DLGPlayer/codec/DLGPlayerAudioManager.m | 6 +- DLGPlayerDemo/RootViewController.swift | 47 ++++++------- 3 files changed, 83 insertions(+), 57 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index d78eef5..e6672d5 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -43,6 +43,7 @@ @interface DLGPlayer () @property (atomic) double mediaSyncPosition; @end +static dispatch_queue_t audioProcessingQueue; static dispatch_queue_t processingQueueStatic; @implementation DLGPlayer @@ -101,6 +102,8 @@ - (void)initVars { } else if (!processingQueueStatic) { processingQueueStatic = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); } + + audioProcessingQueue = dispatch_queue_create("DLGPlayer.audioProcessingQueue", DISPATCH_QUEUE_SERIAL); } - (void)initView { @@ -162,7 +165,11 @@ - (void)open:(NSString *)url { strongSelf.opening = YES; - @autoreleasepool { + dispatch_async(audioProcessingQueue, ^{ + if (!strongSelf) { + return; + } + NSError *error = nil; if ([strongSelf.audio open:&error]) { strongSelf.decoder.audioChannels = [strongSelf.audio channels]; @@ -170,15 +177,14 @@ - (void)open:(NSString *)url { } else { [strongSelf handleError:error]; } + }); + + NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - - NSArray *errors = nil; - [strongSelf.audio close:&errors]; - [strongSelf handleError:error]; - return; - } + [strongSelf handleError:error]; + return; } dispatch_async(dispatch_get_main_queue(), ^{ @@ -238,20 +244,26 @@ - (void)close { [strongSelf.decoder close]; [strongSelf.view clear]; - @autoreleasepool { - NSArray *errors = nil; + dispatch_async(audioProcessingQueue, ^{ + if (!strongSelf) { + return; + } - if ([strongSelf.audio close:&errors]) { - [strongSelf clearVars]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; - } else { - [strongSelf clearVars]; + @autoreleasepool { + NSArray *errors = nil; - for (NSError *error in errors) { - [strongSelf handleError:error]; + if ([strongSelf.audio close:&errors]) { + [strongSelf clearVars]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; + } else { + [strongSelf clearVars]; + + for (NSError *error in errors) { + [strongSelf handleError:error]; + } } } - } + }); }); } @@ -273,13 +285,20 @@ - (void)play { } }); - @autoreleasepool { - NSError *error = nil; + + dispatch_async(audioProcessingQueue, ^{ + if (!strongSelf) { + return; + } - if (![strongSelf.audio play:&error]) { - [strongSelf handleError:error]; + @autoreleasepool { + NSError *error = nil; + + if (![strongSelf.audio play:&error]) { + [strongSelf handleError:error]; + } } - } + }); [strongSelf runFrameReader]; }); @@ -288,12 +307,22 @@ - (void)play { - (void)pause { self.playing = NO; - @autoreleasepool { - NSError *error = nil; - if (![self.audio pause:&error]) { - [self handleError:error]; + __weak typeof(self)weakSelf = self; + + dispatch_async(audioProcessingQueue, ^{ + __strong typeof(self)strongSelf = weakSelf; + + if (!strongSelf) { + return; } - } + + @autoreleasepool { + NSError *error = nil; + if (![self.audio pause:&error]) { + [self handleError:error]; + } + } + }); } - (UIImage *)snapshot { diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 8083b4c..6b8ba98 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -90,10 +90,6 @@ - (AVAudioSessionCategory)category { * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ - (BOOL)open:(NSError **)error { - if (self.mute) { - return NO; - } - @autoreleasepool { AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *rawError = nil; @@ -254,7 +250,7 @@ - (BOOL)close { } - (BOOL)close:(NSArray **)errors { - if (_closing || self.mute) { + if (_closing) { return NO; } diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 94ca227..d147391 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -16,13 +16,13 @@ class RootViewController: UIViewController { @IBOutlet private weak var segmentedControl: UISegmentedControl! private var isFirstViewAppearance = true - private var playerViewController1: DLGSimplePlayerViewController? { + private var playerViewController: DLGSimplePlayerViewController? { didSet { - playerViewController1.map { + playerViewController.map { $0.delegate = self $0.isAllowsFrameDrop = true $0.isAutoplay = true - $0.isMute = true +// $0.isMute = true $0.preventFromScreenLock = true $0.restorePlayAfterAppEnterForeground = true $0.minBufferDuration = 0 @@ -59,7 +59,7 @@ class RootViewController: UIViewController { override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - playerViewController1?.stop() + playerViewController?.stop() coverView?.isHidden = false } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { @@ -68,7 +68,7 @@ class RootViewController: UIViewController { override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segue.destination { case let vc as DLGSimplePlayerViewController: - playerViewController1 = vc + playerViewController = vc default: () } @@ -77,16 +77,17 @@ class RootViewController: UIViewController { // MARK: - Play Test private func playDownload1() { - playerViewController1?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" - playerViewController1?.open() + playerViewController?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" + playerViewController?.open() } private func playRTMP1() { let now = Date().timeIntervalSince1970 let time = Date(timeIntervalSince1970: now - 60 * 60 * 24).timeIntervalSince1970 - playerViewController1?.speed = 2 - playerViewController1?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" - playerViewController1?.open() +// playerViewController?.speed = 2 + playerViewController?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" +// playerViewController?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" + playerViewController?.open() } // MARK: - Hard Test @@ -112,16 +113,16 @@ class RootViewController: UIViewController { "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" - playerViewController1?.stop() + playerViewController?.stop() - playerViewController1?.url = url - playerViewController1?.open() + playerViewController?.url = url + playerViewController?.open() } // MARK: - Private Selectors @IBAction private func captureButtonClicked() { - playerViewController1?.player.snapshot() + playerViewController?.player.snapshot() .map { UIImageView(image: $0) } .map { [weak self] in self?.view.addSubview($0) @@ -130,34 +131,34 @@ class RootViewController: UIViewController { } @IBAction private func muteButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected - playerViewController1?.isMute = !sender.isSelected + playerViewController?.isMute = !sender.isSelected } @IBAction private func playOrPauseButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected if sender.isSelected { - if playerViewController1?.status == .paused { - playerViewController1?.play() + if playerViewController?.status == .paused { + playerViewController?.play() } else { playRTMP1() } } else { - playerViewController1?.pause() + playerViewController?.pause() } } @IBAction private func refreshButtonClicked(_ sender: UIButton) { - playerViewController1?.stop() + playerViewController?.stop() playRTMP1() } @IBAction private func stopButtonClicked() { - playerViewController1?.stop() + playerViewController?.stop() } @IBAction private func valueChanged(_ sender: UISlider) { - playerViewController1?.player.brightness = sender.value + playerViewController?.player.brightness = sender.value } @IBAction private func segmentValueChanged(_ sender: UISegmentedControl) { - playerViewController1?.stop() - playerViewController1?.speed = Double(1 << sender.selectedSegmentIndex) + playerViewController?.stop() + playerViewController?.speed = Double(1 << sender.selectedSegmentIndex) playRTMP1() } } From 798148afba1a00b483938a02c02cd448d7ec2f14 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 17:46:58 +0900 Subject: [PATCH 178/215] Fixed: crash by audio instance solving. --- DLGPlayer/DLGPlayer.m | 87 +++++++++---------------- DLGPlayer/codec/DLGPlayerAudioManager.m | 9 ++- 2 files changed, 33 insertions(+), 63 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index e6672d5..d78eef5 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -43,7 +43,6 @@ @interface DLGPlayer () @property (atomic) double mediaSyncPosition; @end -static dispatch_queue_t audioProcessingQueue; static dispatch_queue_t processingQueueStatic; @implementation DLGPlayer @@ -102,8 +101,6 @@ - (void)initVars { } else if (!processingQueueStatic) { processingQueueStatic = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); } - - audioProcessingQueue = dispatch_queue_create("DLGPlayer.audioProcessingQueue", DISPATCH_QUEUE_SERIAL); } - (void)initView { @@ -165,11 +162,7 @@ - (void)open:(NSString *)url { strongSelf.opening = YES; - dispatch_async(audioProcessingQueue, ^{ - if (!strongSelf) { - return; - } - + @autoreleasepool { NSError *error = nil; if ([strongSelf.audio open:&error]) { strongSelf.decoder.audioChannels = [strongSelf.audio channels]; @@ -177,14 +170,15 @@ - (void)open:(NSString *)url { } else { [strongSelf handleError:error]; } - }); - - NSError *error = nil; - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - [strongSelf handleError:error]; - return; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + + NSArray *errors = nil; + [strongSelf.audio close:&errors]; + [strongSelf handleError:error]; + return; + } } dispatch_async(dispatch_get_main_queue(), ^{ @@ -244,26 +238,20 @@ - (void)close { [strongSelf.decoder close]; [strongSelf.view clear]; - dispatch_async(audioProcessingQueue, ^{ - if (!strongSelf) { - return; - } + @autoreleasepool { + NSArray *errors = nil; - @autoreleasepool { - NSArray *errors = nil; + if ([strongSelf.audio close:&errors]) { + [strongSelf clearVars]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; + } else { + [strongSelf clearVars]; - if ([strongSelf.audio close:&errors]) { - [strongSelf clearVars]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; - } else { - [strongSelf clearVars]; - - for (NSError *error in errors) { - [strongSelf handleError:error]; - } + for (NSError *error in errors) { + [strongSelf handleError:error]; } } - }); + } }); } @@ -285,20 +273,13 @@ - (void)play { } }); - - dispatch_async(audioProcessingQueue, ^{ - if (!strongSelf) { - return; - } + @autoreleasepool { + NSError *error = nil; - @autoreleasepool { - NSError *error = nil; - - if (![strongSelf.audio play:&error]) { - [strongSelf handleError:error]; - } + if (![strongSelf.audio play:&error]) { + [strongSelf handleError:error]; } - }); + } [strongSelf runFrameReader]; }); @@ -307,22 +288,12 @@ - (void)play { - (void)pause { self.playing = NO; - __weak typeof(self)weakSelf = self; - - dispatch_async(audioProcessingQueue, ^{ - __strong typeof(self)strongSelf = weakSelf; - - if (!strongSelf) { - return; - } - - @autoreleasepool { - NSError *error = nil; - if (![self.audio pause:&error]) { - [self handleError:error]; - } + @autoreleasepool { + NSError *error = nil; + if (![self.audio pause:&error]) { + [self handleError:error]; } - }); + } } - (UIImage *)snapshot { diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 6b8ba98..18de149 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -19,7 +19,7 @@ #define PREFERRED_SAMPLE_RATE 44100 #define PREFERRED_BUFFER_DURATION 0.023 -OSStatus audioUnitRenderCallback(void *inRefCon, +static OSStatus audioUnitRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, @@ -72,8 +72,6 @@ - (void)dealloc { } [self unregisterNotifications]; - _audioUnit = NULL; - if (_audioData) { free(_audioData); _audioData = NULL; @@ -250,7 +248,7 @@ - (BOOL)close { } - (BOOL)close:(NSArray **)errors { - if (_closing) { + if (_closing || !_opened) { return NO; } @@ -315,6 +313,7 @@ - (BOOL)close:(NSArray **)errors { if (closed) { _opened = NO; + _audioUnit = NULL; } } @@ -481,7 +480,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N @end -OSStatus audioUnitRenderCallback(void *inRefCon, +static OSStatus audioUnitRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, From 56bb325972e9d64ac8068cf63a8cc6d9ed845c30 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 17:58:44 +0900 Subject: [PATCH 179/215] Fixed: crash by audio instance solving. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 18de149..ee9bc25 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -19,7 +19,7 @@ #define PREFERRED_SAMPLE_RATE 44100 #define PREFERRED_BUFFER_DURATION 0.023 -static OSStatus audioUnitRenderCallback(void *inRefCon, +OSStatus audioUnitRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, @@ -297,7 +297,7 @@ - (BOOL)close:(NSArray **)errors { NSError *error = nil; AVAudioSession *session = [AVAudioSession sharedInstance]; - if (![session setActive:NO error:&error]) { + if (![session setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error]) { closed = NO; if (errs != nil) { NSError *error = nil; @@ -480,7 +480,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N @end -static OSStatus audioUnitRenderCallback(void *inRefCon, +OSStatus audioUnitRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, From eab487b9373a481b0a6c0c67abcfb24b7eb63446 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 18:44:47 +0900 Subject: [PATCH 180/215] Fixed: logic of activation or deactivation removed for audio session. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 50 ++++++------------------- 1 file changed, 12 insertions(+), 38 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index ee9bc25..703f3e6 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -91,7 +91,7 @@ - (BOOL)open:(NSError **)error { @autoreleasepool { AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *rawError = nil; - + if (![session setCategory:self.category error:&rawError]) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager @@ -100,28 +100,19 @@ - (BOOL)open:(NSError **)error { andRawError:rawError]; return NO; } - + if (![session setPreferredIOBufferDuration:_bufferDuration error:&rawError]) { if (DLGPlayerUtils.debugEnabled) { NSLog(@"setPreferredIOBufferDuration: %.4f, error: %@", _bufferDuration, rawError); } } - + double prefferedSampleRate = PREFERRED_SAMPLE_RATE; if (![session setPreferredSampleRate:prefferedSampleRate error:&rawError]) { if (DLGPlayerUtils.debugEnabled) { NSLog(@"setPreferredSampleRate: %.4f, error: %@", prefferedSampleRate, rawError); } } - - if (![session setActive:YES error:&rawError]) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioActive - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE"] - andRawError:rawError]; - return NO; - } if (session.currentRoute.outputs.count < 1) { [DLGPlayerUtils createError:error @@ -130,7 +121,7 @@ - (BOOL)open:(NSError **)error { andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; return NO; } - + if (session.outputNumberOfChannels < 1) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager @@ -138,7 +129,7 @@ - (BOOL)open:(NSError **)error { andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL"]]; return NO; } - + double sampleRate = session.sampleRate; if (sampleRate <= 0) { [DLGPlayerUtils createError:error @@ -147,7 +138,7 @@ - (BOOL)open:(NSError **)error { andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE"]]; return NO; } - + float volume = session.outputVolume; if (volume < 0) { [DLGPlayerUtils createError:error @@ -156,16 +147,16 @@ - (BOOL)open:(NSError **)error { andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME"]]; return NO; } - + if (![self initAudioUnitWithSampleRate:sampleRate andRenderCallback:audioUnitRenderCallback error:error]) { return NO; } - + [self registerNotifications]; _sampleRate = sampleRate; _volume = volume; _opened = YES; - + return YES; } } @@ -216,7 +207,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend AURenderCallbackStruct renderCallbackStruct; renderCallbackStruct.inputProc = renderCallback; renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); - + status = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(renderCallbackStruct)); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -227,7 +218,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend andRawError:rawError]; return NO; } - + status = AudioUnitInitialize(_audioUnit); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -248,7 +239,7 @@ - (BOOL)close { } - (BOOL)close:(NSArray **)errors { - if (_closing || !_opened) { + if (_closing) { return NO; } @@ -294,23 +285,6 @@ - (BOOL)close:(NSArray **)errors { } } - NSError *error = nil; - AVAudioSession *session = [AVAudioSession sharedInstance]; - - if (![session setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error]) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotDeactivateAudio - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] - andRawError:rawError]; - [errs addObject:error]; - } - } - if (closed) { _opened = NO; _audioUnit = NULL; From fa56427c7716342abcd819a87ed91b8d5e76968a Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 16 Dec 2019 19:13:10 +0900 Subject: [PATCH 181/215] Fixed: refactoring. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 93 ++++++++++++++----------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 703f3e6..bae0792 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -84,6 +84,16 @@ - (AVAudioSessionCategory)category { return self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; } +- (void)setMute:(BOOL)mute { + _mute = mute; + + if (mute) { + [self pause]; + } else { + [self play]; + } +} + /* * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ @@ -239,7 +249,7 @@ - (BOOL)close { } - (BOOL)close:(NSArray **)errors { - if (_closing) { + if (_closing || !_opened || !_audioUnit) { return NO; } @@ -251,46 +261,44 @@ - (BOOL)close:(NSArray **)errors { BOOL closed = YES; - if (_opened && _audioUnit) { - [self pause]; - [self unregisterNotifications]; - - OSStatus status = AudioUnitUninitialize(_audioUnit); - if (status != noErr) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotUninitAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT"] - andRawError:rawError]; - [errs addObject:error]; - } - } - - status = AudioComponentInstanceDispose(_audioUnit); - if (status != noErr) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotDisposeAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT"] - andRawError:rawError]; - [errs addObject:error]; - } + [self pause]; + [self unregisterNotifications]; + + OSStatus status = AudioUnitUninitialize(_audioUnit); + if (status != noErr) { + closed = NO; + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotUninitAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT"] + andRawError:rawError]; + [errs addObject:error]; } - - if (closed) { - _opened = NO; - _audioUnit = NULL; + } + + status = AudioComponentInstanceDispose(_audioUnit); + if (status != noErr) { + closed = NO; + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotDisposeAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT"] + andRawError:rawError]; + [errs addObject:error]; } } + if (closed) { + _opened = NO; + _audioUnit = NULL; + } + _closing = NO; return closed; @@ -302,14 +310,15 @@ - (BOOL)play { } - (BOOL)play:(NSError **)error { - if (self.mute) { + if (!_opened || !_audioUnit || self.mute) { return _playing; } - if (_opened && _audioUnit) { - OSStatus status = AudioOutputUnitStart(_audioUnit); - _playing = (status == noErr); - if (!_playing) { + OSStatus status = AudioOutputUnitStart(_audioUnit); + _playing = (status == noErr); + + if (!_playing) { + @autoreleasepool { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager From 6ed01bc41b9aeaf8b8b1e99544891a78832a7368 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sun, 22 Mar 2020 22:44:34 +0900 Subject: [PATCH 182/215] Fixed: logic recovered to set active audio session. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index bae0792..0431dff 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -124,6 +124,15 @@ - (BOOL)open:(NSError **)error { } } + if (![session setActive:YES error:&rawError]) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioActive + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE"] + andRawError:rawError]; + return NO; + } + if (session.currentRoute.outputs.count < 1) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager @@ -294,6 +303,23 @@ - (BOOL)close:(NSArray **)errors { } } + NSError *error = nil; + AVAudioSession *session = [AVAudioSession sharedInstance]; + + if (![session setActive:NO error:&error]) { + closed = NO; + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotDeactivateAudio + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] + andRawError:rawError]; + [errs addObject:error]; + } + } + if (closed) { _opened = NO; _audioUnit = NULL; From 4122d35312bd3dfed5af994c4f857610cc1082a9 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 24 Mar 2020 12:13:14 +0900 Subject: [PATCH 183/215] Fixed: clear sound by audio interruption. Fixed: solve weak reference crash. --- DLGPlayer/DLGPlayer.m | 10 +- DLGPlayer/codec/DLGPlayerAudioManager.m | 433 +++++++++++------------- DLGPlayerDemo/RootViewController.swift | 2 +- 3 files changed, 213 insertions(+), 232 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index d78eef5..7ec96f9 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -97,7 +97,7 @@ - (void)initVars { _aframes = [NSMutableArray arrayWithCapacity:128]; if ([DLGPlayerUtils isMetalSupport]) { - _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); + self.processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); } else if (!processingQueueStatic) { processingQueueStatic = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); } @@ -147,14 +147,14 @@ - (void)clearVars { } - (dispatch_queue_t)processingQueue { - return [DLGPlayerUtils isMetalSupport] ? _processingQueue : processingQueueStatic; + return [DLGPlayerUtils isMetalSupport] ? self.processingQueue : processingQueueStatic; } - (void)open:(NSString *)url { __weak typeof(self)weakSelf = self; dispatch_async(self.processingQueue, ^{ - __strong typeof(self)strongSelf = weakSelf; + __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || strongSelf.opening || strongSelf.closing) { return; @@ -497,7 +497,7 @@ - (void)render { if (self.vframes.count <= 0 || !self.decoder.hasVideo || self.notifiedBufferStart) { __weak typeof(self)weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - __strong typeof(self)strongSelf = weakSelf; + __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf) { [strongSelf render]; @@ -530,7 +530,7 @@ - (void)render { __weak typeof(self)weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (t * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - __strong typeof(self)strongSelf = weakSelf; + __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf) { [strongSelf render]; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 0431dff..aeb8516 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -35,12 +35,13 @@ @interface DLGPlayerAudioManager () { double _sampleRate; UInt32 _bitsPerChannel; UInt32 _channelsPerFrame; - AudioUnit _audioUnit; float *_audioData; } +@property (nonatomic) AudioUnit audioUnit; @end @implementation DLGPlayerAudioManager +@synthesize mute = _mute; - (id)init { self = [super init]; @@ -84,173 +85,163 @@ - (AVAudioSessionCategory)category { return self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; } -- (void)setMute:(BOOL)mute { - _mute = mute; - - if (mute) { - [self pause]; - } else { - [self play]; - } -} - /* * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ - (BOOL)open:(NSError **)error { - @autoreleasepool { - AVAudioSession *session = [AVAudioSession sharedInstance]; - NSError *rawError = nil; - - if (![session setCategory:self.category error:&rawError]) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioCategory - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_CATEGORY"] - andRawError:rawError]; - return NO; - } - - if (![session setPreferredIOBufferDuration:_bufferDuration error:&rawError]) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"setPreferredIOBufferDuration: %.4f, error: %@", _bufferDuration, rawError); - } - } - - double prefferedSampleRate = PREFERRED_SAMPLE_RATE; - if (![session setPreferredSampleRate:prefferedSampleRate error:&rawError]) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"setPreferredSampleRate: %.4f, error: %@", prefferedSampleRate, rawError); - } - } - - if (![session setActive:YES error:&rawError]) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioActive - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE"] - andRawError:rawError]; - return NO; - } - - if (session.currentRoute.outputs.count < 1) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioOuput - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; - return NO; - } - - if (session.outputNumberOfChannels < 1) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioChannel - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL"]]; - return NO; - } - - double sampleRate = session.sampleRate; - if (sampleRate <= 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioSampleRate - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE"]]; - return NO; - } - - float volume = session.outputVolume; - if (volume < 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioVolume - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME"]]; - return NO; + AVAudioSession *session = [AVAudioSession sharedInstance]; + NSError *rawError = nil; + + if (![session setCategory:self.category error:&rawError]) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioCategory + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_CATEGORY"] + andRawError:rawError]; + return NO; + } + + if (![session setPreferredIOBufferDuration:_bufferDuration error:&rawError]) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"setPreferredIOBufferDuration: %.4f, error: %@", _bufferDuration, rawError); } - - if (![self initAudioUnitWithSampleRate:sampleRate andRenderCallback:audioUnitRenderCallback error:error]) { - return NO; + } + + double prefferedSampleRate = PREFERRED_SAMPLE_RATE; + if (![session setPreferredSampleRate:prefferedSampleRate error:&rawError]) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"setPreferredSampleRate: %.4f, error: %@", prefferedSampleRate, rawError); } - - [self registerNotifications]; - _sampleRate = sampleRate; - _volume = volume; - _opened = YES; - - return YES; } + + if (![session setActive:YES error:&rawError]) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioActive + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE"] + andRawError:rawError]; + return NO; + } + + if (session.currentRoute.outputs.count == 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioOuput + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; + return NO; + } + + NSInteger channels = session.outputNumberOfChannels; + if (channels <= 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioChannel + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL"]]; + return NO; + } + + double sampleRate = session.sampleRate; + if (sampleRate <= 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioSampleRate + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE"]]; + return NO; + } + + float volume = session.outputVolume; + if (volume < 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioVolume + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME"]]; + return NO; + } + + if (![self initAudioUnitWithSampleRate:sampleRate andRenderCallback:audioUnitRenderCallback error:error]) { + return NO; + } + + [self registerNotifications]; + _sampleRate = sampleRate; + _volume = volume; + _opened = YES; + + return YES; } - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURenderCallback)renderCallback error:(NSError **)error { - @autoreleasepool { - AudioComponentDescription descr = {0}; - descr.componentType = kAudioUnitType_Output; - descr.componentSubType = kAudioUnitSubType_RemoteIO; - descr.componentManufacturer = kAudioUnitManufacturer_Apple; - descr.componentFlags = 0; - descr.componentFlagsMask = 0; - - AudioComponent component = AudioComponentFindNext(NULL, &descr); - OSStatus status = AudioComponentInstanceNew(component, &_audioUnit); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotCreateAudioComponent - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_CREATE_AUDIO_UNIT"] - andRawError:rawError]; - return NO; - } - - AudioStreamBasicDescription streamDescr = {0}; - UInt32 size = sizeof(AudioStreamBasicDescription); - status = AudioUnitGetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotGetAudioStreamDescription - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_GET_AUDIO_STREAM_DESCRIPTION"] - andRawError:rawError]; - return NO; - } - - streamDescr.mSampleRate = sampleRate; - status = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); - if (status != noErr && DLGPlayerUtils.debugEnabled) { - NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); - } - - _bitsPerChannel = streamDescr.mBitsPerChannel; - _channelsPerFrame = streamDescr.mChannelsPerFrame; - - AURenderCallbackStruct renderCallbackStruct; - renderCallbackStruct.inputProc = renderCallback; - renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); - - status = AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(renderCallbackStruct)); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioRenderCallback - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_RENDER_CALLBACK"] - andRawError:rawError]; - return NO; - } - - status = AudioUnitInitialize(_audioUnit); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotInitAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_INIT_AUDIO_UNIT"] - andRawError:rawError]; - return NO; - } - - return YES; + AudioComponentDescription descr = {0}; + descr.componentType = kAudioUnitType_Output; + descr.componentSubType = kAudioUnitSubType_RemoteIO; + descr.componentManufacturer = kAudioUnitManufacturer_Apple; + descr.componentFlags = 0; + descr.componentFlagsMask = 0; + + AudioUnit audioUnit = NULL; + AudioComponent component = AudioComponentFindNext(NULL, &descr); + OSStatus status = AudioComponentInstanceNew(component, &audioUnit); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotCreateAudioComponent + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_CREATE_AUDIO_UNIT"] + andRawError:rawError]; + return NO; } + + self.audioUnit = audioUnit; + + AudioStreamBasicDescription streamDescr = {0}; + UInt32 size = sizeof(AudioStreamBasicDescription); + status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotGetAudioStreamDescription + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_GET_AUDIO_STREAM_DESCRIPTION"] + andRawError:rawError]; + return NO; + } + + streamDescr.mSampleRate = sampleRate; + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); + if (status != noErr && DLGPlayerUtils.debugEnabled) { + NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); + } + + _bitsPerChannel = streamDescr.mBitsPerChannel; + _channelsPerFrame = streamDescr.mChannelsPerFrame; + + AURenderCallbackStruct renderCallbackStruct; + renderCallbackStruct.inputProc = renderCallback; + renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); + + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(AURenderCallbackStruct)); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioRenderCallback + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_RENDER_CALLBACK"] + andRawError:rawError]; + return NO; + } + + status = AudioUnitInitialize(audioUnit); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotInitAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_INIT_AUDIO_UNIT"] + andRawError:rawError]; + return NO; + } + + return YES; } - (BOOL)close { @@ -258,22 +249,22 @@ - (BOOL)close { } - (BOOL)close:(NSArray **)errors { - if (_closing || !_opened || !_audioUnit) { + if (_closing) { return NO; } _closing = YES; - @autoreleasepool { - NSMutableArray *errs = nil; - if (errors != nil) errs = [NSMutableArray array]; - - BOOL closed = YES; - + NSMutableArray *errs = nil; + if (errors != nil) errs = [NSMutableArray array]; + + BOOL closed = YES; + + if (_opened && self.audioUnit) { [self pause]; [self unregisterNotifications]; - OSStatus status = AudioUnitUninitialize(_audioUnit); + OSStatus status = AudioUnitUninitialize(self.audioUnit); if (status != noErr) { closed = NO; if (errs != nil) { @@ -288,7 +279,7 @@ - (BOOL)close:(NSArray **)errors { } } - status = AudioComponentInstanceDispose(_audioUnit); + status = AudioComponentInstanceDispose(self.audioUnit); if (status != noErr) { closed = NO; if (errs != nil) { @@ -305,30 +296,29 @@ - (BOOL)close:(NSArray **)errors { NSError *error = nil; AVAudioSession *session = [AVAudioSession sharedInstance]; - + if (![session setActive:NO error:&error]) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotDeactivateAudio - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] - andRawError:rawError]; - [errs addObject:error]; - } + closed = NO; + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotDeactivateAudio + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] + andRawError:rawError]; + [errs addObject:error]; + } } if (closed) { _opened = NO; - _audioUnit = NULL; } - - _closing = NO; - - return closed; } + + _closing = NO; + + return closed; } - (BOOL)play { @@ -336,15 +326,14 @@ - (BOOL)play { } - (BOOL)play:(NSError **)error { - if (!_opened || !_audioUnit || self.mute) { + if (self.mute) { return _playing; } - OSStatus status = AudioOutputUnitStart(_audioUnit); - _playing = (status == noErr); - - if (!_playing) { - @autoreleasepool { + if (_opened && self.audioUnit != NULL) { + OSStatus status = AudioOutputUnitStart(self.audioUnit); + _playing = (status == noErr); + if (!_playing) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager @@ -361,8 +350,8 @@ - (BOOL)pause { } - (BOOL)pause:(NSError **)error { - if (_playing && _audioUnit) { - OSStatus status = AudioOutputUnitStop(_audioUnit); + if (_playing && self.audioUnit != NULL) { + OSStatus status = AudioOutputUnitStop(self.audioUnit); _playing = !(status == noErr); if (_playing) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -383,9 +372,7 @@ - (OSStatus)render:(AudioBufferList *)ioData count:(UInt32)inNumberFrames { memset(buf.mData, 0, buf.mDataByteSize); } - if (!_playing || _frameReaderBlock == nil) { - return noErr; - } + if (!_playing || _frameReaderBlock == nil) return noErr; _frameReaderBlock(_audioData, inNumberFrames, _channelsPerFrame); @@ -423,37 +410,33 @@ - (UInt32)channels { #pragma mark - Notifications - (void)registerNotifications { - @autoreleasepool { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self - selector:@selector(notifyAudioSessionRouteChanged:) - name:AVAudioSessionRouteChangeNotification - object:nil]; - [nc addObserver:self - selector:@selector(notifyAudioSessionInterruptionNotification:) - name:AVAudioSessionInterruptionNotification - object:nil]; - - if (!_registeredKVO) { - AVAudioSession *session = [AVAudioSession sharedInstance]; - [session addObserver:self - forKeyPath:@"outputVolume" - options:0 - context:nil]; - _registeredKVO = YES; - } + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(notifyAudioSessionRouteChanged:) + name:AVAudioSessionRouteChangeNotification + object:nil]; + [nc addObserver:self + selector:@selector(notifyAudioSessionInterruptionNotification:) + name:AVAudioSessionInterruptionNotification + object:nil]; + + if (!_registeredKVO) { + AVAudioSession *session = [AVAudioSession sharedInstance]; + [session addObserver:self + forKeyPath:@"outputVolume" + options:0 + context:nil]; + _registeredKVO = YES; } } - (void)unregisterNotifications { - @autoreleasepool { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc removeObserver:self]; - if (_registeredKVO) { - AVAudioSession *session = [AVAudioSession sharedInstance]; - [session removeObserver:self forKeyPath:@"outputVolume"]; - _registeredKVO = NO; - } + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self]; + if (_registeredKVO) { + AVAudioSession *session = [AVAudioSession sharedInstance]; + [session removeObserver:self forKeyPath:@"outputVolume"]; + _registeredKVO = NO; } } @@ -479,11 +462,9 @@ - (void)notifyAudioSessionInterruptionNotification:(NSNotification *)notif { } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - @autoreleasepool { - AVAudioSession *session = [AVAudioSession sharedInstance]; - if (object == session && [keyPath isEqualToString:@"outputVolume"]) { - self.volume = session.outputVolume; - } + AVAudioSession *session = [AVAudioSession sharedInstance]; + if (object == session && [keyPath isEqualToString:@"outputVolume"]) { + self.volume = session.outputVolume; } } diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index d147391..eb50d18 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -85,7 +85,7 @@ class RootViewController: UIViewController { let time = Date(timeIntervalSince1970: now - 60 * 60 * 24).timeIntervalSince1970 // playerViewController?.speed = 2 - playerViewController?.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACQLV?token=b6e503e4-f47c-4238-baca-51cbdfc10001" + playerViewController?.url = "rtmps://media009.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10002" // playerViewController?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" playerViewController?.open() } From 8c6eca5b338cf3be3fd26224d96aac453d5516d9 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 24 Mar 2020 12:25:44 +0900 Subject: [PATCH 184/215] Fixed: solve weak reference crash. --- DLGPlayer/DLGPlayer.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 7ec96f9..f770ccf 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -259,7 +259,7 @@ - (void)play { __weak typeof(self)weakSelf = self; dispatch_async(self.processingQueue, ^{ - __strong typeof(self)strongSelf = weakSelf; + __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { return; From 19dd9a97fa8ef5993b0ffde8042b2ce152c75fc0 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 24 Mar 2020 12:35:20 +0900 Subject: [PATCH 185/215] Fixed: change to property using variable. --- DLGPlayer/DLGSimplePlayerViewController.m | 52 +++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index ac16c9f..9bc7a2e 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -21,7 +21,7 @@ @interface DLGSimplePlayerViewController () { BOOL restorePlay; } -@property (nonatomic, readwrite) DLGPlayer *player; +@property (nonatomic, strong) DLGPlayer *player; @property (nonatomic, readwrite) DLGPlayerStatus status; @end @@ -77,7 +77,7 @@ - (BOOL)hasUrl { } - (BOOL)isPlaying { - return _player.playing; + return self.player.playing; } - (void)setStatus:(DLGPlayerStatus)status { @@ -92,83 +92,83 @@ - (void)setStatus:(DLGPlayerStatus)status { } - (BOOL)isMute { - return _player.mute; + return self.player.mute; } - (void)setIsMute:(BOOL)isMute { - _player.mute = isMute; + self.player.mute = isMute; } - (double)minBufferDuration { - return _player.minBufferDuration; + return self.player.minBufferDuration; } - (void)setMinBufferDuration:(double)minBufferDuration { - _player.minBufferDuration = minBufferDuration; + self.player.minBufferDuration = minBufferDuration; } - (double)maxBufferDuration { - return _player.maxBufferDuration; + return self.player.maxBufferDuration; } - (void)setMaxBufferDuration:(double)maxBufferDuration { - _player.maxBufferDuration = maxBufferDuration; + self.player.maxBufferDuration = maxBufferDuration; } - (BOOL)isAllowsFrameDrop { - return _player.allowsFrameDrop; + return self.player.allowsFrameDrop; } - (void)setIsAllowsFrameDrop:(BOOL)isAllowsFrameDrop { - _player.allowsFrameDrop = isAllowsFrameDrop; + self.player.allowsFrameDrop = isAllowsFrameDrop; } - (double)speed { - return _player.speed; + return self.player.speed; } - (void)setSpeed:(double)speed { - _player.speed = speed; + self.player.speed = speed; } #pragma mark - Init - (void)initAll { - _player = [[DLGPlayer alloc] init]; + self.player = [[DLGPlayer alloc] init]; _status = DLGPlayerStatusNone; _controlStatus = [[DLGPlayerControlStatus alloc] initWithStatus:_status]; } - (void)open { self.status = DLGPlayerStatusOpening; - [_player open:_url]; + [self.player open:_url]; } - (void)play { [UIApplication sharedApplication].idleTimerDisabled = _preventFromScreenLock; - [_player play]; + [self.player play]; self.status = DLGPlayerStatusPlaying; } - (void)replay { - _player.position = 0; + self.player.position = 0; [self play]; } - (void)pause { [UIApplication sharedApplication].idleTimerDisabled = NO; - [_player pause]; + [self.player pause]; self.status = DLGPlayerStatusPaused; } - (void)stop { self.status = DLGPlayerStatusClosing; [UIApplication sharedApplication].idleTimerDisabled = NO; - [_player close]; + [self.player close]; } #pragma mark - UI - (void)addPlayerView { - UIView *v = _player.playerView; + UIView *v = self.player.playerView; v.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:v]; @@ -194,12 +194,12 @@ - (void)registerNotification { name:UIApplicationDidEnterBackgroundNotification object:nil]; [nc addObserver:self selector:@selector(notifyAppWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; - [nc addObserver:self selector:@selector(notifyPlayerOpened:) name:DLGPlayerNotificationOpened object:_player]; - [nc addObserver:self selector:@selector(notifyPlayerClosed:) name:DLGPlayerNotificationClosed object:_player]; - [nc addObserver:self selector:@selector(notifyPlayerEOF:) name:DLGPlayerNotificationEOF object:_player]; - [nc addObserver:self selector:@selector(notifyPlayerBufferStateChanged:) name:DLGPlayerNotificationBufferStateChanged object:_player]; - [nc addObserver:self selector:@selector(notifyPlayerRenderBegan:) name:DLGPlayerNotificationRenderBegan object:_player]; - [nc addObserver:self selector:@selector(notifyPlayerError:) name:DLGPlayerNotificationError object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerOpened:) name:DLGPlayerNotificationOpened object:self.player]; + [nc addObserver:self selector:@selector(notifyPlayerClosed:) name:DLGPlayerNotificationClosed object:self.player]; + [nc addObserver:self selector:@selector(notifyPlayerEOF:) name:DLGPlayerNotificationEOF object:self.player]; + [nc addObserver:self selector:@selector(notifyPlayerBufferStateChanged:) name:DLGPlayerNotificationBufferStateChanged object:self.player]; + [nc addObserver:self selector:@selector(notifyPlayerRenderBegan:) name:DLGPlayerNotificationRenderBegan object:self.player]; + [nc addObserver:self selector:@selector(notifyPlayerError:) name:DLGPlayerNotificationError object:self.player]; } - (void)unregisterNotification { @@ -207,7 +207,7 @@ - (void)unregisterNotification { } - (void)notifyAppDidEnterBackground:(NSNotification *)notif { - if (_player.playing) { + if (self.player.playing) { [self pause]; if (_restorePlayAfterAppEnterForeground) restorePlay = YES; } From e3cc86195ae8c400c442656f0de9adca9bac8a44 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 24 Mar 2020 13:34:05 +0900 Subject: [PATCH 186/215] Fixed: solve critical issue. --- DLGPlayer/DLGPlayer.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index f770ccf..a5ca696 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -97,7 +97,7 @@ - (void)initVars { _aframes = [NSMutableArray arrayWithCapacity:128]; if ([DLGPlayerUtils isMetalSupport]) { - self.processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); + _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); } else if (!processingQueueStatic) { processingQueueStatic = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); } @@ -147,7 +147,7 @@ - (void)clearVars { } - (dispatch_queue_t)processingQueue { - return [DLGPlayerUtils isMetalSupport] ? self.processingQueue : processingQueueStatic; + return [DLGPlayerUtils isMetalSupport] ? _processingQueue : processingQueueStatic; } - (void)open:(NSString *)url { From 646aa49924d180663168c1c60e8ef5277862dd5a Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 24 Mar 2020 16:31:28 +0900 Subject: [PATCH 187/215] Fixed: guard to pause for mute. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 30 +++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index aeb8516..2da9e22 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -36,8 +36,8 @@ @interface DLGPlayerAudioManager () { UInt32 _bitsPerChannel; UInt32 _channelsPerFrame; float *_audioData; + AudioUnit _audioUnit; } -@property (nonatomic) AudioUnit audioUnit; @end @implementation DLGPlayerAudioManager @@ -163,6 +163,7 @@ - (BOOL)open:(NSError **)error { } [self registerNotifications]; + _sampleRate = sampleRate; _volume = volume; _opened = YES; @@ -191,8 +192,6 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } - self.audioUnit = audioUnit; - AudioStreamBasicDescription streamDescr = {0}; UInt32 size = sizeof(AudioStreamBasicDescription); status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); @@ -208,7 +207,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend streamDescr.mSampleRate = sampleRate; status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); - if (status != noErr && DLGPlayerUtils.debugEnabled) { + if (DLGPlayerUtils.debugEnabled && status != noErr) { NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); } @@ -218,7 +217,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend AURenderCallbackStruct renderCallbackStruct; renderCallbackStruct.inputProc = renderCallback; renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); - + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(AURenderCallbackStruct)); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -241,7 +240,10 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend return NO; } + _audioUnit = audioUnit; + return YES; + } - (BOOL)close { @@ -260,11 +262,11 @@ - (BOOL)close:(NSArray **)errors { BOOL closed = YES; - if (_opened && self.audioUnit) { + if (_opened) { [self pause]; [self unregisterNotifications]; - OSStatus status = AudioUnitUninitialize(self.audioUnit); + OSStatus status = AudioUnitUninitialize(_audioUnit); if (status != noErr) { closed = NO; if (errs != nil) { @@ -279,7 +281,7 @@ - (BOOL)close:(NSArray **)errors { } } - status = AudioComponentInstanceDispose(self.audioUnit); + status = AudioComponentInstanceDispose(_audioUnit); if (status != noErr) { closed = NO; if (errs != nil) { @@ -330,8 +332,8 @@ - (BOOL)play:(NSError **)error { return _playing; } - if (_opened && self.audioUnit != NULL) { - OSStatus status = AudioOutputUnitStart(self.audioUnit); + if (_opened) { + OSStatus status = AudioOutputUnitStart(_audioUnit); _playing = (status == noErr); if (!_playing) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -350,8 +352,12 @@ - (BOOL)pause { } - (BOOL)pause:(NSError **)error { - if (_playing && self.audioUnit != NULL) { - OSStatus status = AudioOutputUnitStop(self.audioUnit); + if (self.mute) { + return _playing; + } + + if (_playing) { + OSStatus status = AudioOutputUnitStop(_audioUnit); _playing = !(status == noErr); if (_playing) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; From 74c76261a39bab6d7e12cfdc849c13edb98efde8 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 25 Mar 2020 15:13:13 +0900 Subject: [PATCH 188/215] Updated: change limit size. --- DLGPlayer/view/MetalPlayerView.m | 2 +- DLGPlayerDemo/RootViewController.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/view/MetalPlayerView.m b/DLGPlayer/view/MetalPlayerView.m index bf66a12..19d136c 100644 --- a/DLGPlayer/view/MetalPlayerView.m +++ b/DLGPlayer/view/MetalPlayerView.m @@ -150,7 +150,7 @@ - (void)initProperties { } threadsPerThreadgroup = MTLSizeMake(16, 16, 1); - threadgroupsPerGrid = MTLSizeMake(2048 / threadsPerThreadgroup.width, 1536 / threadsPerThreadgroup.height, 1); + threadgroupsPerGrid = MTLSizeMake(3840 / threadsPerThreadgroup.width, 2160 / threadsPerThreadgroup.height, 1); } #pragma mark - Public Methods (DLGPlayerVideoFrame) diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index eb50d18..6fb5e4a 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -85,7 +85,7 @@ class RootViewController: UIViewController { let time = Date(timeIntervalSince1970: now - 60 * 60 * 24).timeIntervalSince1970 // playerViewController?.speed = 2 - playerViewController?.url = "rtmps://media009.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10002" + playerViewController?.url = "rtmps://mediajp005.toastcam.com:10080/flvplayback/AAAENYZ?token=b6e503e4-f47c-4238-baca-51cbdfc10003" // playerViewController?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" playerViewController?.open() } From 7739b7c6811ed743f9547e3ba8090d0093d026d5 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 27 Mar 2020 09:22:20 +0900 Subject: [PATCH 189/215] Updated: add processor macro to check is running on simulator. --- DLGPlayer/codec/DLGPlayerDecoder.m | 2 +- DLGPlayer/common/DLGPlayerUtils.m | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index 4d1bd99..20b8348 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -489,7 +489,7 @@ - (NSArray *)readFrames { int ret = avcodec_send_packet(context, packet); if (ret != 0) { if (DLGPlayerUtils.debugEnabled) { - NSLog(@"avcodec_send_packet: %d", ret); + NSLog(@"avcodec_send_packet: %d, size: %d", ret); } return nil; } diff --git a/DLGPlayer/common/DLGPlayerUtils.m b/DLGPlayer/common/DLGPlayerUtils.m index 5b0f682..3f54128 100644 --- a/DLGPlayer/common/DLGPlayerUtils.m +++ b/DLGPlayer/common/DLGPlayerUtils.m @@ -61,15 +61,17 @@ + (NSString *)durationStringFromSeconds:(int)seconds { } + (BOOL)isMetalSupport { - if (@available(iOS 9.0, *)) { - if (isMetalSupportChecked) { + #if !TARGET_IPHONE_SIMULATOR + if (@available(iOS 9.0, *)) { + if (isMetalSupportChecked) { + return isMetalSupport; + } + + isMetalSupport = MTLCreateSystemDefaultDevice() != nil; + isMetalSupportChecked = YES; return isMetalSupport; } - - isMetalSupport = MTLCreateSystemDefaultDevice() != nil; - isMetalSupportChecked = YES; - return isMetalSupport; - } + #endif return NO; } From 57eda75f1ee5dbf7ed87db880e7c9a64cbe7f4e6 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 20 Apr 2020 13:55:51 +0900 Subject: [PATCH 190/215] Fixed: audio processing. --- DLGPlayer/DLGPlayer.m | 6 +++--- DLGPlayer/codec/DLGPlayerAudioManager.m | 11 ++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index a5ca696..09f9391 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -222,18 +222,18 @@ - (void)open:(NSString *)url { } - (void)close { - [self pause]; - __weak typeof(self)weakSelf = self; dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; + if (!strongSelf || strongSelf.closing) { return; } strongSelf.closing = YES; - + + [strongSelf pause]; [strongSelf.decoder prepareClose]; [strongSelf.decoder close]; [strongSelf.view clear]; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 2da9e22..bae803d 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -263,7 +263,6 @@ - (BOOL)close:(NSArray **)errors { BOOL closed = YES; if (_opened) { - [self pause]; [self unregisterNotifications]; OSStatus status = AudioUnitUninitialize(_audioUnit); @@ -352,10 +351,6 @@ - (BOOL)pause { } - (BOOL)pause:(NSError **)error { - if (self.mute) { - return _playing; - } - if (_playing) { OSStatus status = AudioOutputUnitStop(_audioUnit); _playing = !(status == noErr); @@ -372,14 +367,16 @@ - (BOOL)pause:(NSError **)error { } - (OSStatus)render:(AudioBufferList *)ioData count:(UInt32)inNumberFrames { + if (!_playing || _frameReaderBlock == nil) { + return noErr; + } + UInt32 num = ioData->mNumberBuffers; for (UInt32 i = 0; i < num; ++i) { AudioBuffer buf = ioData->mBuffers[i]; memset(buf.mData, 0, buf.mDataByteSize); } - if (!_playing || _frameReaderBlock == nil) return noErr; - _frameReaderBlock(_audioData, inNumberFrames, _channelsPerFrame); if (_bitsPerChannel == 32) { From e1a7401fefc796a8e7aba1e1fa7c991670ef446f Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 21 Apr 2020 13:02:41 +0900 Subject: [PATCH 191/215] Updated: change working dispatch queue of audio to other new static dispatch queue. --- DLGPlayer/DLGPlayer.m | 156 ++++++++++++++++-------- DLGPlayer/codec/DLGPlayerAudioManager.h | 1 - DLGPlayer/codec/DLGPlayerAudioManager.m | 21 +--- 3 files changed, 111 insertions(+), 67 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 09f9391..fd8ac86 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -43,9 +43,14 @@ @interface DLGPlayer () @property (atomic) double mediaSyncPosition; @end +static dispatch_queue_t audioProcessingQueue; static dispatch_queue_t processingQueueStatic; @implementation DLGPlayer +{ +@private + dispatch_block_t processingBlock; +} - (id)init { self = [super init]; @@ -69,6 +74,7 @@ - (void)initAll { } - (void)initVars { + processingBlock = NULL; _frameDropDuration = DLGPlayerFrameDropDuration; _minBufferDuration = DLGPlayerMinBufferDuration; _maxBufferDuration = DLGPlayerMaxBufferDuration; @@ -96,6 +102,10 @@ - (void)initVars { _vframes = [NSMutableArray arrayWithCapacity:128]; _aframes = [NSMutableArray arrayWithCapacity:128]; + if (!audioProcessingQueue) { + audioProcessingQueue = dispatch_queue_create("DLGPlayer.audioProcessingQueue", DISPATCH_QUEUE_SERIAL); + } + if ([DLGPlayerUtils isMetalSupport]) { _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); } else if (!processingQueueStatic) { @@ -150,10 +160,23 @@ - (dispatch_queue_t)processingQueue { return [DLGPlayerUtils isMetalSupport] ? _processingQueue : processingQueueStatic; } +- (void)cancelProcessing { + if (processingBlock) { + dispatch_block_cancel(processingBlock); + processingBlock = NULL; + } +} + - (void)open:(NSString *)url { + if (self.opening || self.closing) { + return; + } + + [self cancelProcessing]; + __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ + processingBlock = dispatch_block_create(0, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || strongSelf.opening || strongSelf.closing) { @@ -162,20 +185,31 @@ - (void)open:(NSString *)url { strongSelf.opening = YES; + if (!strongSelf.mute) { + dispatch_async(audioProcessingQueue, ^{ + if ([strongSelf.audio open:nil]) { + strongSelf.decoder.audioChannels = [strongSelf.audio channels]; + strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + } + }); + } + @autoreleasepool { NSError *error = nil; - if ([strongSelf.audio open:&error]) { - strongSelf.decoder.audioChannels = [strongSelf.audio channels]; - strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; - } else { - [strongSelf handleError:error]; - } - if (![strongSelf.decoder open:url error:&error]) { strongSelf.opening = NO; + + if (!strongSelf.mute) { + dispatch_async(audioProcessingQueue, ^{ + [strongSelf.audio close:nil]; + }); + } - NSArray *errors = nil; - [strongSelf.audio close:&errors]; [strongSelf handleError:error]; return; } @@ -200,31 +234,34 @@ - (void)open:(NSString *)url { ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; } - strongSelf.duration = self.decoder.duration; - strongSelf.metadata = self.decoder.metadata; + strongSelf.duration = strongSelf.decoder.duration; + strongSelf.metadata = strongSelf.decoder.metadata; strongSelf.opening = NO; strongSelf.buffering = NO; strongSelf.playing = NO; strongSelf.bufferedDuration = 0; strongSelf.mediaPosition = 0; strongSelf.mediaSyncTime = 0; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - strongSelf.opened = YES; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; }); }); + + dispatch_async(self.processingQueue, processingBlock); } - (void)close { + if (self.closing) { + return; + } + + [self cancelProcessing]; + [self pauseInternally]; + __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ + processingBlock = dispatch_block_create(0, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || strongSelf.closing) { @@ -233,32 +270,29 @@ - (void)close { strongSelf.closing = YES; - [strongSelf pause]; + if (!strongSelf.mute) { + dispatch_async(audioProcessingQueue, ^{ + [strongSelf.audio close:nil]; + }); + } + [strongSelf.decoder prepareClose]; [strongSelf.decoder close]; [strongSelf.view clear]; - - @autoreleasepool { - NSArray *errors = nil; - - if ([strongSelf.audio close:&errors]) { - [strongSelf clearVars]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; - } else { - [strongSelf clearVars]; - - for (NSError *error in errors) { - [strongSelf handleError:error]; - } - } - } + [strongSelf clearVars]; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; }); + + dispatch_async(self.processingQueue, processingBlock); } - (void)play { + [self cancelProcessing]; + __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ + processingBlock = dispatch_block_create(0, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { @@ -272,28 +306,53 @@ - (void)play { [strongSelf render]; } }); - - @autoreleasepool { - NSError *error = nil; - - if (![strongSelf.audio play:&error]) { - [strongSelf handleError:error]; - } + + if (!strongSelf.mute) { + dispatch_async(audioProcessingQueue, ^{ + [strongSelf.audio play:nil]; + }); } [strongSelf runFrameReader]; }); + + dispatch_async(self.processingQueue, processingBlock); } - (void)pause { - self.playing = NO; + [self cancelProcessing]; - @autoreleasepool { - NSError *error = nil; - if (![self.audio pause:&error]) { - [self handleError:error]; + __weak typeof(self)weakSelf = self; + + processingBlock = dispatch_block_create(0, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (!strongSelf) { + return; } + + [strongSelf pauseInternally]; + }); + + dispatch_async(self.processingQueue, processingBlock); +} + +- (void)pauseInternally { + self.playing = NO; + + if (self.mute) { + return; } + + __weak typeof(self)weakSelf = self; + + dispatch_async(audioProcessingQueue, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf) { + [strongSelf.audio pause:nil]; + } + }); } - (UIImage *)snapshot { @@ -668,7 +727,6 @@ - (void)setSpeed:(double)speed { - (void)setMute:(BOOL)mute { _mute = mute; - self.audio.mute = mute; } #pragma mark - Handle Error diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.h b/DLGPlayer/codec/DLGPlayerAudioManager.h index 137b182..34676a9 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.h +++ b/DLGPlayer/codec/DLGPlayerAudioManager.h @@ -12,7 +12,6 @@ typedef void(^DLGPlayerAudioManagerFrameReaderBlock)(float *data, UInt32 num, UI @interface DLGPlayerAudioManager : NSObject -@property (nonatomic) BOOL mute; @property (nonatomic, copy) DLGPlayerAudioManagerFrameReaderBlock frameReaderBlock; @property (nonatomic) float volume; @property (nonatomic) NSTimeInterval bufferDuration; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index bae803d..664ae42 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -41,7 +41,6 @@ @interface DLGPlayerAudioManager () { @end @implementation DLGPlayerAudioManager -@synthesize mute = _mute; - (id)init { self = [super init]; @@ -52,7 +51,6 @@ - (id)init { } - (void)initVars { - self.mute = NO; _registeredKVO = NO; _opened = NO; _closing = NO; @@ -79,12 +77,6 @@ - (void)dealloc { } } -#pragma mark - Added by Steve Kim. - -- (AVAudioSessionCategory)category { - return self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; -} - /* * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ @@ -92,7 +84,7 @@ - (BOOL)open:(NSError **)error { AVAudioSession *session = [AVAudioSession sharedInstance]; NSError *rawError = nil; - if (![session setCategory:self.category error:&rawError]) { + if (![session setCategory:AVAudioSessionCategorySoloAmbient error:&rawError]) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager andCode:DLGPlayerErrorCodeCannotSetAudioCategory @@ -263,6 +255,7 @@ - (BOOL)close:(NSArray **)errors { BOOL closed = YES; if (_opened) { + [self pause]; [self unregisterNotifications]; OSStatus status = AudioUnitUninitialize(_audioUnit); @@ -327,10 +320,6 @@ - (BOOL)play { } - (BOOL)play:(NSError **)error { - if (self.mute) { - return _playing; - } - if (_opened) { OSStatus status = AudioOutputUnitStart(_audioUnit); _playing = (status == noErr); @@ -367,16 +356,14 @@ - (BOOL)pause:(NSError **)error { } - (OSStatus)render:(AudioBufferList *)ioData count:(UInt32)inNumberFrames { - if (!_playing || _frameReaderBlock == nil) { - return noErr; - } - UInt32 num = ioData->mNumberBuffers; for (UInt32 i = 0; i < num; ++i) { AudioBuffer buf = ioData->mBuffers[i]; memset(buf.mData, 0, buf.mDataByteSize); } + if (!_playing || _frameReaderBlock == nil) return noErr; + _frameReaderBlock(_audioData, inNumberFrames, _channelsPerFrame); if (_bitsPerChannel == 32) { From 5598ee7a1503e8482b5f8b1fe08379fabb3d84ed Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 21 Apr 2020 18:11:01 +0900 Subject: [PATCH 192/215] Fixed: solve crash. --- DLGPlayer/DLGPlayer.m | 70 ++- DLGPlayer/DLGSimplePlayerViewController.m | 4 + DLGPlayer/codec/DLGPlayerAudioManager.h | 1 + DLGPlayer/codec/DLGPlayerAudioManager.m | 513 ++++++++++++---------- DLGPlayerDemo/Base.lproj/Main.storyboard | 204 +-------- DLGPlayerDemo/RootViewController.swift | 176 ++++---- 6 files changed, 401 insertions(+), 567 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index fd8ac86..97727aa 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -61,6 +61,8 @@ - (id)init { } - (void)dealloc { + [self cancelProcessing]; + if (DLGPlayerUtils.debugEnabled) { NSLog(@"DLGPlayer dealloc"); } @@ -85,7 +87,6 @@ - (void)initVars { _renderBegan = NO; _requestSeekPosition = 0; _speed = 1.0; - _renderingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); self.buffering = NO; self.closing = NO; @@ -97,20 +98,17 @@ - (void)initVars { self.mediaPosition = 0; self.playingAudioFrameDataPosition = 0; self.playingAudioFrame = nil; + _aFramesLock = dispatch_semaphore_create(1); _vFramesLock = dispatch_semaphore_create(1); _vframes = [NSMutableArray arrayWithCapacity:128]; _aframes = [NSMutableArray arrayWithCapacity:128]; + _renderingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); + _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); if (!audioProcessingQueue) { audioProcessingQueue = dispatch_queue_create("DLGPlayer.audioProcessingQueue", DISPATCH_QUEUE_SERIAL); } - - if ([DLGPlayerUtils isMetalSupport]) { - _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); - } else if (!processingQueueStatic) { - processingQueueStatic = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); - } } - (void)initView { @@ -156,10 +154,6 @@ - (void)clearVars { self.frameDropped = NO; } -- (dispatch_queue_t)processingQueue { - return [DLGPlayerUtils isMetalSupport] ? _processingQueue : processingQueueStatic; -} - - (void)cancelProcessing { if (processingBlock) { dispatch_block_cancel(processingBlock); @@ -185,30 +179,26 @@ - (void)open:(NSString *)url { strongSelf.opening = YES; - if (!strongSelf.mute) { - dispatch_async(audioProcessingQueue, ^{ - if ([strongSelf.audio open:nil]) { - strongSelf.decoder.audioChannels = [strongSelf.audio channels]; - strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - } - }); - } + dispatch_async(audioProcessingQueue, ^{ + if ([strongSelf.audio open:nil]) { + strongSelf.decoder.audioChannels = [strongSelf.audio channels]; + strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + } + }); @autoreleasepool { NSError *error = nil; if (![strongSelf.decoder open:url error:&error]) { strongSelf.opening = NO; - if (!strongSelf.mute) { - dispatch_async(audioProcessingQueue, ^{ - [strongSelf.audio close:nil]; - }); - } + dispatch_async(audioProcessingQueue, ^{ + [strongSelf.audio close:nil]; + }); [strongSelf handleError:error]; return; @@ -256,12 +246,11 @@ - (void)close { return; } - [self cancelProcessing]; [self pauseInternally]; __weak typeof(self)weakSelf = self; - processingBlock = dispatch_block_create(0, ^{ + dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || strongSelf.closing) { @@ -270,11 +259,9 @@ - (void)close { strongSelf.closing = YES; - if (!strongSelf.mute) { - dispatch_async(audioProcessingQueue, ^{ - [strongSelf.audio close:nil]; - }); - } + dispatch_async(audioProcessingQueue, ^{ + [strongSelf.audio close:nil]; + }); [strongSelf.decoder prepareClose]; [strongSelf.decoder close]; @@ -283,8 +270,6 @@ - (void)close { [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; }); - - dispatch_async(self.processingQueue, processingBlock); } - (void)play { @@ -307,11 +292,9 @@ - (void)play { } }); - if (!strongSelf.mute) { - dispatch_async(audioProcessingQueue, ^{ - [strongSelf.audio play:nil]; - }); - } + dispatch_async(audioProcessingQueue, ^{ + [strongSelf.audio play:nil]; + }); [strongSelf runFrameReader]; }); @@ -727,6 +710,7 @@ - (void)setSpeed:(double)speed { - (void)setMute:(BOOL)mute { _mute = mute; + self.audio.mute = mute; } #pragma mark - Handle Error diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 9bc7a2e..0e84c5f 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -27,6 +27,10 @@ @interface DLGSimplePlayerViewController () { @implementation DLGSimplePlayerViewController +- (void)dealloc { + NSLog(@"DLGSimplePlayerViewController dealloc"); +} + #pragma mark - Constructors - (instancetype)init { self = [super init]; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.h b/DLGPlayer/codec/DLGPlayerAudioManager.h index 34676a9..137b182 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.h +++ b/DLGPlayer/codec/DLGPlayerAudioManager.h @@ -12,6 +12,7 @@ typedef void(^DLGPlayerAudioManagerFrameReaderBlock)(float *data, UInt32 num, UI @interface DLGPlayerAudioManager : NSObject +@property (nonatomic) BOOL mute; @property (nonatomic, copy) DLGPlayerAudioManagerFrameReaderBlock frameReaderBlock; @property (nonatomic) float volume; @property (nonatomic) NSTimeInterval bufferDuration; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 664ae42..b72fcd0 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -19,7 +19,7 @@ #define PREFERRED_SAMPLE_RATE 44100 #define PREFERRED_BUFFER_DURATION 0.023 -OSStatus audioUnitRenderCallback(void *inRefCon, +static OSStatus audioUnitRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, @@ -41,6 +41,7 @@ @interface DLGPlayerAudioManager () { @end @implementation DLGPlayerAudioManager +@synthesize mute = _mute; - (id)init { self = [super init]; @@ -51,6 +52,7 @@ - (id)init { } - (void)initVars { + self.mute = NO; _registeredKVO = NO; _opened = NO; _closing = NO; @@ -81,161 +83,166 @@ - (void)dealloc { * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ - (BOOL)open:(NSError **)error { - AVAudioSession *session = [AVAudioSession sharedInstance]; - NSError *rawError = nil; - - if (![session setCategory:AVAudioSessionCategorySoloAmbient error:&rawError]) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioCategory - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_CATEGORY"] - andRawError:rawError]; - return NO; - } - - if (![session setPreferredIOBufferDuration:_bufferDuration error:&rawError]) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"setPreferredIOBufferDuration: %.4f, error: %@", _bufferDuration, rawError); + @autoreleasepool { + NSError *rawError = nil; + AVAudioSession *session = [AVAudioSession sharedInstance]; + AVAudioSessionCategory category = self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; + + if (![session setCategory:category error:&rawError]) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioCategory + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_CATEGORY"] + andRawError:rawError]; + return NO; } - } - - double prefferedSampleRate = PREFERRED_SAMPLE_RATE; - if (![session setPreferredSampleRate:prefferedSampleRate error:&rawError]) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"setPreferredSampleRate: %.4f, error: %@", prefferedSampleRate, rawError); + + if (![session setPreferredIOBufferDuration:_bufferDuration error:&rawError]) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"setPreferredIOBufferDuration: %.4f, error: %@", _bufferDuration, rawError); + } + } + + double prefferedSampleRate = PREFERRED_SAMPLE_RATE; + if (![session setPreferredSampleRate:prefferedSampleRate error:&rawError]) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"setPreferredSampleRate: %.4f, error: %@", prefferedSampleRate, rawError); + } + } + + if (![session setActive:YES error:&rawError]) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioActive + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE"] + andRawError:rawError]; + return NO; + } + + NSInteger outputsCount = session.currentRoute.outputs.count; + if (outputsCount == 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioOuput + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; + return NO; + } + + NSInteger channels = session.outputNumberOfChannels; + if (channels <= 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioChannel + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL"]]; + return NO; + } + + double sampleRate = session.sampleRate; + if (sampleRate <= 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioSampleRate + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE"]]; + return NO; + } + + float volume = session.outputVolume; + if (volume < 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioVolume + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME"]]; + return NO; + } + + if (![self initAudioUnitWithSampleRate:sampleRate andRenderCallback:audioUnitRenderCallback error:error]) { + return NO; } - } - - if (![session setActive:YES error:&rawError]) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioActive - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE"] - andRawError:rawError]; - return NO; - } - - if (session.currentRoute.outputs.count == 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioOuput - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; - return NO; - } - - NSInteger channels = session.outputNumberOfChannels; - if (channels <= 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioChannel - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL"]]; - return NO; - } - - double sampleRate = session.sampleRate; - if (sampleRate <= 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioSampleRate - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE"]]; - return NO; - } - - float volume = session.outputVolume; - if (volume < 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioVolume - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME"]]; - return NO; - } - if (![self initAudioUnitWithSampleRate:sampleRate andRenderCallback:audioUnitRenderCallback error:error]) { - return NO; + [self registerNotifications]; + + _sampleRate = sampleRate; + _volume = volume; + _opened = YES; + + return YES; } - - [self registerNotifications]; - - _sampleRate = sampleRate; - _volume = volume; - _opened = YES; - - return YES; } - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURenderCallback)renderCallback error:(NSError **)error { - AudioComponentDescription descr = {0}; - descr.componentType = kAudioUnitType_Output; - descr.componentSubType = kAudioUnitSubType_RemoteIO; - descr.componentManufacturer = kAudioUnitManufacturer_Apple; - descr.componentFlags = 0; - descr.componentFlagsMask = 0; - - AudioUnit audioUnit = NULL; - AudioComponent component = AudioComponentFindNext(NULL, &descr); - OSStatus status = AudioComponentInstanceNew(component, &audioUnit); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotCreateAudioComponent - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_CREATE_AUDIO_UNIT"] - andRawError:rawError]; - return NO; - } - - AudioStreamBasicDescription streamDescr = {0}; - UInt32 size = sizeof(AudioStreamBasicDescription); - status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotGetAudioStreamDescription - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_GET_AUDIO_STREAM_DESCRIPTION"] - andRawError:rawError]; - return NO; - } - - streamDescr.mSampleRate = sampleRate; - status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); - if (DLGPlayerUtils.debugEnabled && status != noErr) { - NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); - } - - _bitsPerChannel = streamDescr.mBitsPerChannel; - _channelsPerFrame = streamDescr.mChannelsPerFrame; - - AURenderCallbackStruct renderCallbackStruct; - renderCallbackStruct.inputProc = renderCallback; - renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); - - status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(AURenderCallbackStruct)); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioRenderCallback - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_RENDER_CALLBACK"] - andRawError:rawError]; - return NO; - } - - status = AudioUnitInitialize(audioUnit); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotInitAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_INIT_AUDIO_UNIT"] - andRawError:rawError]; - return NO; + @autoreleasepool { + AudioComponentDescription descr = {0}; + descr.componentType = kAudioUnitType_Output; + descr.componentSubType = kAudioUnitSubType_RemoteIO; + descr.componentManufacturer = kAudioUnitManufacturer_Apple; + descr.componentFlags = 0; + descr.componentFlagsMask = 0; + + AudioUnit audioUnit = NULL; + AudioComponent component = AudioComponentFindNext(NULL, &descr); + OSStatus status = AudioComponentInstanceNew(component, &audioUnit); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotCreateAudioComponent + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_CREATE_AUDIO_UNIT"] + andRawError:rawError]; + return NO; + } + + AudioStreamBasicDescription streamDescr = {0}; + UInt32 size = sizeof(AudioStreamBasicDescription); + status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotGetAudioStreamDescription + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_GET_AUDIO_STREAM_DESCRIPTION"] + andRawError:rawError]; + return NO; + } + + streamDescr.mSampleRate = sampleRate; + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); + if (DLGPlayerUtils.debugEnabled && status != noErr) { + NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); + } + + _bitsPerChannel = streamDescr.mBitsPerChannel; + _channelsPerFrame = streamDescr.mChannelsPerFrame; + + AURenderCallbackStruct renderCallbackStruct; + renderCallbackStruct.inputProc = renderCallback; + renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); + + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(AURenderCallbackStruct)); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioRenderCallback + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_RENDER_CALLBACK"] + andRawError:rawError]; + return NO; + } + + status = AudioUnitInitialize(audioUnit); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotInitAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_INIT_AUDIO_UNIT"] + andRawError:rawError]; + return NO; + } + + _audioUnit = audioUnit; + + return YES; } - - _audioUnit = audioUnit; - - return YES; - } - (BOOL)close { @@ -248,71 +255,73 @@ - (BOOL)close:(NSArray **)errors { } _closing = YES; - - NSMutableArray *errs = nil; - if (errors != nil) errs = [NSMutableArray array]; - - BOOL closed = YES; - - if (_opened) { - [self pause]; - [self unregisterNotifications]; + + @autoreleasepool { + NSMutableArray *errs = nil; + if (errors != nil) errs = [NSMutableArray array]; - OSStatus status = AudioUnitUninitialize(_audioUnit); - if (status != noErr) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotUninitAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT"] - andRawError:rawError]; - [errs addObject:error]; - } - } + BOOL closed = YES; - status = AudioComponentInstanceDispose(_audioUnit); - if (status != noErr) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotDisposeAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT"] - andRawError:rawError]; - [errs addObject:error]; + if (_opened) { + [self pause]; + [self unregisterNotifications]; + + OSStatus status = AudioUnitUninitialize(_audioUnit); + if (status != noErr) { + closed = NO; + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotUninitAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT"] + andRawError:rawError]; + [errs addObject:error]; + } } - } - - NSError *error = nil; - AVAudioSession *session = [AVAudioSession sharedInstance]; + + status = AudioComponentInstanceDispose(_audioUnit); + if (status != noErr) { + closed = NO; + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotDisposeAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT"] + andRawError:rawError]; + [errs addObject:error]; + } + } + + AVAudioSession *session = [AVAudioSession sharedInstance]; + NSError *error = nil; - if (![session setActive:NO error:&error]) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotDeactivateAudio - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] - andRawError:rawError]; - [errs addObject:error]; + if (![session setActive:NO error:&error]) { + closed = NO; + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotDeactivateAudio + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] + andRawError:rawError]; + [errs addObject:error]; + } + } + + if (closed) { + _opened = NO; } } - if (closed) { - _opened = NO; - } + _closing = NO; + + return closed; } - - _closing = NO; - - return closed; } - (BOOL)play { @@ -320,16 +329,22 @@ - (BOOL)play { } - (BOOL)play:(NSError **)error { + if (self.mute) { + return _playing; + } + if (_opened) { OSStatus status = AudioOutputUnitStart(_audioUnit); _playing = (status == noErr); if (!_playing) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotStartAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_START_AUDIO_UNIT"] - andRawError:rawError]; + @autoreleasepool { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotStartAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_START_AUDIO_UNIT"] + andRawError:rawError]; + } } } return _playing; @@ -340,16 +355,22 @@ - (BOOL)pause { } - (BOOL)pause:(NSError **)error { + if (self.mute) { + return _playing; + } + if (_playing) { OSStatus status = AudioOutputUnitStop(_audioUnit); _playing = !(status == noErr); if (_playing) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotStopAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_STOP_AUDIO_UNIT"] - andRawError:rawError]; + @autoreleasepool { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotStopAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_STOP_AUDIO_UNIT"] + andRawError:rawError]; + } } } return !_playing; @@ -400,32 +421,36 @@ - (UInt32)channels { #pragma mark - Notifications - (void)registerNotifications { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self - selector:@selector(notifyAudioSessionRouteChanged:) - name:AVAudioSessionRouteChangeNotification - object:nil]; - [nc addObserver:self - selector:@selector(notifyAudioSessionInterruptionNotification:) - name:AVAudioSessionInterruptionNotification - object:nil]; - - if (!_registeredKVO) { - AVAudioSession *session = [AVAudioSession sharedInstance]; - [session addObserver:self - forKeyPath:@"outputVolume" - options:0 - context:nil]; - _registeredKVO = YES; + @autoreleasepool { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(notifyAudioSessionRouteChanged:) + name:AVAudioSessionRouteChangeNotification + object:nil]; + [nc addObserver:self + selector:@selector(notifyAudioSessionInterruptionNotification:) + name:AVAudioSessionInterruptionNotification + object:nil]; + + if (!_registeredKVO) { + AVAudioSession *session = [AVAudioSession sharedInstance]; + [session addObserver:self + forKeyPath:@"outputVolume" + options:0 + context:nil]; + _registeredKVO = YES; + } } } - (void)unregisterNotifications { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc removeObserver:self]; - if (_registeredKVO) { - AVAudioSession *session = [AVAudioSession sharedInstance]; - [session removeObserver:self forKeyPath:@"outputVolume"]; + @autoreleasepool { + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self]; + if (_registeredKVO) { + AVAudioSession *session = [AVAudioSession sharedInstance]; + [session removeObserver:self forKeyPath:@"outputVolume"]; + } _registeredKVO = NO; } } @@ -452,15 +477,17 @@ - (void)notifyAudioSessionInterruptionNotification:(NSNotification *)notif { } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - AVAudioSession *session = [AVAudioSession sharedInstance]; - if (object == session && [keyPath isEqualToString:@"outputVolume"]) { - self.volume = session.outputVolume; + @autoreleasepool { + AVAudioSession *session = [AVAudioSession sharedInstance]; + if (object == session && [keyPath isEqualToString:@"outputVolume"]) { + self.volume = session.outputVolume; + } } } @end -OSStatus audioUnitRenderCallback(void *inRefCon, +static OSStatus audioUnitRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, diff --git a/DLGPlayerDemo/Base.lproj/Main.storyboard b/DLGPlayerDemo/Base.lproj/Main.storyboard index 26273c1..c41ac95 100644 --- a/DLGPlayerDemo/Base.lproj/Main.storyboard +++ b/DLGPlayerDemo/Base.lproj/Main.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -15,7 +13,7 @@ - + @@ -50,24 +48,20 @@ - - - - - + - - - - - - - - - - + @@ -126,61 +111,47 @@ + + + + + - - - + + - + - - - - - - - - - - - - - - - - + @@ -188,138 +159,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 6fb5e4a..845aff6 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -8,33 +8,73 @@ import UIKit -class RootViewController: UIViewController { +final class RootViewController: UIViewController { - @IBOutlet private weak var coverView: UIView? + @IBOutlet private weak var containerView: UIView! @IBOutlet private weak var muteButton: UIButton! @IBOutlet private weak var playOrPauseButton: UIButton! @IBOutlet private weak var segmentedControl: UISegmentedControl! + private lazy var players = [DLGSimplePlayerViewController]() + private var isFirstViewAppearance = true - private var playerViewController: DLGSimplePlayerViewController? { - didSet { - playerViewController.map { - $0.delegate = self - $0.isAllowsFrameDrop = true - $0.isAutoplay = true -// $0.isMute = true - $0.preventFromScreenLock = true - $0.restorePlayAfterAppEnterForeground = true - $0.minBufferDuration = 0 - $0.maxBufferDuration = 3 - } - } - } deinit { print("deinit") } + + private func createPlayers() { + for i in 0..<3 { + let pv = DLGSimplePlayerViewController() + pv.view.translatesAutoresizingMaskIntoConstraints = true + pv.delegate = self + pv.isAllowsFrameDrop = true + pv.isAutoplay = true +// pv.isMute = true + pv.preventFromScreenLock = true + pv.restorePlayAfterAppEnterForeground = true + pv.minBufferDuration = 0 + pv.maxBufferDuration = 3 + pv.view.backgroundColor = .red + + addChild(pv) + + let height = 9 * containerView.frame.width / 16 + + pv.view.frame = .init(x: 0, y: height * CGFloat(i), width: containerView.frame.width, height: height) + containerView.addSubview(pv.view) + players.append(pv) + } + } + private func removePlayers() { + players.forEach { + $0.removeFromParent() + $0.view.removeFromSuperview() + } + players.removeAll() + } + private func playAll() { + let first = players.first + + players + .filter { $0 != first } + .forEach { $0.stop() } + + first.map { + $0.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAADIQF?token=b6e503e4-f47c-4238-baca-51cbdfc10001" + $0.open() + } + } + private func reset() { + removePlayers() + createPlayers() + playAll() + + DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) { [weak self] in + self?.reset() + } + } override func viewDidLoad() { super.viewDidLoad() @@ -43,130 +83,68 @@ class RootViewController: UIViewController { segmentedControl.setWidth(50, forSegmentAt: i) } + DLGPlayerUtils.setDebugEnabled(true) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - playRTMP1() -// playRTMP2() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) isFirstViewAppearance = false + + reset() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - playerViewController?.stop() - coverView?.isHidden = false } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { navigationController?.isNavigationBarHidden = UIDevice.current.orientation.isLandscape } - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - switch segue.destination { - case let vc as DLGSimplePlayerViewController: - playerViewController = vc - default: - () - } - } - - // MARK: - Play Test - - private func playDownload1() { - playerViewController?.url = "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" - playerViewController?.open() - } - private func playRTMP1() { - let now = Date().timeIntervalSince1970 - let time = Date(timeIntervalSince1970: now - 60 * 60 * 24).timeIntervalSince1970 - -// playerViewController?.speed = 2 - playerViewController?.url = "rtmps://mediajp005.toastcam.com:10080/flvplayback/AAAENYZ?token=b6e503e4-f47c-4238-baca-51cbdfc10003" -// playerViewController?.url = "rtmps://media007.toastcam.com:10080/flvplayback/AAAADSE?token=b6e503e4-f47c-4238-baca-51cbdfc10001&time=\(time)&speed=2" - playerViewController?.open() - } - - // MARK: - Hard Test - - private let hardTestCount: Int = 10 - private var playCount: Int = 0 - private func startHardTest() { - if #available(iOS 10.0, *), playCount < hardTestCount { - var count = 0 - - Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { - self.playTest(0) - count += 1 - - if count > self.hardTestCount { - $0.invalidate() - } - } - } - } - private func playTest(_ count: Int) { - let url = count % 2 == 0 ? - "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAACPUS?token=1234567890" : - "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4" - - playerViewController?.stop() - - playerViewController?.url = url - playerViewController?.open() - } // MARK: - Private Selectors @IBAction private func captureButtonClicked() { - playerViewController?.player.snapshot() - .map { UIImageView(image: $0) } - .map { [weak self] in - self?.view.addSubview($0) - $0.frame = .init(x: 0, y: 100, width: 160, height: 90) - } +// playerViewController?.player.snapshot() +// .map { UIImageView(image: $0) } +// .map { [weak self] in +// self?.view.addSubview($0) +// $0.frame = .init(x: 0, y: 100, width: 160, height: 90) +// } } @IBAction private func muteButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected - playerViewController?.isMute = !sender.isSelected +// playerViewController?.isMute = !sender.isSelected } @IBAction private func playOrPauseButtonClicked(_ sender: UIButton) { - sender.isSelected = !sender.isSelected - - if sender.isSelected { - if playerViewController?.status == .paused { - playerViewController?.play() - } else { - playRTMP1() - } - } else { - playerViewController?.pause() - } +// sender.isSelected = !sender.isSelected +// +// if sender.isSelected { +// if playerViewController?.status == .paused { +// playerViewController?.play() +// } else { +// playRTMP1() +// } +// } else { +// playerViewController?.pause() +// } } @IBAction private func refreshButtonClicked(_ sender: UIButton) { - playerViewController?.stop() - playRTMP1() } @IBAction private func stopButtonClicked() { - playerViewController?.stop() } @IBAction private func valueChanged(_ sender: UISlider) { - playerViewController?.player.brightness = sender.value } @IBAction private func segmentValueChanged(_ sender: UISegmentedControl) { - playerViewController?.stop() - playerViewController?.speed = Double(1 << sender.selectedSegmentIndex) - playRTMP1() } } extension RootViewController: DLGSimplePlayerViewControllerDelegate { func didBeginRender(in viewController: DLGSimplePlayerViewController) { // print("didBeginRender -> ", viewController.url) - coverView?.isHidden = true } func viewController(_ viewController: DLGSimplePlayerViewController, didReceiveError error: Error) { // print("didReceiveError -> ", error) From a11175446dda6fdd0e13602b57efd188a0a8891c Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 22 Apr 2020 09:24:08 +0900 Subject: [PATCH 193/215] Fixed: solve issue that sometime audio does not work. --- DLGPlayer/DLGPlayer.m | 97 ++++++------------------- DLGPlayer/codec/DLGPlayerAudioManager.m | 2 +- 2 files changed, 25 insertions(+), 74 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 97727aa..5e0f986 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -47,10 +47,6 @@ @interface DLGPlayer () static dispatch_queue_t processingQueueStatic; @implementation DLGPlayer -{ -@private - dispatch_block_t processingBlock; -} - (id)init { self = [super init]; @@ -61,8 +57,6 @@ - (id)init { } - (void)dealloc { - [self cancelProcessing]; - if (DLGPlayerUtils.debugEnabled) { NSLog(@"DLGPlayer dealloc"); } @@ -76,7 +70,6 @@ - (void)initAll { } - (void)initVars { - processingBlock = NULL; _frameDropDuration = DLGPlayerFrameDropDuration; _minBufferDuration = DLGPlayerMinBufferDuration; _maxBufferDuration = DLGPlayerMaxBufferDuration; @@ -154,23 +147,21 @@ - (void)clearVars { self.frameDropped = NO; } -- (void)cancelProcessing { - if (processingBlock) { - dispatch_block_cancel(processingBlock); - processingBlock = NULL; - } -} - - (void)open:(NSString *)url { if (self.opening || self.closing) { return; } - [self cancelProcessing]; + dispatch_async(audioProcessingQueue, ^{ + if ([self.audio open:nil]) { + self.decoder.audioChannels = [self.audio channels]; + self.decoder.audioSampleRate = [self.audio sampleRate]; + } + }); __weak typeof(self)weakSelf = self; - processingBlock = dispatch_block_create(0, ^{ + dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || strongSelf.opening || strongSelf.closing) { @@ -179,18 +170,6 @@ - (void)open:(NSString *)url { strongSelf.opening = YES; - dispatch_async(audioProcessingQueue, ^{ - if ([strongSelf.audio open:nil]) { - strongSelf.decoder.audioChannels = [strongSelf.audio channels]; - strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - } - }); - @autoreleasepool { NSError *error = nil; if (![strongSelf.decoder open:url error:&error]) { @@ -232,37 +211,41 @@ - (void)open:(NSString *)url { strongSelf.bufferedDuration = 0; strongSelf.mediaPosition = 0; strongSelf.mediaSyncTime = 0; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + strongSelf.opened = YES; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; }); }); - - dispatch_async(self.processingQueue, processingBlock); } - (void)close { - if (self.closing) { + if (self.closing || !self.opened) { return; } - [self pauseInternally]; + [self pause]; + dispatch_async(audioProcessingQueue, ^{ + [self.audio close:nil]; + }); + __weak typeof(self)weakSelf = self; dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - if (!strongSelf || strongSelf.closing) { + if (!strongSelf || strongSelf.closing || !strongSelf.opened) { return; } strongSelf.closing = YES; - dispatch_async(audioProcessingQueue, ^{ - [strongSelf.audio close:nil]; - }); - [strongSelf.decoder prepareClose]; [strongSelf.decoder close]; [strongSelf.view clear]; @@ -273,11 +256,9 @@ - (void)close { } - (void)play { - [self cancelProcessing]; - __weak typeof(self)weakSelf = self; - processingBlock = dispatch_block_create(0, ^{ + dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { @@ -291,50 +272,20 @@ - (void)play { [strongSelf render]; } }); - + dispatch_async(audioProcessingQueue, ^{ - [strongSelf.audio play:nil]; + [strongSelf.audio play]; }); [strongSelf runFrameReader]; }); - - dispatch_async(self.processingQueue, processingBlock); } - (void)pause { - [self cancelProcessing]; - - __weak typeof(self)weakSelf = self; - - processingBlock = dispatch_block_create(0, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (!strongSelf) { - return; - } - - [strongSelf pauseInternally]; - }); - - dispatch_async(self.processingQueue, processingBlock); -} - -- (void)pauseInternally { self.playing = NO; - if (self.mute) { - return; - } - - __weak typeof(self)weakSelf = self; - dispatch_async(audioProcessingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf) { - [strongSelf.audio pause:nil]; - } + [self.audio pause]; }); } diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index b72fcd0..f772dfb 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -255,7 +255,7 @@ - (BOOL)close:(NSArray **)errors { } _closing = YES; - + @autoreleasepool { NSMutableArray *errs = nil; if (errors != nil) errs = [NSMutableArray array]; From d8dc3aa3ebcde9de54fc6444602bc366427946e1 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 28 Apr 2020 19:12:19 +0900 Subject: [PATCH 194/215] Fixed: memory leak guessing logic. --- DLGPlayer/codec/DLGPlayerAudioManager.m | 5 +++-- DLGPlayer/common/DLGPlayerUtils.m | 30 ++++++++++++++----------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index f772dfb..000e92b 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -119,8 +119,8 @@ - (BOOL)open:(NSError **)error { return NO; } - NSInteger outputsCount = session.currentRoute.outputs.count; - if (outputsCount == 0) { + AVAudioSessionRouteDescription *currentRoute = session.currentRoute; + if (currentRoute.outputs.count == 0) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager andCode:DLGPlayerErrorCodeNoAudioOuput @@ -315,6 +315,7 @@ - (BOOL)close:(NSArray **)errors { if (closed) { _opened = NO; + _audioUnit = NULL; } } diff --git a/DLGPlayer/common/DLGPlayerUtils.m b/DLGPlayer/common/DLGPlayerUtils.m index 3f54128..121be1e 100644 --- a/DLGPlayer/common/DLGPlayerUtils.m +++ b/DLGPlayer/common/DLGPlayerUtils.m @@ -18,23 +18,27 @@ @implementation DLGPlayerUtils + (BOOL)createError:(NSError **)error withDomain:(NSString *)domain andCode:(NSInteger)code andMessage:(NSString *)message { if (error == nil) return NO; - NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; - if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; - *error = [NSError errorWithDomain:domain - code:code - userInfo:userInfo]; - return YES; + @autoreleasepool { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; + *error = [NSError errorWithDomain:domain + code:code + userInfo:userInfo]; + return YES; + } } + (BOOL)createError:(NSError **)error withDomain:(NSString *)domain andCode:(NSInteger)code andMessage:(NSString *)message andRawError:(NSError *)rawError { if (error == nil) return NO; - NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; - if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; - if (rawError != nil) userInfo[NSLocalizedFailureReasonErrorKey] = rawError; - *error = [NSError errorWithDomain:domain - code:code - userInfo:userInfo]; - return YES; + @autoreleasepool { + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; + if (rawError != nil) userInfo[NSLocalizedFailureReasonErrorKey] = rawError; + *error = [NSError errorWithDomain:domain + code:code + userInfo:userInfo]; + return YES; + } } + (BOOL)debugEnabled { From 013dc6596b6d31e0f22030ca947ffbe1ae985ea0 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 29 Apr 2020 13:09:07 +0900 Subject: [PATCH 195/215] Fixed: rollback to alloc processing queue. --- DLGPlayer/DLGPlayer.m | 11 ++++++++++- DLGPlayer/common/DLGPlayerUtils.m | 30 +++++++++++++----------------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 5e0f986..ae0498f 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -97,11 +97,16 @@ - (void)initVars { _vframes = [NSMutableArray arrayWithCapacity:128]; _aframes = [NSMutableArray arrayWithCapacity:128]; _renderingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); - _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); if (!audioProcessingQueue) { audioProcessingQueue = dispatch_queue_create("DLGPlayer.audioProcessingQueue", DISPATCH_QUEUE_SERIAL); } + + if ([DLGPlayerUtils isMetalSupport]) { + _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); + } else if (!processingQueueStatic) { + processingQueueStatic = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); + } } - (void)initView { @@ -147,6 +152,10 @@ - (void)clearVars { self.frameDropped = NO; } +- (dispatch_queue_t)processingQueue { + return [DLGPlayerUtils isMetalSupport] ? _processingQueue : processingQueueStatic; +} + - (void)open:(NSString *)url { if (self.opening || self.closing) { return; diff --git a/DLGPlayer/common/DLGPlayerUtils.m b/DLGPlayer/common/DLGPlayerUtils.m index 121be1e..3f54128 100644 --- a/DLGPlayer/common/DLGPlayerUtils.m +++ b/DLGPlayer/common/DLGPlayerUtils.m @@ -18,27 +18,23 @@ @implementation DLGPlayerUtils + (BOOL)createError:(NSError **)error withDomain:(NSString *)domain andCode:(NSInteger)code andMessage:(NSString *)message { if (error == nil) return NO; - @autoreleasepool { - NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; - if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; - *error = [NSError errorWithDomain:domain - code:code - userInfo:userInfo]; - return YES; - } + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; + *error = [NSError errorWithDomain:domain + code:code + userInfo:userInfo]; + return YES; } + (BOOL)createError:(NSError **)error withDomain:(NSString *)domain andCode:(NSInteger)code andMessage:(NSString *)message andRawError:(NSError *)rawError { if (error == nil) return NO; - @autoreleasepool { - NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; - if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; - if (rawError != nil) userInfo[NSLocalizedFailureReasonErrorKey] = rawError; - *error = [NSError errorWithDomain:domain - code:code - userInfo:userInfo]; - return YES; - } + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + if (message != nil) userInfo[NSLocalizedDescriptionKey] = message; + if (rawError != nil) userInfo[NSLocalizedFailureReasonErrorKey] = rawError; + *error = [NSError errorWithDomain:domain + code:code + userInfo:userInfo]; + return YES; } + (BOOL)debugEnabled { From 1f5e00eca9743e701223de6c57f7606941eb6e0f Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 11 May 2020 18:15:27 +0900 Subject: [PATCH 196/215] Fixed: bugs. --- DLGPlayer/DLGPlayer.m | 37 +++++++++++------- DLGPlayer/DLGSimplePlayerViewController.m | 37 +++++++++++++----- DLGPlayer/common/DLGPlayerDef.h | 4 ++ DLGPlayerDemo/RootViewController.swift | 47 +++++++++++------------ 4 files changed, 78 insertions(+), 47 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index ae0498f..f6b360d 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -161,15 +161,23 @@ - (void)open:(NSString *)url { return; } + __weak typeof(self)weakSelf = self; + dispatch_async(audioProcessingQueue, ^{ - if ([self.audio open:nil]) { - self.decoder.audioChannels = [self.audio channels]; - self.decoder.audioSampleRate = [self.audio sampleRate]; + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (!strongSelf || strongSelf.opening || strongSelf.closing) { + return; + } + + if ([strongSelf.audio open:nil]) { + strongSelf.decoder.audioChannels = [strongSelf.audio channels]; + strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; } }); - __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; @@ -183,11 +191,6 @@ - (void)open:(NSString *)url { NSError *error = nil; if (![strongSelf.decoder open:url error:&error]) { strongSelf.opening = NO; - - dispatch_async(audioProcessingQueue, ^{ - [strongSelf.audio close:nil]; - }); - [strongSelf handleError:error]; return; } @@ -240,12 +243,20 @@ - (void)close { [self pause]; + __weak typeof(self)weakSelf = self; + dispatch_async(audioProcessingQueue, ^{ - [self.audio close:nil]; + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (!strongSelf || strongSelf.closing || !strongSelf.opened) { + return; + } + + if ([strongSelf.audio close:nil]) { + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:strongSelf]; + } }); - __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 0e84c5f..bdcdebb 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -88,11 +88,15 @@ - (void)setStatus:(DLGPlayerStatus)status { _status = status; [_controlStatus setStatus:_status]; - if ([_delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [self.delegate viewController:self didChangeStatus:status]; - }); - } + __weak typeof(self)weakSelf = self; + + dispatch_async(dispatch_get_main_queue(), ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf && [strongSelf.delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { + [strongSelf.delegate viewController:strongSelf didChangeStatus:status]; + } + }); } - (BOOL)isMute { @@ -147,7 +151,7 @@ - (void)open { } - (void)play { - [UIApplication sharedApplication].idleTimerDisabled = _preventFromScreenLock; + [UIApplication sharedApplication].idleTimerDisabled = self.preventFromScreenLock; [self.player play]; self.status = DLGPlayerStatusPlaying; } @@ -198,6 +202,8 @@ - (void)registerNotification { name:UIApplicationDidEnterBackgroundNotification object:nil]; [nc addObserver:self selector:@selector(notifyAppWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; + [nc addObserver:self selector:@selector(notifyPlayerAudioOpened:) name:DLGPlayerNotificationAudioOpened object:self.player]; + [nc addObserver:self selector:@selector(notifyPlayerAudioClosed:) name:DLGPlayerNotificationAudioClosed object:self.player]; [nc addObserver:self selector:@selector(notifyPlayerOpened:) name:DLGPlayerNotificationOpened object:self.player]; [nc addObserver:self selector:@selector(notifyPlayerClosed:) name:DLGPlayerNotificationClosed object:self.player]; [nc addObserver:self selector:@selector(notifyPlayerEOF:) name:DLGPlayerNotificationEOF object:self.player]; @@ -243,6 +249,14 @@ - (void)notifyPlayerOpened:(NSNotification *)notif { if (_isAutoplay) [self play]; } + +- (void)notifyPlayerAudioOpened:(NSNotification *)notif { + self.status = DLGPlayerStatusAudioOpened; +} + +- (void)notifyPlayerAudioClosed:(NSNotification *)notif { + self.status = DLGPlayerStatusAudioClosed; +} - (void)notifyPlayerBufferStateChanged:(NSNotification *)notif { NSDictionary *userInfo = notif.userInfo; @@ -276,12 +290,15 @@ - (void)notifyPlayerError:(NSNotification *)notif { } } + __weak typeof(self)weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ - if ([self.delegate respondsToSelector:@selector(viewController:didReceiveError:)]) { - [self.delegate viewController:self didReceiveError:error]; - } + __strong typeof(weakSelf)strongSelf = weakSelf; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:self userInfo:notif.userInfo]; + if (strongSelf && [strongSelf.delegate respondsToSelector:@selector(viewController:didReceiveError:)]) { + [strongSelf.delegate viewController:strongSelf didReceiveError:error]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:strongSelf userInfo:notif.userInfo]; + } }); } diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index 7e7ab5a..7e91686 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -40,6 +40,8 @@ #define DLGPlayerErrorCodeCannotStopAudioUnit -19 #pragma mark - Notification +#define DLGPlayerNotificationAudioOpened @"DLGPlayerNotificationAudioOpened" +#define DLGPlayerNotificationAudioClosed @"DLGPlayerNotificationAudioClosed" #define DLGPlayerNotificationOpened @"DLGPlayerNotificationOpened" #define DLGPlayerNotificationClosed @"DLGPlayerNotificationClosed" #define DLGPlayerNotificationEOF @"DLGPlayerNotificationEOF" @@ -56,12 +58,14 @@ typedef NS_ENUM(NSUInteger, DLGPlayerStatus) { DLGPlayerStatusNone, DLGPlayerStatusOpening, + DLGPlayerStatusAudioOpened, DLGPlayerStatusOpened, DLGPlayerStatusPlaying, DLGPlayerStatusBuffering, DLGPlayerStatusPaused, DLGPlayerStatusEOF, DLGPlayerStatusClosing, + DLGPlayerStatusAudioClosed, DLGPlayerStatusClosed }; diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 845aff6..dd23ea4 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -25,7 +25,7 @@ final class RootViewController: UIViewController { } private func createPlayers() { - for i in 0..<3 { + for i in 0..<1 { let pv = DLGSimplePlayerViewController() pv.view.translatesAutoresizingMaskIntoConstraints = true pv.delegate = self @@ -49,20 +49,16 @@ final class RootViewController: UIViewController { } private func removePlayers() { players.forEach { + $0.stop() $0.removeFromParent() $0.view.removeFromSuperview() } players.removeAll() } private func playAll() { - let first = players.first - - players - .filter { $0 != first } - .forEach { $0.stop() } - - first.map { - $0.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAADIQF?token=b6e503e4-f47c-4238-baca-51cbdfc10001" + players.forEach { + $0.url = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" +// $0.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAADIQF?token=b6e503e4-f47c-4238-baca-51cbdfc10001" $0.open() } } @@ -70,10 +66,6 @@ final class RootViewController: UIViewController { removePlayers() createPlayers() playAll() - - DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) { [weak self] in - self?.reset() - } } override func viewDidLoad() { @@ -101,6 +93,11 @@ final class RootViewController: UIViewController { super.viewWillDisappear(animated) } + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + removePlayers() + } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { navigationController?.isNavigationBarHidden = UIDevice.current.orientation.isLandscape } @@ -120,17 +117,15 @@ final class RootViewController: UIViewController { // playerViewController?.isMute = !sender.isSelected } @IBAction private func playOrPauseButtonClicked(_ sender: UIButton) { -// sender.isSelected = !sender.isSelected -// -// if sender.isSelected { -// if playerViewController?.status == .paused { -// playerViewController?.play() -// } else { -// playRTMP1() -// } -// } else { -// playerViewController?.pause() -// } + sender.isSelected = !sender.isSelected + + let vc = players.first + + if sender.isSelected { + vc?.play() + } else { + vc?.pause() + } } @IBAction private func refreshButtonClicked(_ sender: UIButton) { } @@ -163,6 +158,8 @@ extension DLGPlayerStatus { return "buffering" case .closed: return "closed" + case .audioClosed: + return "audioClosed" case .closing: return "closing" case .EOF: @@ -171,6 +168,8 @@ extension DLGPlayerStatus { return "none" case .opened: return "opened" + case .audioOpened: + return "audioOpened" case .opening: return "opening" case .paused: From d0359e8b600b0c84467dcfdbc7a48f38e5f65293 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 11 May 2020 20:44:55 +0900 Subject: [PATCH 197/215] Fixed: remove unnecessary code. --- DLGPlayer/DLGSimplePlayerViewController.m | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index bdcdebb..a0accb3 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -88,13 +88,9 @@ - (void)setStatus:(DLGPlayerStatus)status { _status = status; [_controlStatus setStatus:_status]; - __weak typeof(self)weakSelf = self; - dispatch_async(dispatch_get_main_queue(), ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf && [strongSelf.delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { - [strongSelf.delegate viewController:strongSelf didChangeStatus:status]; + if ([self.delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { + [self.delegate viewController:self didChangeStatus:status]; } }); } @@ -290,14 +286,10 @@ - (void)notifyPlayerError:(NSNotification *)notif { } } - __weak typeof(self)weakSelf = self; - dispatch_async(dispatch_get_main_queue(), ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf && [strongSelf.delegate respondsToSelector:@selector(viewController:didReceiveError:)]) { - [strongSelf.delegate viewController:strongSelf didReceiveError:error]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:strongSelf userInfo:notif.userInfo]; + if ([self.delegate respondsToSelector:@selector(viewController:didReceiveError:)]) { + [self.delegate viewController:self didReceiveError:error]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:self userInfo:notif.userInfo]; } }); } From be7e39673c8b3368db81861427495644f29a3cff Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 12 May 2020 10:03:27 +0900 Subject: [PATCH 198/215] Fixed: remove unnecessary code. --- DLGPlayer/DLGPlayer.m | 130 ++++---- DLGPlayer/codec/DLGPlayerAudioManager.m | 426 ++++++++++++------------ 2 files changed, 274 insertions(+), 282 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index f6b360d..09306ef 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -187,13 +187,11 @@ - (void)open:(NSString *)url { strongSelf.opening = YES; - @autoreleasepool { - NSError *error = nil; - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - [strongSelf handleError:error]; - return; - } + NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + [strongSelf handleError:error]; + return; } dispatch_async(dispatch_get_main_queue(), ^{ @@ -288,9 +286,7 @@ - (void)play { strongSelf.playing = YES; dispatch_async(dispatch_get_main_queue(), ^{ - if (strongSelf) { - [strongSelf render]; - } + [strongSelf render]; }); dispatch_async(audioProcessingQueue, ^{ @@ -303,9 +299,13 @@ - (void)play { - (void)pause { self.playing = NO; - + + __weak typeof(self)weakSelf = self; + dispatch_async(audioProcessingQueue, ^{ - [self.audio pause]; + __strong typeof(weakSelf)strongSelf = weakSelf; + + [strongSelf.audio pause]; }); } @@ -595,69 +595,67 @@ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)chan } while(frames > 0) { - @autoreleasepool { - if (self.playingAudioFrame == nil) { - { - if (self.aframes.count <= 0) { - memset(data, 0, frames * channels * sizeof(float)); - return; - } + if (self.playingAudioFrame == nil) { + { + if (self.aframes.count <= 0) { + memset(data, 0, frames * channels * sizeof(float)); + return; + } + + long timeout = dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW); + if (timeout == 0) { + DLGPlayerAudioFrame *frame = self.aframes[0]; - long timeout = dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW); - if (timeout == 0) { - DLGPlayerAudioFrame *frame = self.aframes[0]; + if (self.decoder.hasVideo) { + const double dt = self.mediaPosition - frame.position; - if (self.decoder.hasVideo) { - const double dt = self.mediaPosition - frame.position; - - if (dt < -0.1 && self.vframes.count > 0) { // audio is faster than video, silence - memset(data, 0, frames * channels * sizeof(float)); - dispatch_semaphore_signal(self.aFramesLock); - break; - } else if (dt > 0.1) { // audio is slower than video, skip - [self.aframes removeObjectAtIndex:0]; - dispatch_semaphore_signal(self.aFramesLock); - continue; - } else { - self.playingAudioFrameDataPosition = 0; - self.playingAudioFrame = frame; - [self.aframes removeObjectAtIndex:0]; - } + if (dt < -0.1 && self.vframes.count > 0) { // audio is faster than video, silence + memset(data, 0, frames * channels * sizeof(float)); + dispatch_semaphore_signal(self.aFramesLock); + break; + } else if (dt > 0.1) { // audio is slower than video, skip + [self.aframes removeObjectAtIndex:0]; + dispatch_semaphore_signal(self.aFramesLock); + continue; } else { self.playingAudioFrameDataPosition = 0; self.playingAudioFrame = frame; [self.aframes removeObjectAtIndex:0]; - self.mediaPosition = frame.position; - self.bufferedDuration -= frame.duration; } - dispatch_semaphore_signal(self.aFramesLock); - } else return; - } - } - - NSData *frameData = self.playingAudioFrame.data; - NSUInteger pos = self.playingAudioFrameDataPosition; - if (frameData == nil) { - memset(data, 0, frames * channels * sizeof(float)); - return; - } - - const void *bytes = (Byte *)frameData.bytes + pos; - const NSUInteger remainingBytes = frameData.length - pos; - const NSUInteger channelSize = channels * sizeof(float); - const NSUInteger bytesToCopy = MIN(frames * channelSize, remainingBytes); - const NSUInteger framesToCopy = bytesToCopy / channelSize; - - memcpy(data, bytes, bytesToCopy); - frames -= framesToCopy; - data += framesToCopy * channels; - - if (bytesToCopy < remainingBytes) { - self.playingAudioFrameDataPosition += bytesToCopy; - } else { - self.playingAudioFrame = nil; + } else { + self.playingAudioFrameDataPosition = 0; + self.playingAudioFrame = frame; + [self.aframes removeObjectAtIndex:0]; + self.mediaPosition = frame.position; + self.bufferedDuration -= frame.duration; + } + dispatch_semaphore_signal(self.aFramesLock); + } else return; } } + + NSData *frameData = self.playingAudioFrame.data; + NSUInteger pos = self.playingAudioFrameDataPosition; + if (frameData == nil) { + memset(data, 0, frames * channels * sizeof(float)); + return; + } + + const void *bytes = (Byte *)frameData.bytes + pos; + const NSUInteger remainingBytes = frameData.length - pos; + const NSUInteger channelSize = channels * sizeof(float); + const NSUInteger bytesToCopy = MIN(frames * channelSize, remainingBytes); + const NSUInteger framesToCopy = bytesToCopy / channelSize; + + memcpy(data, bytes, bytesToCopy); + frames -= framesToCopy; + data += framesToCopy * channels; + + if (bytesToCopy < remainingBytes) { + self.playingAudioFrameDataPosition += bytesToCopy; + } else { + self.playingAudioFrame = nil; + } } } diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 000e92b..bc05a2f 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -83,166 +83,162 @@ - (void)dealloc { * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ - (BOOL)open:(NSError **)error { - @autoreleasepool { - NSError *rawError = nil; - AVAudioSession *session = [AVAudioSession sharedInstance]; - AVAudioSessionCategory category = self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; - - if (![session setCategory:category error:&rawError]) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioCategory - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_CATEGORY"] - andRawError:rawError]; - return NO; - } - - if (![session setPreferredIOBufferDuration:_bufferDuration error:&rawError]) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"setPreferredIOBufferDuration: %.4f, error: %@", _bufferDuration, rawError); - } - } - - double prefferedSampleRate = PREFERRED_SAMPLE_RATE; - if (![session setPreferredSampleRate:prefferedSampleRate error:&rawError]) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"setPreferredSampleRate: %.4f, error: %@", prefferedSampleRate, rawError); - } - } - - if (![session setActive:YES error:&rawError]) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioActive - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE"] - andRawError:rawError]; - return NO; - } - - AVAudioSessionRouteDescription *currentRoute = session.currentRoute; - if (currentRoute.outputs.count == 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioOuput - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; - return NO; - } - - NSInteger channels = session.outputNumberOfChannels; - if (channels <= 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioChannel - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL"]]; - return NO; - } - - double sampleRate = session.sampleRate; - if (sampleRate <= 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioSampleRate - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE"]]; - return NO; - } - - float volume = session.outputVolume; - if (volume < 0) { - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeNoAudioVolume - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME"]]; - return NO; + NSError *rawError = nil; + AVAudioSession *session = [AVAudioSession sharedInstance]; + AVAudioSessionCategory category = self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; + + if (![session setCategory:category error:&rawError]) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioCategory + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_CATEGORY"] + andRawError:rawError]; + return NO; + } + + if (![session setPreferredIOBufferDuration:_bufferDuration error:&rawError]) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"setPreferredIOBufferDuration: %.4f, error: %@", _bufferDuration, rawError); } - - if (![self initAudioUnitWithSampleRate:sampleRate andRenderCallback:audioUnitRenderCallback error:error]) { - return NO; + } + + double prefferedSampleRate = PREFERRED_SAMPLE_RATE; + if (![session setPreferredSampleRate:prefferedSampleRate error:&rawError]) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"setPreferredSampleRate: %.4f, error: %@", prefferedSampleRate, rawError); } + } - [self registerNotifications]; - - _sampleRate = sampleRate; - _volume = volume; - _opened = YES; - - return YES; + if (![session setActive:YES error:&rawError]) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioActive + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_ACTIVE"] + andRawError:rawError]; + return NO; + } + + AVAudioSessionRouteDescription *currentRoute = session.currentRoute; + if (currentRoute.outputs.count == 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioOuput + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; + return NO; + } + + NSInteger channels = session.outputNumberOfChannels; + if (channels <= 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioChannel + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL"]]; + return NO; + } + + double sampleRate = session.sampleRate; + if (sampleRate <= 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioSampleRate + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE"]]; + return NO; + } + + float volume = session.outputVolume; + if (volume < 0) { + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeNoAudioVolume + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME"]]; + return NO; + } + + if (![self initAudioUnitWithSampleRate:sampleRate andRenderCallback:audioUnitRenderCallback error:error]) { + return NO; } + + [self registerNotifications]; + + _sampleRate = sampleRate; + _volume = volume; + _opened = YES; + + return YES; } - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURenderCallback)renderCallback error:(NSError **)error { - @autoreleasepool { - AudioComponentDescription descr = {0}; - descr.componentType = kAudioUnitType_Output; - descr.componentSubType = kAudioUnitSubType_RemoteIO; - descr.componentManufacturer = kAudioUnitManufacturer_Apple; - descr.componentFlags = 0; - descr.componentFlagsMask = 0; - - AudioUnit audioUnit = NULL; - AudioComponent component = AudioComponentFindNext(NULL, &descr); - OSStatus status = AudioComponentInstanceNew(component, &audioUnit); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotCreateAudioComponent - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_CREATE_AUDIO_UNIT"] - andRawError:rawError]; - return NO; - } - - AudioStreamBasicDescription streamDescr = {0}; - UInt32 size = sizeof(AudioStreamBasicDescription); - status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotGetAudioStreamDescription - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_GET_AUDIO_STREAM_DESCRIPTION"] - andRawError:rawError]; - return NO; - } - - streamDescr.mSampleRate = sampleRate; - status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); - if (DLGPlayerUtils.debugEnabled && status != noErr) { - NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); - } - - _bitsPerChannel = streamDescr.mBitsPerChannel; - _channelsPerFrame = streamDescr.mChannelsPerFrame; - - AURenderCallbackStruct renderCallbackStruct; - renderCallbackStruct.inputProc = renderCallback; - renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); - - status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(AURenderCallbackStruct)); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotSetAudioRenderCallback - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_RENDER_CALLBACK"] - andRawError:rawError]; - return NO; - } - - status = AudioUnitInitialize(audioUnit); - if (status != noErr) { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotInitAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_INIT_AUDIO_UNIT"] - andRawError:rawError]; - return NO; - } - - _audioUnit = audioUnit; - - return YES; + AudioComponentDescription descr = {0}; + descr.componentType = kAudioUnitType_Output; + descr.componentSubType = kAudioUnitSubType_RemoteIO; + descr.componentManufacturer = kAudioUnitManufacturer_Apple; + descr.componentFlags = 0; + descr.componentFlagsMask = 0; + + AudioUnit audioUnit = NULL; + AudioComponent component = AudioComponentFindNext(NULL, &descr); + OSStatus status = AudioComponentInstanceNew(component, &audioUnit); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotCreateAudioComponent + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_CREATE_AUDIO_UNIT"] + andRawError:rawError]; + return NO; + } + + AudioStreamBasicDescription streamDescr = {0}; + UInt32 size = sizeof(AudioStreamBasicDescription); + status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotGetAudioStreamDescription + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_GET_AUDIO_STREAM_DESCRIPTION"] + andRawError:rawError]; + return NO; } + + streamDescr.mSampleRate = sampleRate; + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); + if (DLGPlayerUtils.debugEnabled && status != noErr) { + NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); + } + + _bitsPerChannel = streamDescr.mBitsPerChannel; + _channelsPerFrame = streamDescr.mChannelsPerFrame; + + AURenderCallbackStruct renderCallbackStruct; + renderCallbackStruct.inputProc = renderCallback; + renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); + + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(AURenderCallbackStruct)); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotSetAudioRenderCallback + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_SET_AUDIO_RENDER_CALLBACK"] + andRawError:rawError]; + return NO; + } + + status = AudioUnitInitialize(audioUnit); + if (status != noErr) { + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotInitAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_INIT_AUDIO_UNIT"] + andRawError:rawError]; + return NO; + } + + _audioUnit = audioUnit; + + return YES; } - (BOOL)close { @@ -255,21 +251,21 @@ - (BOOL)close:(NSArray **)errors { } _closing = YES; + + NSMutableArray *errs = nil; + if (errors != nil) errs = [NSMutableArray array]; - @autoreleasepool { - NSMutableArray *errs = nil; - if (errors != nil) errs = [NSMutableArray array]; - - BOOL closed = YES; + BOOL closed = YES; + + if (_opened) { + [self pause]; + [self unregisterNotifications]; - if (_opened) { - [self pause]; - [self unregisterNotifications]; - - OSStatus status = AudioUnitUninitialize(_audioUnit); - if (status != noErr) { - closed = NO; - if (errs != nil) { + OSStatus status = AudioUnitUninitialize(_audioUnit); + if (status != noErr) { + closed = NO; + if (errs != nil) { + @autoreleasepool { NSError *error = nil; NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:&error @@ -280,11 +276,13 @@ - (BOOL)close:(NSArray **)errors { [errs addObject:error]; } } - - status = AudioComponentInstanceDispose(_audioUnit); - if (status != noErr) { - closed = NO; - if (errs != nil) { + } + + status = AudioComponentInstanceDispose(_audioUnit); + if (status != noErr) { + closed = NO; + if (errs != nil) { + @autoreleasepool { NSError *error = nil; NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:&error @@ -295,13 +293,15 @@ - (BOOL)close:(NSArray **)errors { [errs addObject:error]; } } - - AVAudioSession *session = [AVAudioSession sharedInstance]; - NSError *error = nil; + } - if (![session setActive:NO error:&error]) { - closed = NO; - if (errs != nil) { + AVAudioSession *session = [AVAudioSession sharedInstance]; + NSError *error = nil; + + if (![session setActive:NO error:&error]) { + closed = NO; + if (errs != nil) { + @autoreleasepool { NSError *error = nil; NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; [DLGPlayerUtils createError:&error @@ -312,17 +312,17 @@ - (BOOL)close:(NSArray **)errors { [errs addObject:error]; } } - - if (closed) { - _opened = NO; - _audioUnit = NULL; - } } - _closing = NO; - - return closed; + if (closed) { + _opened = NO; + _audioUnit = NULL; + } } + + _closing = NO; + + return closed; } - (BOOL)play { @@ -422,38 +422,34 @@ - (UInt32)channels { #pragma mark - Notifications - (void)registerNotifications { - @autoreleasepool { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self - selector:@selector(notifyAudioSessionRouteChanged:) - name:AVAudioSessionRouteChangeNotification - object:nil]; - [nc addObserver:self - selector:@selector(notifyAudioSessionInterruptionNotification:) - name:AVAudioSessionInterruptionNotification - object:nil]; - - if (!_registeredKVO) { - AVAudioSession *session = [AVAudioSession sharedInstance]; - [session addObserver:self - forKeyPath:@"outputVolume" - options:0 - context:nil]; - _registeredKVO = YES; - } + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self + selector:@selector(notifyAudioSessionRouteChanged:) + name:AVAudioSessionRouteChangeNotification + object:nil]; + [nc addObserver:self + selector:@selector(notifyAudioSessionInterruptionNotification:) + name:AVAudioSessionInterruptionNotification + object:nil]; + + if (!_registeredKVO) { + AVAudioSession *session = [AVAudioSession sharedInstance]; + [session addObserver:self + forKeyPath:@"outputVolume" + options:0 + context:nil]; + _registeredKVO = YES; } } - (void)unregisterNotifications { - @autoreleasepool { - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc removeObserver:self]; - if (_registeredKVO) { - AVAudioSession *session = [AVAudioSession sharedInstance]; - [session removeObserver:self forKeyPath:@"outputVolume"]; - } - _registeredKVO = NO; + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self]; + if (_registeredKVO) { + AVAudioSession *session = [AVAudioSession sharedInstance]; + [session removeObserver:self forKeyPath:@"outputVolume"]; } + _registeredKVO = NO; } - (void)notifyAudioSessionRouteChanged:(NSNotification *)notif { @@ -478,11 +474,9 @@ - (void)notifyAudioSessionInterruptionNotification:(NSNotification *)notif { } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - @autoreleasepool { - AVAudioSession *session = [AVAudioSession sharedInstance]; - if (object == session && [keyPath isEqualToString:@"outputVolume"]) { - self.volume = session.outputVolume; - } + AVAudioSession *session = [AVAudioSession sharedInstance]; + if (object == session && [keyPath isEqualToString:@"outputVolume"]) { + self.volume = session.outputVolume; } } From b99849d430b147dd706560ca4ce8e9db98904d0f Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 12 May 2020 19:40:55 +0900 Subject: [PATCH 199/215] Fixed: crash solved. --- DLGPlayer/DLGPlayer.m | 106 ++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 56 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 09306ef..ec6f7de 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -163,21 +163,6 @@ - (void)open:(NSString *)url { __weak typeof(self)weakSelf = self; - dispatch_async(audioProcessingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (!strongSelf || strongSelf.opening || strongSelf.closing) { - return; - } - - if ([strongSelf.audio open:nil]) { - strongSelf.decoder.audioChannels = [strongSelf.audio channels]; - strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; - } - }); - dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; @@ -186,50 +171,59 @@ - (void)open:(NSString *)url { } strongSelf.opening = YES; - - NSError *error = nil; - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - [strongSelf handleError:error]; - return; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - if (!strongSelf || !strongSelf.opening || strongSelf.closing) { - return; - } - - if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { - DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; - [view setCurrentEAGLContext]; + + dispatch_async(audioProcessingQueue, ^{ + if ([strongSelf.audio open:nil]) { + strongSelf.decoder.audioChannels = [strongSelf.audio channels]; + strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; } - - strongSelf.view.isYUV = [strongSelf.decoder isYUV]; - strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; - strongSelf.view.rotation = strongSelf.decoder.rotation; - strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); - - if ([strongSelf.view isKindOfClass:[UIView class]]) { - ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; + + NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + [strongSelf handleError:error]; + return; } - strongSelf.duration = strongSelf.decoder.duration; - strongSelf.metadata = strongSelf.decoder.metadata; - strongSelf.opening = NO; - strongSelf.buffering = NO; - strongSelf.playing = NO; - strongSelf.bufferedDuration = 0; - strongSelf.mediaPosition = 0; - strongSelf.mediaSyncTime = 0; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - - strongSelf.opened = YES; - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (!strongSelf || !strongSelf.opening || strongSelf.closing) { + return; + } + + if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { + DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; + [view setCurrentEAGLContext]; + } + + strongSelf.view.isYUV = [strongSelf.decoder isYUV]; + strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; + strongSelf.view.rotation = strongSelf.decoder.rotation; + strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); + + if ([strongSelf.view isKindOfClass:[UIView class]]) { + ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; + } + + strongSelf.duration = strongSelf.decoder.duration; + strongSelf.metadata = strongSelf.decoder.metadata; + strongSelf.opening = NO; + strongSelf.buffering = NO; + strongSelf.playing = NO; + strongSelf.bufferedDuration = 0; + strongSelf.mediaPosition = 0; + strongSelf.mediaSyncTime = 0; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + + strongSelf.opened = YES; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; + }); }); }); } From a91a46bc382d1dcb9cfae58e3eb84c3bdf8e0ce9 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 13 May 2020 18:20:39 +0900 Subject: [PATCH 200/215] Fixed: null check. --- DLGPlayer/DLGPlayer.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index ec6f7de..0bbd013 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -299,7 +299,9 @@ - (void)pause { dispatch_async(audioProcessingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - [strongSelf.audio pause]; + if (strongSelf) { + [strongSelf.audio pause]; + } }); } From ba925f17ed3b6466c49bc3b8608db448790a2d95 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 15 May 2020 18:23:36 +0900 Subject: [PATCH 201/215] Fixed: solve memory leaks and crash. --- DLGPlayer/DLGPlayer.m | 163 ++++++++++------------ DLGPlayer/DLGSimplePlayerViewController.m | 108 +++++++------- DLGPlayer/codec/DLGPlayerDecoder.m | 104 +++++++------- DLGPlayer/view/MetalPlayerView.m | 20 +-- DLGPlayerDemo/RootViewController.swift | 26 +++- DLGPlayerDemo/ViewController.swift | 9 +- 6 files changed, 229 insertions(+), 201 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 0bbd013..50ad3df 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -24,8 +24,9 @@ @interface DLGPlayer () @property (nonatomic) double requestSeekPosition; @property (nonatomic, strong) NSMutableArray *vframes; @property (nonatomic, strong) NSMutableArray *aframes; -@property (nonatomic, strong) dispatch_queue_t processingQueue; -@property (nonatomic, strong) dispatch_queue_t renderingQueue; +@property (nonatomic, copy) dispatch_queue_t frameQueue; +@property (nonatomic, copy) dispatch_queue_t processingQueue; +@property (nonatomic, copy) dispatch_queue_t renderingQueue; @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; @property (nonatomic, strong) DLGPlayerAudioFrame *playingAudioFrame; @@ -43,9 +44,6 @@ @interface DLGPlayer () @property (atomic) double mediaSyncPosition; @end -static dispatch_queue_t audioProcessingQueue; -static dispatch_queue_t processingQueueStatic; - @implementation DLGPlayer - (id)init { @@ -97,16 +95,8 @@ - (void)initVars { _vframes = [NSMutableArray arrayWithCapacity:128]; _aframes = [NSMutableArray arrayWithCapacity:128]; _renderingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); - - if (!audioProcessingQueue) { - audioProcessingQueue = dispatch_queue_create("DLGPlayer.audioProcessingQueue", DISPATCH_QUEUE_SERIAL); - } - - if ([DLGPlayerUtils isMetalSupport]) { - _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); - } else if (!processingQueueStatic) { - processingQueueStatic = dispatch_queue_create("DLGPlayer.processingQueue", DISPATCH_QUEUE_SERIAL); - } + _frameQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.frameQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); + _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); } - (void)initView { @@ -152,10 +142,6 @@ - (void)clearVars { self.frameDropped = NO; } -- (dispatch_queue_t)processingQueue { - return [DLGPlayerUtils isMetalSupport] ? _processingQueue : processingQueueStatic; -} - - (void)open:(NSString *)url { if (self.opening || self.closing) { return; @@ -171,59 +157,57 @@ - (void)open:(NSString *)url { } strongSelf.opening = YES; + + if ([strongSelf.audio open:nil]) { + strongSelf.decoder.audioChannels = [strongSelf.audio channels]; + strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; + } - dispatch_async(audioProcessingQueue, ^{ - if ([strongSelf.audio open:nil]) { - strongSelf.decoder.audioChannels = [strongSelf.audio channels]; - strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; - } - - NSError *error = nil; - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - [strongSelf handleError:error]; + NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + [strongSelf handleError:error]; + return; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + if (!strongSelf || !strongSelf.opening || strongSelf.closing) { return; } - dispatch_async(dispatch_get_main_queue(), ^{ - if (!strongSelf || !strongSelf.opening || strongSelf.closing) { - return; - } - - if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { - DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; - [view setCurrentEAGLContext]; - } - - strongSelf.view.isYUV = [strongSelf.decoder isYUV]; - strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; - strongSelf.view.rotation = strongSelf.decoder.rotation; - strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); - - if ([strongSelf.view isKindOfClass:[UIView class]]) { - ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; - } - - strongSelf.duration = strongSelf.decoder.duration; - strongSelf.metadata = strongSelf.decoder.metadata; - strongSelf.opening = NO; - strongSelf.buffering = NO; - strongSelf.playing = NO; - strongSelf.bufferedDuration = 0; - strongSelf.mediaPosition = 0; - strongSelf.mediaSyncTime = 0; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - - strongSelf.opened = YES; - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; - }); + if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { + DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; + [view setCurrentEAGLContext]; + } + + strongSelf.view.isYUV = [strongSelf.decoder isYUV]; + strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; + strongSelf.view.rotation = strongSelf.decoder.rotation; + strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); + + if ([strongSelf.view isKindOfClass:[UIView class]]) { + ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; + } + + strongSelf.duration = strongSelf.decoder.duration; + strongSelf.metadata = strongSelf.decoder.metadata; + strongSelf.opening = NO; + strongSelf.buffering = NO; + strongSelf.playing = NO; + strongSelf.bufferedDuration = 0; + strongSelf.mediaPosition = 0; + strongSelf.mediaSyncTime = 0; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + + strongSelf.opened = YES; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; }); }); } @@ -233,41 +217,39 @@ - (void)close { return; } - [self pause]; - __weak typeof(self)weakSelf = self; - dispatch_async(audioProcessingQueue, ^{ + dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || strongSelf.closing || !strongSelf.opened) { return; } + strongSelf.closing = YES; + strongSelf.playing = NO; + if ([strongSelf.audio close:nil]) { [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:strongSelf]; } - }); - - dispatch_async(self.processingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (!strongSelf || strongSelf.closing || !strongSelf.opened) { - return; - } - strongSelf.closing = YES; + dispatch_async(strongSelf.frameQueue, ^{ + [strongSelf runFrameReader]; + [strongSelf.decoder prepareClose]; + [strongSelf.decoder close]; + }); - [strongSelf.decoder prepareClose]; - [strongSelf.decoder close]; [strongSelf.view clear]; [strongSelf clearVars]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; }); } - (void)play { + if (!self.opened || self.playing || self.closing) { + return; + } + __weak typeof(self)weakSelf = self; dispatch_async(self.processingQueue, ^{ @@ -283,23 +265,26 @@ - (void)play { [strongSelf render]; }); - dispatch_async(audioProcessingQueue, ^{ - [strongSelf.audio play]; + dispatch_async(strongSelf.frameQueue, ^{ + [strongSelf runFrameReader]; }); - - [strongSelf runFrameReader]; + [strongSelf.audio play]; }); } - (void)pause { - self.playing = NO; + if (!self.playing) { + return; + } __weak typeof(self)weakSelf = self; - dispatch_async(audioProcessingQueue, ^{ + dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf) { + strongSelf.playing = NO; + [strongSelf.audio pause]; } }); diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index a0accb3..d7eb0a2 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -81,114 +81,120 @@ - (BOOL)hasUrl { } - (BOOL)isPlaying { - return self.player.playing; + return _player.playing; } - (void)setStatus:(DLGPlayerStatus)status { _status = status; [_controlStatus setStatus:_status]; + __weak typeof(self)weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ - if ([self.delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { - [self.delegate viewController:self didChangeStatus:status]; + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf && [strongSelf.delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { + [strongSelf.delegate viewController:strongSelf didChangeStatus:status]; } }); } - (BOOL)isMute { - return self.player.mute; + return _player.mute; } - (void)setIsMute:(BOOL)isMute { - self.player.mute = isMute; + _player.mute = isMute; } - (double)minBufferDuration { - return self.player.minBufferDuration; + return _player.minBufferDuration; } - (void)setMinBufferDuration:(double)minBufferDuration { - self.player.minBufferDuration = minBufferDuration; + _player.minBufferDuration = minBufferDuration; } - (double)maxBufferDuration { - return self.player.maxBufferDuration; + return _player.maxBufferDuration; } - (void)setMaxBufferDuration:(double)maxBufferDuration { - self.player.maxBufferDuration = maxBufferDuration; + _player.maxBufferDuration = maxBufferDuration; } - (BOOL)isAllowsFrameDrop { - return self.player.allowsFrameDrop; + return _player.allowsFrameDrop; } - (void)setIsAllowsFrameDrop:(BOOL)isAllowsFrameDrop { - self.player.allowsFrameDrop = isAllowsFrameDrop; + _player.allowsFrameDrop = isAllowsFrameDrop; } - (double)speed { - return self.player.speed; + return _player.speed; } - (void)setSpeed:(double)speed { - self.player.speed = speed; + _player.speed = speed; } #pragma mark - Init - (void)initAll { - self.player = [[DLGPlayer alloc] init]; + _player = [[DLGPlayer alloc] init]; _status = DLGPlayerStatusNone; _controlStatus = [[DLGPlayerControlStatus alloc] initWithStatus:_status]; } - (void)open { self.status = DLGPlayerStatusOpening; - [self.player open:_url]; + [_player open:_url]; } - (void)play { - [UIApplication sharedApplication].idleTimerDisabled = self.preventFromScreenLock; - [self.player play]; +// [UIApplication sharedApplication].idleTimerDisabled = self.preventFromScreenLock; + [_player play]; self.status = DLGPlayerStatusPlaying; } - (void)replay { - self.player.position = 0; + _player.position = 0; [self play]; } - (void)pause { - [UIApplication sharedApplication].idleTimerDisabled = NO; - [self.player pause]; +// [UIApplication sharedApplication].idleTimerDisabled = NO; + [_player pause]; self.status = DLGPlayerStatusPaused; } - (void)stop { self.status = DLGPlayerStatusClosing; - [UIApplication sharedApplication].idleTimerDisabled = NO; - [self.player close]; +// [UIApplication sharedApplication].idleTimerDisabled = NO; + [_player close]; } #pragma mark - UI - (void)addPlayerView { - UIView *v = self.player.playerView; + UIView *v = _player.playerView; v.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:v]; - // Add constraints - NSDictionary *views = NSDictionaryOfVariableBindings(v); - NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" - options:0 - metrics:nil - views:views]; - [self.view addConstraints:ch]; - NSArray *cv = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" - options:0 - metrics:nil - views:views]; - [self.view addConstraints:cv]; + @autoreleasepool { + // Add constraints + NSDictionary *views = NSDictionaryOfVariableBindings(v); + NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:ch]; + NSArray *cv = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:cv]; + } } #pragma mark - Notifications @@ -198,14 +204,14 @@ - (void)registerNotification { name:UIApplicationDidEnterBackgroundNotification object:nil]; [nc addObserver:self selector:@selector(notifyAppWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; - [nc addObserver:self selector:@selector(notifyPlayerAudioOpened:) name:DLGPlayerNotificationAudioOpened object:self.player]; - [nc addObserver:self selector:@selector(notifyPlayerAudioClosed:) name:DLGPlayerNotificationAudioClosed object:self.player]; - [nc addObserver:self selector:@selector(notifyPlayerOpened:) name:DLGPlayerNotificationOpened object:self.player]; - [nc addObserver:self selector:@selector(notifyPlayerClosed:) name:DLGPlayerNotificationClosed object:self.player]; - [nc addObserver:self selector:@selector(notifyPlayerEOF:) name:DLGPlayerNotificationEOF object:self.player]; - [nc addObserver:self selector:@selector(notifyPlayerBufferStateChanged:) name:DLGPlayerNotificationBufferStateChanged object:self.player]; - [nc addObserver:self selector:@selector(notifyPlayerRenderBegan:) name:DLGPlayerNotificationRenderBegan object:self.player]; - [nc addObserver:self selector:@selector(notifyPlayerError:) name:DLGPlayerNotificationError object:self.player]; + [nc addObserver:self selector:@selector(notifyPlayerAudioOpened:) name:DLGPlayerNotificationAudioOpened object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerAudioClosed:) name:DLGPlayerNotificationAudioClosed object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerOpened:) name:DLGPlayerNotificationOpened object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerClosed:) name:DLGPlayerNotificationClosed object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerEOF:) name:DLGPlayerNotificationEOF object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerBufferStateChanged:) name:DLGPlayerNotificationBufferStateChanged object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerRenderBegan:) name:DLGPlayerNotificationRenderBegan object:_player]; + [nc addObserver:self selector:@selector(notifyPlayerError:) name:DLGPlayerNotificationError object:_player]; } - (void)unregisterNotification { @@ -213,7 +219,7 @@ - (void)unregisterNotification { } - (void)notifyAppDidEnterBackground:(NSNotification *)notif { - if (self.player.playing) { + if (_player.playing) { [self pause]; if (_restorePlayAfterAppEnterForeground) restorePlay = YES; } @@ -286,10 +292,18 @@ - (void)notifyPlayerError:(NSNotification *)notif { } } + __weak typeof(self)weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ - if ([self.delegate respondsToSelector:@selector(viewController:didReceiveError:)]) { - [self.delegate viewController:self didReceiveError:error]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:self userInfo:notif.userInfo]; + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + if ([strongSelf.delegate respondsToSelector:@selector(viewController:didReceiveError:)]) { + [strongSelf.delegate viewController:strongSelf didReceiveError:error]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:strongSelf userInfo:notif.userInfo]; } }); } diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index 20b8348..b0bd836 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -372,69 +372,67 @@ - (NSArray *)readFrames { return nil; } - @autoreleasepool { - AVFormatContext *fmtctx = m_pFormatContext; - const int vstream = m_nVideoStream; - AVFrame *vframe = m_pVideoFrame; - AVFrame *vswsframe = m_pVideoSwsFrame; - AVCodecContext *vcodectx = m_pVideoCodecContext; - struct SwsContext *swsctx = m_pVideoSwsContext; - const int picstream = m_nPictureStream; - const int astream = m_nAudioStream; - AVFrame *aframe = m_pAudioFrame; - AVCodecContext *acodectx = m_pAudioCodecContext; - SwrContext *swrctx = m_pAudioSwrContext; - void **swrbuf = &m_pAudioSwrBuffer; - int *swrbufsize = &m_nAudioSwrBufferSize; - - AVPacket packet; + AVFormatContext *fmtctx = m_pFormatContext; + const int vstream = m_nVideoStream; + AVFrame *vframe = m_pVideoFrame; + AVFrame *vswsframe = m_pVideoSwsFrame; + AVCodecContext *vcodectx = m_pVideoCodecContext; + struct SwsContext *swsctx = m_pVideoSwsContext; + const int picstream = m_nPictureStream; + const int astream = m_nAudioStream; + AVFrame *aframe = m_pAudioFrame; + AVCodecContext *acodectx = m_pAudioCodecContext; + SwrContext *swrctx = m_pAudioSwrContext; + void **swrbuf = &m_pAudioSwrBuffer; + int *swrbufsize = &m_nAudioSwrBufferSize; + + AVPacket packet; + + NSMutableArray *frames = [NSMutableArray arrayWithCapacity:15]; + BOOL reading = YES; + + while (reading) { + g_dIOStartTime = [NSDate timeIntervalSinceReferenceDate]; + int ret = av_read_frame(fmtctx, &packet); + if (ret < 0) { + if (ret == AVERROR_EOF) self.isEOF = YES; + char *e = av_err2str(ret); + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"DLGPlayer read frame error: %s", e); + } + break; + } - NSMutableArray *frames = [NSMutableArray arrayWithCapacity:15]; - BOOL reading = YES; + /* + * https://ffmpeg.org/doxygen/3.1/group__lavc__encdec.html + */ + NSArray *fs = nil; - while (reading) { - g_dIOStartTime = [NSDate timeIntervalSinceReferenceDate]; - int ret = av_read_frame(fmtctx, &packet); - if (ret < 0) { - if (ret == AVERROR_EOF) self.isEOF = YES; - char *e = av_err2str(ret); - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer read frame error: %s", e); - } - break; - } - - /* - * https://ffmpeg.org/doxygen/3.1/group__lavc__encdec.html - */ - NSArray *fs = nil; + if (packet.stream_index == vstream) { + fs = [self handleVideoPacket:&packet byContext:vcodectx andFrame:vframe andSwsContext:swsctx andSwsFrame:vswsframe]; + reading = NO; + } else if (packet.stream_index == astream) { + fs = [self handleAudioPacket:&packet byContext:acodectx andFrame:aframe andSwrContext:swrctx andSwrBuffer:swrbuf andSwrBufferSize:swrbufsize]; - if (packet.stream_index == vstream) { - fs = [self handleVideoPacket:&packet byContext:vcodectx andFrame:vframe andSwsContext:swsctx andSwsFrame:vswsframe]; + if (!_hasVideo) { reading = NO; - } else if (packet.stream_index == astream) { - fs = [self handleAudioPacket:&packet byContext:acodectx andFrame:aframe andSwrContext:swrctx andSwrBuffer:swrbuf andSwrBufferSize:swrbufsize]; - - if (!_hasVideo) { - reading = NO; - } - } else if (packet.stream_index == picstream) { - fs = [self handlePicturePacket:&packet]; - - if (!_hasVideo && !_hasAudio) { - reading = NO; - } } + } else if (packet.stream_index == picstream) { + fs = [self handlePicturePacket:&packet]; - if (fs != nil && fs.count > 0) { - [frames addObjectsFromArray:fs]; + if (!_hasVideo && !_hasAudio) { + reading = NO; } - - av_packet_unref(&packet); } - return frames; + if (fs != nil && fs.count > 0) { + [frames addObjectsFromArray:fs]; + } + + av_packet_unref(&packet); } + + return frames; } - (NSArray *)handlePicturePacket:(AVPacket *)packet { diff --git a/DLGPlayer/view/MetalPlayerView.m b/DLGPlayer/view/MetalPlayerView.m index 19d136c..d52c416 100644 --- a/DLGPlayer/view/MetalPlayerView.m +++ b/DLGPlayer/view/MetalPlayerView.m @@ -205,15 +205,17 @@ - (UIImage *)snapshot { return nil; } - const id texture = metalView.currentDrawable.texture; - const NSInteger w = texture.width; - const NSInteger h = texture.height; - CIContext *context = [CIContext contextWithMTLDevice:metalView.device]; - CIImage *outputImage = [[CIImage alloc] initWithMTLTexture:texture options:@{kCIImageColorSpace: (__bridge_transfer id) CGColorSpaceCreateDeviceRGB()}]; - CGImageRef cgImg = [context createCGImage:outputImage fromRect:CGRectMake(0, 0, w, h)]; - UIImage *resultImg = [UIImage imageWithCGImage:cgImg scale:UIScreen.mainScreen.scale orientation:UIImageOrientationDownMirrored]; - CGImageRelease(cgImg); - return resultImg; + @autoreleasepool { + const id texture = metalView.currentDrawable.texture; + const NSInteger w = texture.width; + const NSInteger h = texture.height; + CIContext *context = [CIContext contextWithMTLDevice:metalView.device]; + CIImage *outputImage = [[CIImage alloc] initWithMTLTexture:texture options:@{kCIImageColorSpace: (__bridge_transfer id) CGColorSpaceCreateDeviceRGB()}]; + CGImageRef cgImg = [context createCGImage:outputImage fromRect:CGRectMake(0, 0, w, h)]; + UIImage *resultImg = [UIImage imageWithCGImage:cgImg scale:UIScreen.mainScreen.scale orientation:UIImageOrientationDownMirrored]; + CGImageRelease(cgImg); + return resultImg; + } #endif } diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index dd23ea4..a42f6de 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -20,8 +20,8 @@ final class RootViewController: UIViewController { private var isFirstViewAppearance = true deinit { - print("deinit") - + print("RootViewController deinit") + navigationItem.rightBarButtonItem = nil } private func createPlayers() { @@ -129,7 +129,29 @@ final class RootViewController: UIViewController { } @IBAction private func refreshButtonClicked(_ sender: UIButton) { } + + private var isPlaying = true @IBAction private func stopButtonClicked() { + guard let vc = players.first else { + return + } + + if isPlaying { + vc.stop() + } else { + vc.url = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" + vc.open() + } + + isPlaying = !isPlaying + + if #available(iOS 10.0, *) { + Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in + self?.stopButtonClicked() + } + } else { + // Fallback on earlier versions + } } @IBAction private func valueChanged(_ sender: UISlider) { } diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index f355d9e..ea8a49d 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -10,14 +10,21 @@ import Foundation class ViewController: UIViewController { + deinit { + navigationItem.rightBarButtonItem = nil + } + override func viewDidLoad() { super.viewDidLoad() + navigationItem.rightBarButtonItem = .init(title: "open", style: .plain, target: self, action: #selector(clicked)) + } + + @objc private func clicked() { guard let vc = storyboard?.instantiateViewController(withIdentifier: "RootViewController") else { return } navigationController?.pushViewController(vc, animated: false) } - } From 3b7f0e595a8ea42d2e2dd36104d0b423509d0df0 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Sun, 17 May 2020 01:39:03 +0900 Subject: [PATCH 202/215] Updated: property frameDropDuration is added. Updated: rollback to origin logic instead of using dispatch queues. Updated: remove or add autorelease pool. --- DLGPlayer/DLGPlayer.m | 338 +++++++++++----------- DLGPlayer/DLGSimplePlayerViewController.h | 1 + DLGPlayer/DLGSimplePlayerViewController.m | 37 +-- DLGPlayer/codec/DLGPlayerAudioManager.m | 84 +++--- DLGPlayer/codec/DLGPlayerDecoder.m | 316 ++++++++++---------- DLGPlayer/common/DLGPlayerDef.h | 2 +- 6 files changed, 378 insertions(+), 400 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 50ad3df..f6580db 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -24,15 +24,14 @@ @interface DLGPlayer () @property (nonatomic) double requestSeekPosition; @property (nonatomic, strong) NSMutableArray *vframes; @property (nonatomic, strong) NSMutableArray *aframes; -@property (nonatomic, copy) dispatch_queue_t frameQueue; -@property (nonatomic, copy) dispatch_queue_t processingQueue; -@property (nonatomic, copy) dispatch_queue_t renderingQueue; @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; +@property (nonatomic, strong) dispatch_queue_t renderingQueue; @property (nonatomic, strong) DLGPlayerAudioFrame *playingAudioFrame; @property (nonatomic, strong) DLGPlayerDecoder *decoder; @property (nonatomic, strong) DLGPlayerAudioManager *audio; @property (nonatomic, strong) id view; +@property (nonatomic, strong) NSThread *frameReaderThread; @property (atomic) BOOL closing; @property (atomic) BOOL opening; @@ -95,8 +94,6 @@ - (void)initVars { _vframes = [NSMutableArray arrayWithCapacity:128]; _aframes = [NSMutableArray arrayWithCapacity:128]; _renderingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); - _frameQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.frameQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); - _processingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); } - (void)initView { @@ -143,50 +140,41 @@ - (void)clearVars { } - (void)open:(NSString *)url { - if (self.opening || self.closing) { - return; - } - __weak typeof(self)weakSelf = self; - - dispatch_async(self.processingQueue, ^{ + + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - - if (!strongSelf || strongSelf.opening || strongSelf.closing) { + if (!strongSelf) { return; } - + + NSError *error = nil; strongSelf.opening = YES; - if ([strongSelf.audio open:nil]) { + if ([strongSelf.audio open:&error]) { strongSelf.decoder.audioChannels = [strongSelf.audio channels]; strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; + } else { + [strongSelf handleError:error]; } - - NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { strongSelf.opening = NO; [strongSelf handleError:error]; return; } - dispatch_async(dispatch_get_main_queue(), ^{ - if (!strongSelf || !strongSelf.opening || strongSelf.closing) { - return; - } - if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; [view setCurrentEAGLContext]; } - + strongSelf.view.isYUV = [strongSelf.decoder isYUV]; strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; strongSelf.view.rotation = strongSelf.decoder.rotation; strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); - + if ([strongSelf.view isKindOfClass:[UIView class]]) { ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; } @@ -206,116 +194,116 @@ - (void)open:(NSString *)url { }; strongSelf.opened = YES; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; }); }); } - (void)close { - if (self.closing || !self.opened) { + if (!self.opened && !self.opening) { + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:self]; return; } - + + [self pause]; + [self.decoder prepareClose]; + + dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); + dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC); + __weak typeof(self)weakSelf = self; - - dispatch_async(self.processingQueue, ^{ + + dispatch_source_set_event_handler(timer, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - - if (!strongSelf || strongSelf.closing || !strongSelf.opened) { + if (!strongSelf) { return; } - - strongSelf.closing = YES; - strongSelf.playing = NO; - - if ([strongSelf.audio close:nil]) { + + if (strongSelf.opening || strongSelf.buffering) return; + [strongSelf.decoder close]; + + NSArray *errors = nil; + if ([strongSelf.audio close:&errors]) { + [strongSelf clearVars]; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:strongSelf]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; + } else { + for (NSError *error in errors) { + [strongSelf handleError:error]; + } } - - dispatch_async(strongSelf.frameQueue, ^{ - [strongSelf runFrameReader]; - [strongSelf.decoder prepareClose]; - [strongSelf.decoder close]; - }); - - [strongSelf.view clear]; - [strongSelf clearVars]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; + dispatch_cancel(timer); }); + dispatch_resume(timer); } - (void)play { - if (!self.opened || self.playing || self.closing) { - return; - } - __weak typeof(self)weakSelf = self; + if (!self.opened || self.playing) return; - dispatch_async(self.processingQueue, ^{ + self.playing = YES; + __weak typeof(self)weakSelf = self; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - - if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { + if (!strongSelf) { return; } - - strongSelf.playing = YES; - - dispatch_async(dispatch_get_main_queue(), ^{ - [strongSelf render]; - }); - - dispatch_async(strongSelf.frameQueue, ^{ - [strongSelf runFrameReader]; - }); - [strongSelf.audio play]; + + [strongSelf render]; + [strongSelf startFrameReaderThread]; }); + + NSError *error = nil; + if (![self.audio play:&error]) { + [self handleError:error]; + } } - (void)pause { - if (!self.playing) { - return; + self.playing = NO; + NSError *error = nil; + + if (![self.audio pause:&error]) { + [self handleError:error]; } - - __weak typeof(self)weakSelf = self; - - dispatch_async(self.processingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf) { - strongSelf.playing = NO; - - [strongSelf.audio pause]; - } - }); } - (UIImage *)snapshot { return [_view snapshot]; } +- (void)startFrameReaderThread { + if (self.frameReaderThread == nil) { + self.frameReaderThread = [[NSThread alloc] initWithTarget:self selector:@selector(runFrameReader) object:nil]; + [self.frameReaderThread start]; + } +} + - (void)runFrameReader { - while (self.playing && !self.closing) { - [self readFrame]; - - if (self.requestSeek) { - [self seekPositionInFrameReader]; - } else { - [NSThread sleepForTimeInterval:1.5]; + @autoreleasepool { + while (self.playing) { + [self readFrame]; + if (self.requestSeek) { + [self seekPositionInFrameReader]; + } else { + [NSThread sleepForTimeInterval:1.5]; + } } + self.frameReaderThread = nil; } } - (void)readFrame { self.buffering = YES; - @autoreleasepool { - double tempDuration = 0; - NSMutableArray *tempVFrames = [NSMutableArray arrayWithCapacity:8]; - NSMutableArray *tempAFrames = [NSMutableArray arrayWithCapacity:8]; - dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); - - while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek) { + NSMutableArray *tempVFrames = [NSMutableArray arrayWithCapacity:8]; + NSMutableArray *tempAFrames = [NSMutableArray arrayWithCapacity:8]; + double tempDuration = 0; + dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); + + while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek) { + @autoreleasepool { // Drop frames if (self.allowsFrameDrop && !self.frameDropped) { if (self.bufferedDuration > self.frameDropDuration / self.speed) { @@ -397,31 +385,31 @@ - (void)readFrame { } } } - - { - // add the rest video frames - while (tempVFrames.count > 0 || tempAFrames.count > 0) { - if (tempVFrames.count > 0) { - long timeout = dispatch_semaphore_wait(self.vFramesLock, t); - if (timeout == 0) { + } + + { + // add the rest video frames + while (tempVFrames.count > 0 || tempAFrames.count > 0) { + if (tempVFrames.count > 0) { + long timeout = dispatch_semaphore_wait(self.vFramesLock, t); + if (timeout == 0) { + self.bufferedDuration += tempDuration; + tempDuration = 0; + [self.vframes addObjectsFromArray:tempVFrames]; + [tempVFrames removeAllObjects]; + dispatch_semaphore_signal(self.vFramesLock); + } + } + if (tempAFrames.count > 0) { + long timeout = dispatch_semaphore_wait(self.aFramesLock, t); + if (timeout == 0) { + if (!self.decoder.hasVideo) { self.bufferedDuration += tempDuration; tempDuration = 0; - [self.vframes addObjectsFromArray:tempVFrames]; - [tempVFrames removeAllObjects]; - dispatch_semaphore_signal(self.vFramesLock); - } - } - if (tempAFrames.count > 0) { - long timeout = dispatch_semaphore_wait(self.aFramesLock, t); - if (timeout == 0) { - if (!self.decoder.hasVideo) { - self.bufferedDuration += tempDuration; - tempDuration = 0; - } - [self.aframes addObjectsFromArray:tempAFrames]; - [tempAFrames removeAllObjects]; - dispatch_semaphore_signal(self.aFramesLock); } + [self.aframes addObjectsFromArray:tempAFrames]; + [tempAFrames removeAllObjects]; + dispatch_semaphore_signal(self.aFramesLock); } } } @@ -533,15 +521,17 @@ - (void)render { } - (void)renderView:(DLGPlayerVideoFrame *)frame { + __weak typeof(self)weakSelf = self; + dispatch_sync(self.renderingQueue, ^{ - [self.view render:frame]; + __strong typeof(weakSelf)strongSelf = weakSelf; - if (!self.renderBegan && frame.width > 0 && frame.height > 0) { - self.renderBegan = YES; + [strongSelf.view render:frame]; + + if (!strongSelf.renderBegan && frame.width > 0 && frame.height > 0) { + strongSelf.renderBegan = YES; - dispatch_async(dispatch_get_main_queue(), ^{ - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationRenderBegan object:self]; - }); + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationRenderBegan object:strongSelf]; } }); } @@ -576,66 +566,68 @@ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)chan } while(frames > 0) { - if (self.playingAudioFrame == nil) { - { - if (self.aframes.count <= 0) { - memset(data, 0, frames * channels * sizeof(float)); - return; - } - - long timeout = dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW); - if (timeout == 0) { - DLGPlayerAudioFrame *frame = self.aframes[0]; + @autoreleasepool { + if (self.playingAudioFrame == nil) { + { + if (self.aframes.count <= 0) { + memset(data, 0, frames * channels * sizeof(float)); + return; + } - if (self.decoder.hasVideo) { - const double dt = self.mediaPosition - frame.position; + long timeout = dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW); + if (timeout == 0) { + DLGPlayerAudioFrame *frame = self.aframes[0]; - if (dt < -0.1 && self.vframes.count > 0) { // audio is faster than video, silence - memset(data, 0, frames * channels * sizeof(float)); - dispatch_semaphore_signal(self.aFramesLock); - break; - } else if (dt > 0.1) { // audio is slower than video, skip - [self.aframes removeObjectAtIndex:0]; - dispatch_semaphore_signal(self.aFramesLock); - continue; + if (self.decoder.hasVideo) { + const double dt = self.mediaPosition - frame.position; + + if (dt < -0.1 && self.vframes.count > 0) { // audio is faster than video, silence + memset(data, 0, frames * channels * sizeof(float)); + dispatch_semaphore_signal(self.aFramesLock); + break; + } else if (dt > 0.1) { // audio is slower than video, skip + [self.aframes removeObjectAtIndex:0]; + dispatch_semaphore_signal(self.aFramesLock); + continue; + } else { + self.playingAudioFrameDataPosition = 0; + self.playingAudioFrame = frame; + [self.aframes removeObjectAtIndex:0]; + } } else { self.playingAudioFrameDataPosition = 0; self.playingAudioFrame = frame; [self.aframes removeObjectAtIndex:0]; + self.mediaPosition = frame.position; + self.bufferedDuration -= frame.duration; } - } else { - self.playingAudioFrameDataPosition = 0; - self.playingAudioFrame = frame; - [self.aframes removeObjectAtIndex:0]; - self.mediaPosition = frame.position; - self.bufferedDuration -= frame.duration; - } - dispatch_semaphore_signal(self.aFramesLock); - } else return; + dispatch_semaphore_signal(self.aFramesLock); + } else return; + } + } + + NSData *frameData = self.playingAudioFrame.data; + NSUInteger pos = self.playingAudioFrameDataPosition; + if (frameData == nil) { + memset(data, 0, frames * channels * sizeof(float)); + return; + } + + const void *bytes = (Byte *)frameData.bytes + pos; + const NSUInteger remainingBytes = frameData.length - pos; + const NSUInteger channelSize = channels * sizeof(float); + const NSUInteger bytesToCopy = MIN(frames * channelSize, remainingBytes); + const NSUInteger framesToCopy = bytesToCopy / channelSize; + + memcpy(data, bytes, bytesToCopy); + frames -= framesToCopy; + data += framesToCopy * channels; + + if (bytesToCopy < remainingBytes) { + self.playingAudioFrameDataPosition += bytesToCopy; + } else { + self.playingAudioFrame = nil; } - } - - NSData *frameData = self.playingAudioFrame.data; - NSUInteger pos = self.playingAudioFrameDataPosition; - if (frameData == nil) { - memset(data, 0, frames * channels * sizeof(float)); - return; - } - - const void *bytes = (Byte *)frameData.bytes + pos; - const NSUInteger remainingBytes = frameData.length - pos; - const NSUInteger channelSize = channels * sizeof(float); - const NSUInteger bytesToCopy = MIN(frames * channelSize, remainingBytes); - const NSUInteger framesToCopy = bytesToCopy / channelSize; - - memcpy(data, bytes, bytesToCopy); - frames -= framesToCopy; - data += framesToCopy * channels; - - if (bytesToCopy < remainingBytes) { - self.playingAudioFrameDataPosition += bytesToCopy; - } else { - self.playingAudioFrame = nil; } } } diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index d8cde1b..279063b 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -27,6 +27,7 @@ @property (nonatomic) BOOL isRepeat; @property (nonatomic) BOOL preventFromScreenLock; @property (nonatomic) BOOL restorePlayAfterAppEnterForeground; +@property (nonatomic) double frameDropDuration; @property (nonatomic) double minBufferDuration; @property (nonatomic) double maxBufferDuration; @property (nonatomic) double speed; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index d7eb0a2..c4b2276 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -102,15 +102,20 @@ - (void)setStatus:(DLGPlayerStatus)status { - (BOOL)isMute { return _player.mute; } - - (void)setIsMute:(BOOL)isMute { _player.mute = isMute; } +- (double)frameDropDuration { + return _player.frameDropDuration; +} +- (void)setFrameDropDuration:(double)frameDropDuration { + _player.frameDropDuration = frameDropDuration; +} + - (double)minBufferDuration { return _player.minBufferDuration; } - - (void)setMinBufferDuration:(double)minBufferDuration { _player.minBufferDuration = minBufferDuration; } @@ -118,7 +123,6 @@ - (void)setMinBufferDuration:(double)minBufferDuration { - (double)maxBufferDuration { return _player.maxBufferDuration; } - - (void)setMaxBufferDuration:(double)maxBufferDuration { _player.maxBufferDuration = maxBufferDuration; } @@ -126,7 +130,6 @@ - (void)setMaxBufferDuration:(double)maxBufferDuration { - (BOOL)isAllowsFrameDrop { return _player.allowsFrameDrop; } - - (void)setIsAllowsFrameDrop:(BOOL)isAllowsFrameDrop { _player.allowsFrameDrop = isAllowsFrameDrop; } @@ -181,20 +184,18 @@ - (void)addPlayerView { [self.view addSubview:v]; - @autoreleasepool { - // Add constraints - NSDictionary *views = NSDictionaryOfVariableBindings(v); - NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" - options:0 - metrics:nil - views:views]; - [self.view addConstraints:ch]; - NSArray *cv = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" - options:0 - metrics:nil - views:views]; - [self.view addConstraints:cv]; - } + // Add constraints + NSDictionary *views = NSDictionaryOfVariableBindings(v); + NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:ch]; + NSArray *cv = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:cv]; } #pragma mark - Notifications diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index bc05a2f..1d4976a 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -85,7 +85,7 @@ - (void)dealloc { - (BOOL)open:(NSError **)error { NSError *rawError = nil; AVAudioSession *session = [AVAudioSession sharedInstance]; - AVAudioSessionCategory category = self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategorySoloAmbient; + AVAudioSessionCategory category = self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategoryPlayback; if (![session setCategory:category error:&rawError]) { [DLGPlayerUtils createError:error @@ -265,16 +265,14 @@ - (BOOL)close:(NSArray **)errors { if (status != noErr) { closed = NO; if (errs != nil) { - @autoreleasepool { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotUninitAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT"] - andRawError:rawError]; - [errs addObject:error]; - } + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotUninitAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT"] + andRawError:rawError]; + [errs addObject:error]; } } @@ -282,16 +280,14 @@ - (BOOL)close:(NSArray **)errors { if (status != noErr) { closed = NO; if (errs != nil) { - @autoreleasepool { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotDisposeAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT"] - andRawError:rawError]; - [errs addObject:error]; - } + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotDisposeAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT"] + andRawError:rawError]; + [errs addObject:error]; } } @@ -301,16 +297,14 @@ - (BOOL)close:(NSArray **)errors { if (![session setActive:NO error:&error]) { closed = NO; if (errs != nil) { - @autoreleasepool { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotDeactivateAudio - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] - andRawError:rawError]; - [errs addObject:error]; - } + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotDeactivateAudio + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] + andRawError:rawError]; + [errs addObject:error]; } } @@ -338,14 +332,12 @@ - (BOOL)play:(NSError **)error { OSStatus status = AudioOutputUnitStart(_audioUnit); _playing = (status == noErr); if (!_playing) { - @autoreleasepool { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotStartAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_START_AUDIO_UNIT"] - andRawError:rawError]; - } + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotStartAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_START_AUDIO_UNIT"] + andRawError:rawError]; } } return _playing; @@ -364,14 +356,12 @@ - (BOOL)pause:(NSError **)error { OSStatus status = AudioOutputUnitStop(_audioUnit); _playing = !(status == noErr); if (_playing) { - @autoreleasepool { - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotStopAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_STOP_AUDIO_UNIT"] - andRawError:rawError]; - } + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotStopAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_STOP_AUDIO_UNIT"] + andRawError:rawError]; } } return !_playing; diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index b0bd836..cbd195f 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -492,73 +492,71 @@ - (NSArray *)readFrames { return nil; } - @autoreleasepool { - NSMutableArray *frames = [NSMutableArray array]; - do { - ret = avcodec_receive_frame(context, frame); - if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { - break; - } else if (ret < 0) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"avcodec_receive_frame: %d", ret); - } - break; - } - - DLGPlayerVideoFrame *f = nil; - const int width = context->width; - const int height = context->height; - if (_isYUV) { - DLGPlayerVideoYUVFrame *yuv = [[DLGPlayerVideoYUVFrame alloc] init]; - yuv.Y = [DLGPlayerDecoder dataFromVideoFrame:frame->data[0] - linesize:frame->linesize[0] - width:width - height:height]; - yuv.Cb = [DLGPlayerDecoder dataFromVideoFrame:frame->data[1] - linesize:frame->linesize[1] - width:width / 2 - height:height / 2]; - yuv.Cr = [DLGPlayerDecoder dataFromVideoFrame:frame->data[2] - linesize:frame->linesize[2] - width:width / 2 - height:height / 2]; - f = yuv; - } else { - sws_scale(swsctx, - (uint8_t const **)frame->data, - frame->linesize, - 0, - context->height, - swsframe->data, - swsframe->linesize); - - DLGPlayerVideoRGBFrame *rgb = [[DLGPlayerVideoRGBFrame alloc] init]; - rgb.linesize = swsframe->linesize[0]; - rgb.data = [NSData dataWithBytes:swsframe->data[0] length:rgb.linesize * height]; - f = rgb; - } - - f.width = width; - f.height = height; - f.position = frame->best_effort_timestamp * _videoTimebase; - - double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevVideo; - - if (duration > 0) { - f.duration = duration * _videoTimebase / _speed; - f.duration += (frame->repeat_pict * _videoTimebase * 0.5) / _speed; - } else { - f.duration = 1 / _videoFPS / _speed; + NSMutableArray *frames = [NSMutableArray array]; + do { + ret = avcodec_receive_frame(context, frame); + if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { + break; + } else if (ret < 0) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"avcodec_receive_frame: %d", ret); } + break; + } + + DLGPlayerVideoFrame *f = nil; + const int width = context->width; + const int height = context->height; + if (_isYUV) { + DLGPlayerVideoYUVFrame *yuv = [[DLGPlayerVideoYUVFrame alloc] init]; + yuv.Y = [DLGPlayerDecoder dataFromVideoFrame:frame->data[0] + linesize:frame->linesize[0] + width:width + height:height]; + yuv.Cb = [DLGPlayerDecoder dataFromVideoFrame:frame->data[1] + linesize:frame->linesize[1] + width:width / 2 + height:height / 2]; + yuv.Cr = [DLGPlayerDecoder dataFromVideoFrame:frame->data[2] + linesize:frame->linesize[2] + width:width / 2 + height:height / 2]; + f = yuv; + } else { + sws_scale(swsctx, + (uint8_t const **)frame->data, + frame->linesize, + 0, + context->height, + swsframe->data, + swsframe->linesize); - [frames addObject:f]; - - ptsPrevVideo = frame->pts; - - } while(ret == 0); + DLGPlayerVideoRGBFrame *rgb = [[DLGPlayerVideoRGBFrame alloc] init]; + rgb.linesize = swsframe->linesize[0]; + rgb.data = [NSData dataWithBytes:swsframe->data[0] length:rgb.linesize * height]; + f = rgb; + } - return frames; - } + f.width = width; + f.height = height; + f.position = frame->best_effort_timestamp * _videoTimebase; + + double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevVideo; + + if (duration > 0) { + f.duration = duration * _videoTimebase / _speed; + f.duration += (frame->repeat_pict * _videoTimebase * 0.5) / _speed; + } else { + f.duration = 1 / _videoFPS / _speed; + } + + [frames addObject:f]; + + ptsPrevVideo = frame->pts; + + } while(ret == 0); + + return frames; } - (NSArray *)handleAudioPacket:(AVPacket *)packet byContext:(AVCodecContext *)context andFrame:(AVFrame *)frame andSwrContext:(SwrContext *)swrctx andSwrBuffer:(void **)swrbuf andSwrBufferSize:(int *)swrbufsize { @@ -570,117 +568,113 @@ - (NSArray *)readFrames { return nil; } - @autoreleasepool { - NSMutableArray *frames = [NSMutableArray array]; - do { - ret = avcodec_receive_frame(context, frame); - if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { - break; - } else if (ret < 0) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"avcodec_receive_frame: %d", ret); - } - break; + NSMutableArray *frames = [NSMutableArray array]; + do { + ret = avcodec_receive_frame(context, frame); + if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { + break; + } else if (ret < 0) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"avcodec_receive_frame: %d", ret); + } + break; + } + if (frame->data[0] == NULL) continue; + + const float sampleRate = _audioSampleRate; + const UInt32 channels = _audioChannels; + + void *data = NULL; + NSInteger samplesPerChannel = 0; + if (swrctx != NULL && swrbuf != NULL) { + float sampleRatio = sampleRate / context->sample_rate; + float channelRatio = channels / context->channels; + float ratio = MAX(1, sampleRatio) * MAX(1, channelRatio) * 2; + int samples = frame->nb_samples * ratio; + int bufsize = av_samples_get_buffer_size(NULL, + channels, + samples, + AV_SAMPLE_FMT_S16, + 1); + if (*swrbuf == NULL || *swrbufsize < bufsize) { + *swrbufsize = bufsize; + *swrbuf = realloc(*swrbuf, bufsize); } - if (frame->data[0] == NULL) continue; - - const float sampleRate = _audioSampleRate; - const UInt32 channels = _audioChannels; - void *data = NULL; - NSInteger samplesPerChannel = 0; - if (swrctx != NULL && swrbuf != NULL) { - float sampleRatio = sampleRate / context->sample_rate; - float channelRatio = channels / context->channels; - float ratio = MAX(1, sampleRatio) * MAX(1, channelRatio) * 2; - int samples = frame->nb_samples * ratio; - int bufsize = av_samples_get_buffer_size(NULL, - channels, - samples, - AV_SAMPLE_FMT_S16, - 1); - if (*swrbuf == NULL || *swrbufsize < bufsize) { - *swrbufsize = bufsize; - *swrbuf = realloc(*swrbuf, bufsize); - } - - Byte *o[2] = { *swrbuf, 0 }; - samplesPerChannel = swr_convert(swrctx, o, samples, (const uint8_t **)frame->data, frame->nb_samples); - if (samplesPerChannel < 0) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"failed to resample audio"); - } - return nil; - } - - data = *swrbuf; - } else { - if (context->sample_fmt != AV_SAMPLE_FMT_S16) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"invalid audio format"); - } - return nil; + Byte *o[2] = { *swrbuf, 0 }; + samplesPerChannel = swr_convert(swrctx, o, samples, (const uint8_t **)frame->data, frame->nb_samples); + if (samplesPerChannel < 0) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"failed to resample audio"); } - - data = frame->data[0]; - samplesPerChannel = frame->nb_samples; + return nil; } - NSUInteger elements = samplesPerChannel * channels; - NSUInteger dataLength = elements * sizeof(float); - NSMutableData *mdata = [NSMutableData dataWithLength:dataLength]; - - float scalar = 1.0f / INT16_MAX; - vDSP_vflt16(data, 1, mdata.mutableBytes, 1, elements); - vDSP_vsmul(mdata.mutableBytes, 1, &scalar, mdata.mutableBytes, 1, elements); - - DLGPlayerAudioFrame *f = [[DLGPlayerAudioFrame alloc] init]; - f.data = mdata; - f.position = frame->best_effort_timestamp * _audioTimebase; - - - double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevAudio; - - if (duration > 0) { - f.duration = duration * _audioTimebase / _speed; - } else { - f.duration = f.data.length / (sizeof(float) * channels * sampleRate) / _speed; + data = *swrbuf; + } else { + if (context->sample_fmt != AV_SAMPLE_FMT_S16) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"invalid audio format"); + } + return nil; } - ptsPrevAudio = frame->pts; - - [frames addObject:f]; - } while(ret == 0); + data = frame->data[0]; + samplesPerChannel = frame->nb_samples; + } - return frames; - } + NSUInteger elements = samplesPerChannel * channels; + NSUInteger dataLength = elements * sizeof(float); + NSMutableData *mdata = [NSMutableData dataWithLength:dataLength]; + + float scalar = 1.0f / INT16_MAX; + vDSP_vflt16(data, 1, mdata.mutableBytes, 1, elements); + vDSP_vsmul(mdata.mutableBytes, 1, &scalar, mdata.mutableBytes, 1, elements); + + DLGPlayerAudioFrame *f = [[DLGPlayerAudioFrame alloc] init]; + f.data = mdata; + f.position = frame->best_effort_timestamp * _audioTimebase; + + + double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevAudio; + + if (duration > 0) { + f.duration = duration * _audioTimebase / _speed; + } else { + f.duration = f.data.length / (sizeof(float) * channels * sampleRate) / _speed; + } + + ptsPrevAudio = frame->pts; + + [frames addObject:f]; + } while(ret == 0); + + return frames; } #pragma mark - Seek - (void)seek:(double)position { _isEOF = NO; - @autoreleasepool { - if (_hasVideo) { - NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; - int64_t ts = (int64_t)(position / _videoTimebase); - avformat_seek_file(m_pFormatContext, m_nVideoStream, ts, ts, ts, AVSEEK_FLAG_FRAME); - avcodec_flush_buffers(m_pVideoCodecContext); - NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate]; - NSTimeInterval dt = end - start; - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"seek video: %.4f, start: %.4f, end: %.4f", dt, start, end); - } - } else if (_hasAudio) { - NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; - int64_t ts = (int64_t)(position / _audioTimebase); - avformat_seek_file(m_pFormatContext, m_nAudioStream, ts, ts, ts, AVSEEK_FLAG_FRAME); - avcodec_flush_buffers(m_pAudioCodecContext); - NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate]; - NSTimeInterval dt = end - start; - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"seek audio: %.4f, start: %.4f, end: %.4f", dt, start, end); - } + if (_hasVideo) { + NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; + int64_t ts = (int64_t)(position / _videoTimebase); + avformat_seek_file(m_pFormatContext, m_nVideoStream, ts, ts, ts, AVSEEK_FLAG_FRAME); + avcodec_flush_buffers(m_pVideoCodecContext); + NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate]; + NSTimeInterval dt = end - start; + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"seek video: %.4f, start: %.4f, end: %.4f", dt, start, end); + } + } else if (_hasAudio) { + NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; + int64_t ts = (int64_t)(position / _audioTimebase); + avformat_seek_file(m_pFormatContext, m_nAudioStream, ts, ts, ts, AVSEEK_FLAG_FRAME); + avcodec_flush_buffers(m_pAudioCodecContext); + NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate]; + NSTimeInterval dt = end - start; + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"seek audio: %.4f, start: %.4f, end: %.4f", dt, start, end); } } } diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index 7e91686..f639e11 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -11,7 +11,7 @@ #define DLGPlayerLocalizedStringTable @"DLGPlayerStrings" -#define DLGPlayerFrameDropDuration 4 +#define DLGPlayerFrameDropDuration 3 #define DLGPlayerMinBufferDuration 1 #define DLGPlayerMaxBufferDuration 5 From 233827a4aa60a38a9d50eaf1151d3de36312d10a Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 19 May 2020 20:41:04 +0900 Subject: [PATCH 203/215] Fixed: solve crash and memory leaks. --- DLGPlayer/DLGPlayer.h | 7 +- DLGPlayer/DLGPlayer.m | 439 +++++++++++----------- DLGPlayer/DLGSimplePlayerViewController.m | 40 +- DLGPlayer/codec/DLGPlayerAudioManager.h | 2 +- DLGPlayer/codec/DLGPlayerAudioManager.m | 191 ++++++---- DLGPlayer/codec/DLGPlayerDecoder.m | 354 ++++++++--------- DLGPlayer/view/MetalPlayerView.m | 25 +- DLGPlayerDemo/RootViewController.swift | 5 +- 8 files changed, 564 insertions(+), 499 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index e037268..a3a04bf 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -26,9 +26,9 @@ typedef void (^onPauseComplete)(void); @property (readonly, strong) UIView *playerView; @property (nonatomic) BOOL allowsFrameDrop; @property (nonatomic) BOOL mute; -@property (atomic) BOOL playing; -@property (atomic) BOOL buffering; -@property (atomic) BOOL opened; +@property (nonatomic) BOOL playing; +@property (nonatomic) BOOL buffering; +@property (nonatomic) BOOL opened; @property (nonatomic) float brightness; @property (nonatomic) double frameDropDuration; @property (nonatomic) double minBufferDuration; @@ -41,6 +41,7 @@ typedef void (^onPauseComplete)(void); - (void)open:(NSString *)url; - (void)close; +- (void)closeAudio; - (void)play; - (void)pause; - (UIImage *)snapshot; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index f6580db..a01a9c5 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -20,27 +20,28 @@ @interface DLGPlayer () @property (nonatomic) BOOL notifiedBufferStart; @property (nonatomic) BOOL requestSeek; -@property (nonatomic) NSUInteger playingAudioFrameDataPosition; @property (nonatomic) double requestSeekPosition; +@property (nonatomic) NSUInteger playingAudioFrameDataPosition; @property (nonatomic, strong) NSMutableArray *vframes; @property (nonatomic, strong) NSMutableArray *aframes; +@property (nonatomic, strong) dispatch_queue_t frameReaderQueue; +@property (nonatomic, strong) dispatch_queue_t processingQueue; +@property (nonatomic, strong) dispatch_queue_t renderingQueue; @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; -@property (nonatomic, strong) dispatch_queue_t renderingQueue; @property (nonatomic, strong) DLGPlayerAudioFrame *playingAudioFrame; @property (nonatomic, strong) DLGPlayerDecoder *decoder; @property (nonatomic, strong) DLGPlayerAudioManager *audio; @property (nonatomic, strong) id view; -@property (nonatomic, strong) NSThread *frameReaderThread; - -@property (atomic) BOOL closing; -@property (atomic) BOOL opening; -@property (atomic) BOOL renderBegan; -@property (atomic) BOOL frameDropped; -@property (atomic) double bufferedDuration; -@property (atomic) double mediaPosition; -@property (atomic) double mediaSyncTime; -@property (atomic) double mediaSyncPosition; + +@property (nonatomic) BOOL closing; +@property (nonatomic) BOOL opening; +@property (nonatomic) BOOL renderBegan; +@property (nonatomic) BOOL frameDropped; +@property (nonatomic) double bufferedDuration; +@property (nonatomic) double mediaPosition; +@property (nonatomic) double mediaSyncTime; +@property (nonatomic) double mediaSyncPosition; @end @implementation DLGPlayer @@ -67,14 +68,14 @@ - (void)initAll { } - (void)initVars { + _allowsFrameDrop = NO; + _requestSeek = NO; + _renderBegan = NO; _frameDropDuration = DLGPlayerFrameDropDuration; _minBufferDuration = DLGPlayerMinBufferDuration; _maxBufferDuration = DLGPlayerMaxBufferDuration; _mediaSyncTime = 0; _brightness = 1; - _allowsFrameDrop = NO; - _requestSeek = NO; - _renderBegan = NO; _requestSeekPosition = 0; _speed = 1.0; @@ -93,14 +94,22 @@ - (void)initVars { _vFramesLock = dispatch_semaphore_create(1); _vframes = [NSMutableArray arrayWithCapacity:128]; _aframes = [NSMutableArray arrayWithCapacity:128]; - _renderingQueue = dispatch_queue_create([[NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash] UTF8String], DISPATCH_QUEUE_SERIAL); + + @autoreleasepool { + NSString *frameReaderQueueName = [NSString stringWithFormat:@"DLGPlayer.frameReaderQueue::%zd", self.hash]; + NSString *processingQueueName = [NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash]; + NSString *renderingQueueName = [NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash]; + _frameReaderQueue = dispatch_queue_create(frameReaderQueueName.UTF8String, DISPATCH_QUEUE_SERIAL); + _processingQueue = dispatch_queue_create(processingQueueName.UTF8String, DISPATCH_QUEUE_SERIAL); + _renderingQueue = dispatch_queue_create(renderingQueueName.UTF8String, DISPATCH_QUEUE_SERIAL); + } } - (void)initView { if (@available(iOS 9.0, *)) { - _view = [DLGPlayerUtils isMetalSupport] ? [MetalPlayerView new] : [DLGPlayerView new]; + _view = [DLGPlayerUtils isMetalSupport] ? [[MetalPlayerView alloc] init] : [[DLGPlayerView alloc] init]; } else { - _view = [DLGPlayerView new]; + _view = [[DLGPlayerView alloc] init]; } } @@ -125,213 +134,212 @@ - (void)clearVars { dispatch_semaphore_signal(self.aFramesLock); } - self.playingAudioFrame = nil; - self.playingAudioFrameDataPosition = 0; self.buffering = NO; - self.playing = NO; + self.closing = NO; + self.frameDropped = NO; self.opened = NO; + self.opening = NO; + self.playing = NO; self.renderBegan = NO; - self.mediaPosition = 0; self.bufferedDuration = 0; + self.mediaPosition = 0; self.mediaSyncTime = 0; - self.closing = NO; - self.opening = NO; - self.frameDropped = NO; + self.playingAudioFrameDataPosition = 0; + self.playingAudioFrame = nil; } - (void)open:(NSString *)url { __weak typeof(self)weakSelf = self; - - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + + dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - if (!strongSelf) { + + if (!strongSelf || strongSelf.opening || strongSelf.closing) { return; } - - NSError *error = nil; + strongSelf.opening = YES; - if ([strongSelf.audio open:&error]) { + if ([strongSelf.audio open:nil]) { strongSelf.decoder.audioChannels = [strongSelf.audio channels]; strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; - } else { - [strongSelf handleError:error]; - } - - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - [strongSelf handleError:error]; - return; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:self]; } - dispatch_async(dispatch_get_main_queue(), ^{ - if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { - DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; - [view setCurrentEAGLContext]; - } - - strongSelf.view.isYUV = [strongSelf.decoder isYUV]; - strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; - strongSelf.view.rotation = strongSelf.decoder.rotation; - strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); - if ([strongSelf.view isKindOfClass:[UIView class]]) { - ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; + dispatch_async(strongSelf.frameReaderQueue, ^{ + NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + [strongSelf handleError:error]; + return; } - strongSelf.duration = strongSelf.decoder.duration; - strongSelf.metadata = strongSelf.decoder.metadata; - strongSelf.opening = NO; - strongSelf.buffering = NO; - strongSelf.playing = NO; - strongSelf.bufferedDuration = 0; - strongSelf.mediaPosition = 0; - strongSelf.mediaSyncTime = 0; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - - strongSelf.opened = YES; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (!strongSelf || !strongSelf.opening || strongSelf.closing) { + return; + } + + if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { + DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; + [view setCurrentEAGLContext]; + } + + strongSelf.view.isYUV = [strongSelf.decoder isYUV]; + strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; + strongSelf.view.rotation = strongSelf.decoder.rotation; + strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); + + if ([strongSelf.view isKindOfClass:[UIView class]]) { + ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; + } + + strongSelf.duration = strongSelf.decoder.duration; + strongSelf.metadata = strongSelf.decoder.metadata; + strongSelf.opening = NO; + strongSelf.buffering = NO; + strongSelf.playing = NO; + strongSelf.bufferedDuration = 0; + strongSelf.mediaPosition = 0; + strongSelf.mediaSyncTime = 0; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + + strongSelf.opened = YES; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; + }); }); }); } - (void)close { - if (!self.opened && !self.opening) { - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:self]; - return; - } - - [self pause]; - [self.decoder prepareClose]; - - dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); - dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC); - __weak typeof(self)weakSelf = self; - - dispatch_source_set_event_handler(timer, ^{ + + dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - if (!strongSelf) { + + if (!strongSelf || strongSelf.closing || !strongSelf.opened) { return; } - - if (strongSelf.opening || strongSelf.buffering) return; - [strongSelf.decoder close]; - - NSArray *errors = nil; - if ([strongSelf.audio close:&errors]) { - [strongSelf clearVars]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:strongSelf]; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; - } else { - for (NSError *error in errors) { - [strongSelf handleError:error]; - } - } - dispatch_cancel(timer); + + strongSelf.closing = YES; + strongSelf.playing = NO; + + [strongSelf closeAudio]; + + dispatch_async(strongSelf.frameReaderQueue, ^{ + [strongSelf.decoder prepareClose]; + [strongSelf.decoder close]; + }); + + [strongSelf.view clear]; + [strongSelf clearVars]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; }); - dispatch_resume(timer); +} + +- (void)closeAudio { + if ([self.audio close:nil]) { + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:self]; + } } - (void)play { - - if (!self.opened || self.playing) return; - - self.playing = YES; __weak typeof(self)weakSelf = self; - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + + dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - if (!strongSelf) { + + if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { return; } + + strongSelf.playing = YES; - [strongSelf render]; - [strongSelf startFrameReaderThread]; + [strongSelf.audio play]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [strongSelf render]; + }); + + dispatch_async(strongSelf.frameReaderQueue, ^{ + [strongSelf runFrameReader]; + }); }); - - NSError *error = nil; - if (![self.audio play:&error]) { - [self handleError:error]; - } } - (void)pause { - self.playing = NO; - NSError *error = nil; - - if (![self.audio pause:&error]) { - [self handleError:error]; - } + __weak typeof(self)weakSelf = self; + + dispatch_async(self.processingQueue, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf.playing) { + strongSelf.playing = NO; + + [strongSelf.audio pause]; + } + }); } - (UIImage *)snapshot { return [_view snapshot]; } -- (void)startFrameReaderThread { - if (self.frameReaderThread == nil) { - self.frameReaderThread = [[NSThread alloc] initWithTarget:self selector:@selector(runFrameReader) object:nil]; - [self.frameReaderThread start]; - } -} - - (void)runFrameReader { - @autoreleasepool { - while (self.playing) { - [self readFrame]; - if (self.requestSeek) { - [self seekPositionInFrameReader]; - } else { - [NSThread sleepForTimeInterval:1.5]; - } + while (self.playing && !self.closing) { + [self readFrame]; + + if (self.requestSeek) { + [self seekPositionInFrameReader]; + } else { + [NSThread sleepForTimeInterval:1.5]; } - self.frameReaderThread = nil; } } - (void)readFrame { self.buffering = YES; - + + double tempDuration = 0; NSMutableArray *tempVFrames = [NSMutableArray arrayWithCapacity:8]; NSMutableArray *tempAFrames = [NSMutableArray arrayWithCapacity:8]; - double tempDuration = 0; dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek) { - @autoreleasepool { - // Drop frames - if (self.allowsFrameDrop && !self.frameDropped) { - if (self.bufferedDuration > self.frameDropDuration / self.speed) { - if (dispatch_semaphore_wait(self.vFramesLock, t) == 0) { - for (DLGPlayerFrame *f in self.vframes) { - f.dropFrame = YES; - } - dispatch_semaphore_signal(self.vFramesLock); - } - - if (dispatch_semaphore_wait(self.aFramesLock, t) == 0) { - for (DLGPlayerFrame *f in self.aframes) { - f.dropFrame = YES; - } - dispatch_semaphore_signal(self.aFramesLock); + // Drop frames + if (self.allowsFrameDrop && !self.frameDropped) { + if (self.bufferedDuration > self.frameDropDuration / self.speed) { + if (dispatch_semaphore_wait(self.vFramesLock, t) == 0) { + for (DLGPlayerFrame *f in self.vframes) { + f.dropFrame = YES; } - - self.frameDropped = YES; - - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); + dispatch_semaphore_signal(self.vFramesLock); + } + + if (dispatch_semaphore_wait(self.aFramesLock, t) == 0) { + for (DLGPlayerFrame *f in self.aframes) { + f.dropFrame = YES; } - continue; + dispatch_semaphore_signal(self.aFramesLock); + } + + self.frameDropped = YES; + + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); } - } else if (self.bufferedDuration > self.maxBufferDuration / self.speed) { continue; } - + } else if (self.bufferedDuration > self.maxBufferDuration / self.speed) { + continue; + } + + @autoreleasepool { NSArray *fs = [self.decoder readFrames]; if (fs == nil) { break; } @@ -526,11 +534,14 @@ - (void)renderView:(DLGPlayerVideoFrame *)frame { dispatch_sync(self.renderingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; + if (!strongSelf) { + return; + } + [strongSelf.view render:frame]; if (!strongSelf.renderBegan && frame.width > 0 && frame.height > 0) { strongSelf.renderBegan = YES; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationRenderBegan object:strongSelf]; } }); @@ -566,69 +577,67 @@ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)chan } while(frames > 0) { - @autoreleasepool { - if (self.playingAudioFrame == nil) { - { - if (self.aframes.count <= 0) { - memset(data, 0, frames * channels * sizeof(float)); - return; - } + if (self.playingAudioFrame == nil) { + { + if (self.aframes.count <= 0) { + memset(data, 0, frames * channels * sizeof(float)); + return; + } + + long timeout = dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW); + if (timeout == 0) { + DLGPlayerAudioFrame *frame = self.aframes[0]; - long timeout = dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW); - if (timeout == 0) { - DLGPlayerAudioFrame *frame = self.aframes[0]; + if (self.decoder.hasVideo) { + const double dt = self.mediaPosition - frame.position; - if (self.decoder.hasVideo) { - const double dt = self.mediaPosition - frame.position; - - if (dt < -0.1 && self.vframes.count > 0) { // audio is faster than video, silence - memset(data, 0, frames * channels * sizeof(float)); - dispatch_semaphore_signal(self.aFramesLock); - break; - } else if (dt > 0.1) { // audio is slower than video, skip - [self.aframes removeObjectAtIndex:0]; - dispatch_semaphore_signal(self.aFramesLock); - continue; - } else { - self.playingAudioFrameDataPosition = 0; - self.playingAudioFrame = frame; - [self.aframes removeObjectAtIndex:0]; - } + if (dt < -0.1 && self.vframes.count > 0) { // audio is faster than video, silence + memset(data, 0, frames * channels * sizeof(float)); + dispatch_semaphore_signal(self.aFramesLock); + break; + } else if (dt > 0.1) { // audio is slower than video, skip + [self.aframes removeObjectAtIndex:0]; + dispatch_semaphore_signal(self.aFramesLock); + continue; } else { self.playingAudioFrameDataPosition = 0; self.playingAudioFrame = frame; [self.aframes removeObjectAtIndex:0]; - self.mediaPosition = frame.position; - self.bufferedDuration -= frame.duration; } - dispatch_semaphore_signal(self.aFramesLock); - } else return; - } - } - - NSData *frameData = self.playingAudioFrame.data; - NSUInteger pos = self.playingAudioFrameDataPosition; - if (frameData == nil) { - memset(data, 0, frames * channels * sizeof(float)); - return; - } - - const void *bytes = (Byte *)frameData.bytes + pos; - const NSUInteger remainingBytes = frameData.length - pos; - const NSUInteger channelSize = channels * sizeof(float); - const NSUInteger bytesToCopy = MIN(frames * channelSize, remainingBytes); - const NSUInteger framesToCopy = bytesToCopy / channelSize; - - memcpy(data, bytes, bytesToCopy); - frames -= framesToCopy; - data += framesToCopy * channels; - - if (bytesToCopy < remainingBytes) { - self.playingAudioFrameDataPosition += bytesToCopy; - } else { - self.playingAudioFrame = nil; + } else { + self.playingAudioFrameDataPosition = 0; + self.playingAudioFrame = frame; + [self.aframes removeObjectAtIndex:0]; + self.mediaPosition = frame.position; + self.bufferedDuration -= frame.duration; + } + dispatch_semaphore_signal(self.aFramesLock); + } else return; } } + + NSData *frameData = self.playingAudioFrame.data; + NSUInteger pos = self.playingAudioFrameDataPosition; + if (frameData == nil) { + memset(data, 0, frames * channels * sizeof(float)); + return; + } + + const void *bytes = (Byte *)frameData.bytes + pos; + const NSUInteger remainingBytes = frameData.length - pos; + const NSUInteger channelSize = channels * sizeof(float); + const NSUInteger bytesToCopy = MIN(frames * channelSize, remainingBytes); + const NSUInteger framesToCopy = bytesToCopy / channelSize; + + memcpy(data, bytes, bytesToCopy); + frames -= framesToCopy; + data += framesToCopy * channels; + + if (bytesToCopy < remainingBytes) { + self.playingAudioFrameDataPosition += bytesToCopy; + } else { + self.playingAudioFrame = nil; + } } } diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index c4b2276..600738a 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -77,7 +77,10 @@ - (void)viewWillDisappear:(BOOL)animated { #pragma mark - getter/setter - (BOOL)hasUrl { - return _url != nil && [_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet].length > 0; + @autoreleasepool { + NSString *trimmed = [_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet]; + return _url != nil && trimmed.length > 0; + } } - (BOOL)isPlaying { @@ -154,7 +157,7 @@ - (void)open { } - (void)play { -// [UIApplication sharedApplication].idleTimerDisabled = self.preventFromScreenLock; + [UIApplication sharedApplication].idleTimerDisabled = self.preventFromScreenLock; [_player play]; self.status = DLGPlayerStatusPlaying; } @@ -165,14 +168,14 @@ - (void)replay { } - (void)pause { -// [UIApplication sharedApplication].idleTimerDisabled = NO; + [UIApplication sharedApplication].idleTimerDisabled = NO; [_player pause]; self.status = DLGPlayerStatusPaused; } - (void)stop { self.status = DLGPlayerStatusClosing; -// [UIApplication sharedApplication].idleTimerDisabled = NO; + [UIApplication sharedApplication].idleTimerDisabled = NO; [_player close]; } @@ -181,21 +184,22 @@ - (void)stop { - (void)addPlayerView { UIView *v = _player.playerView; v.translatesAutoresizingMaskIntoConstraints = NO; - + [self.view addSubview:v]; - - // Add constraints - NSDictionary *views = NSDictionaryOfVariableBindings(v); - NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" - options:0 - metrics:nil - views:views]; - [self.view addConstraints:ch]; - NSArray *cv = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" - options:0 - metrics:nil - views:views]; - [self.view addConstraints:cv]; + + @autoreleasepool { + NSDictionary *views = NSDictionaryOfVariableBindings(v); + NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:ch]; + NSArray *cv = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:cv]; + } } #pragma mark - Notifications diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.h b/DLGPlayer/codec/DLGPlayerAudioManager.h index 137b182..8744dd8 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.h +++ b/DLGPlayer/codec/DLGPlayerAudioManager.h @@ -13,8 +13,8 @@ typedef void(^DLGPlayerAudioManagerFrameReaderBlock)(float *data, UInt32 num, UI @interface DLGPlayerAudioManager : NSObject @property (nonatomic) BOOL mute; -@property (nonatomic, copy) DLGPlayerAudioManagerFrameReaderBlock frameReaderBlock; @property (nonatomic) float volume; +@property (nonatomic, copy) DLGPlayerAudioManagerFrameReaderBlock frameReaderBlock; @property (nonatomic) NSTimeInterval bufferDuration; - (BOOL)open:(NSError **)error; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 1d4976a..057df04 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -19,7 +19,7 @@ #define PREFERRED_SAMPLE_RATE 44100 #define PREFERRED_BUFFER_DURATION 0.023 -static OSStatus audioUnitRenderCallback(void *inRefCon, +OSStatus audioUnitRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, @@ -33,15 +33,14 @@ @interface DLGPlayerAudioManager () { BOOL _shouldPlayAfterInterruption; BOOL _playing; double _sampleRate; + float *_audioData; UInt32 _bitsPerChannel; UInt32 _channelsPerFrame; - float *_audioData; AudioUnit _audioUnit; } @end @implementation DLGPlayerAudioManager -@synthesize mute = _mute; - (id)init { self = [super init]; @@ -52,16 +51,16 @@ - (id)init { } - (void)initVars { - self.mute = NO; + _closing = NO; + _mute = NO; _registeredKVO = NO; _opened = NO; - _closing = NO; _shouldPlayAfterInterruption = NO; _playing = NO; - _sampleRate = 0; _bitsPerChannel = 0; - _channelsPerFrame = 0; _bufferDuration = 1; + _channelsPerFrame = 0; + _sampleRate = 0; _audioUnit = NULL; _audioData = (float *)calloc(MAX_FRAME_SIZE * MAX_CHANNEL, sizeof(float)); _frameReaderBlock = nil; @@ -71,6 +70,7 @@ - (void)dealloc { if (DLGPlayerUtils.debugEnabled) { NSLog(@"DLGPlayerAudioManager dealloc"); } + [self unregisterNotifications]; if (_audioData) { @@ -83,10 +83,13 @@ - (void)dealloc { * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ - (BOOL)open:(NSError **)error { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"[Audio] %zd -> opening", self.hash); + } NSError *rawError = nil; AVAudioSession *session = [AVAudioSession sharedInstance]; AVAudioSessionCategory category = self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategoryPlayback; - + if (![session setCategory:category error:&rawError]) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager @@ -95,20 +98,20 @@ - (BOOL)open:(NSError **)error { andRawError:rawError]; return NO; } - + if (![session setPreferredIOBufferDuration:_bufferDuration error:&rawError]) { if (DLGPlayerUtils.debugEnabled) { NSLog(@"setPreferredIOBufferDuration: %.4f, error: %@", _bufferDuration, rawError); } } - + double prefferedSampleRate = PREFERRED_SAMPLE_RATE; if (![session setPreferredSampleRate:prefferedSampleRate error:&rawError]) { if (DLGPlayerUtils.debugEnabled) { NSLog(@"setPreferredSampleRate: %.4f, error: %@", prefferedSampleRate, rawError); } } - + if (![session setActive:YES error:&rawError]) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager @@ -117,7 +120,7 @@ - (BOOL)open:(NSError **)error { andRawError:rawError]; return NO; } - + AVAudioSessionRouteDescription *currentRoute = session.currentRoute; if (currentRoute.outputs.count == 0) { [DLGPlayerUtils createError:error @@ -126,7 +129,7 @@ - (BOOL)open:(NSError **)error { andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_OUTPUT"]]; return NO; } - + NSInteger channels = session.outputNumberOfChannels; if (channels <= 0) { [DLGPlayerUtils createError:error @@ -135,7 +138,7 @@ - (BOOL)open:(NSError **)error { andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_CHANNEL"]]; return NO; } - + double sampleRate = session.sampleRate; if (sampleRate <= 0) { [DLGPlayerUtils createError:error @@ -144,7 +147,7 @@ - (BOOL)open:(NSError **)error { andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_SAMPLE_RATE"]]; return NO; } - + float volume = session.outputVolume; if (volume < 0) { [DLGPlayerUtils createError:error @@ -153,17 +156,21 @@ - (BOOL)open:(NSError **)error { andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_NO_AUDIO_VOLUME"]]; return NO; } - + if (![self initAudioUnitWithSampleRate:sampleRate andRenderCallback:audioUnitRenderCallback error:error]) { return NO; } [self registerNotifications]; - + _sampleRate = sampleRate; _volume = volume; _opened = YES; + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"[Audio] %zd -> opened", self.hash); + } + return YES; } @@ -187,7 +194,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend andRawError:rawError]; return NO; } - + AudioStreamBasicDescription streamDescr = {0}; UInt32 size = sizeof(AudioStreamBasicDescription); status = AudioUnitGetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, &size); @@ -200,20 +207,20 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend andRawError:rawError]; return NO; } - + streamDescr.mSampleRate = sampleRate; status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamDescr, size); if (DLGPlayerUtils.debugEnabled && status != noErr) { NSLog(@"FAILED to set audio sample rate: %f, error: %d", sampleRate, (int)status); } - + _bitsPerChannel = streamDescr.mBitsPerChannel; _channelsPerFrame = streamDescr.mChannelsPerFrame; - + AURenderCallbackStruct renderCallbackStruct; renderCallbackStruct.inputProc = renderCallback; renderCallbackStruct.inputProcRefCon = (__bridge void *)(self); - + status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &renderCallbackStruct, sizeof(AURenderCallbackStruct)); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -224,7 +231,7 @@ - (BOOL)initAudioUnitWithSampleRate:(double)sampleRate andRenderCallback:(AURend andRawError:rawError]; return NO; } - + status = AudioUnitInitialize(audioUnit); if (status != noErr) { NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; @@ -246,71 +253,74 @@ - (BOOL)close { } - (BOOL)close:(NSArray **)errors { - if (_closing) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"[Audio] %zd -> closing: %d", self.hash, _closing); + } + if (!_opened || _closing) { return NO; } - _closing = YES; - NSMutableArray *errs = nil; if (errors != nil) errs = [NSMutableArray array]; + _closing = YES; + BOOL closed = YES; - if (_opened) { - [self pause]; - [self unregisterNotifications]; - - OSStatus status = AudioUnitUninitialize(_audioUnit); - if (status != noErr) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotUninitAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT"] - andRawError:rawError]; - [errs addObject:error]; - } + [self pause]; + [self unregisterNotifications]; + + OSStatus status = AudioUnitUninitialize(_audioUnit); + if (status != noErr) { + closed = NO; + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotUninitAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_UNINIT_AUDIO_UNIT"] + andRawError:rawError]; + [errs addObject:error]; } - - status = AudioComponentInstanceDispose(_audioUnit); - if (status != noErr) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotDisposeAudioUnit - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT"] - andRawError:rawError]; - [errs addObject:error]; - } + } + + status = AudioComponentInstanceDispose(_audioUnit); + if (status != noErr) { + closed = NO; + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotDisposeAudioUnit + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DISPOSE_AUDIO_UNIT"] + andRawError:rawError]; + [errs addObject:error]; } - - AVAudioSession *session = [AVAudioSession sharedInstance]; - NSError *error = nil; + } - if (![session setActive:NO error:&error]) { - closed = NO; - if (errs != nil) { - NSError *error = nil; - NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; - [DLGPlayerUtils createError:&error - withDomain:DLGPlayerErrorDomainAudioManager - andCode:DLGPlayerErrorCodeCannotDeactivateAudio - andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] - andRawError:rawError]; - [errs addObject:error]; - } + AVAudioSession *session = [AVAudioSession sharedInstance]; + NSError *error = nil; + + if (![session setActive:NO error:&error]) { + if (errs != nil) { + NSError *error = nil; + NSError *rawError = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil]; + [DLGPlayerUtils createError:&error + withDomain:DLGPlayerErrorDomainAudioManager + andCode:DLGPlayerErrorCodeCannotDeactivateAudio + andMessage:[DLGPlayerUtils localizedString:@"DLG_PLAYER_STRINGS_CANNOT_DEACTIVATE_AUDIO"] + andRawError:rawError]; + [errs addObject:error]; } + } + + if (closed) { + [self clear]; - if (closed) { - _opened = NO; - _audioUnit = NULL; + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"[Audio] %zd -> closed", self.hash); } } @@ -329,6 +339,9 @@ - (BOOL)play:(NSError **)error { } if (_opened) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"[Audio] %zd -> play", self.hash); + } OSStatus status = AudioOutputUnitStart(_audioUnit); _playing = (status == noErr); if (!_playing) { @@ -353,6 +366,9 @@ - (BOOL)pause:(NSError **)error { } if (_playing) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"[Audio] %zd -> pause", self.hash); + } OSStatus status = AudioOutputUnitStop(_audioUnit); _playing = !(status == noErr); if (_playing) { @@ -367,6 +383,13 @@ - (BOOL)pause:(NSError **)error { return !_playing; } +- (void)clear { + _opened = NO; + _closing = NO; + _playing = NO; + _audioUnit = NULL; +} + - (OSStatus)render:(AudioBufferList *)ioData count:(UInt32)inNumberFrames { UInt32 num = ioData->mNumberBuffers; for (UInt32 i = 0; i < num; ++i) { @@ -421,6 +444,14 @@ - (void)registerNotifications { selector:@selector(notifyAudioSessionInterruptionNotification:) name:AVAudioSessionInterruptionNotification object:nil]; + [nc addObserver:self + selector:@selector(notifyAudioSessionMediaServicesWereLostNotification:) + name:AVAudioSessionMediaServicesWereLostNotification + object:nil]; + [nc addObserver:self + selector:@selector(notifyAudioSessionMediaServicesWereResetNotification:) + name:AVAudioSessionMediaServicesWereResetNotification + object:nil]; if (!_registeredKVO) { AVAudioSession *session = [AVAudioSession sharedInstance]; @@ -463,6 +494,14 @@ - (void)notifyAudioSessionInterruptionNotification:(NSNotification *)notif { } } +- (void)notifyAudioSessionMediaServicesWereLostNotification:(NSNotification *)notif { + [self clear]; +} + +- (void)notifyAudioSessionMediaServicesWereResetNotification:(NSNotification *)notif { + [self clear]; +} + - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { AVAudioSession *session = [AVAudioSession sharedInstance]; if (object == session && [keyPath isEqualToString:@"outputVolume"]) { @@ -472,7 +511,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N @end -static OSStatus audioUnitRenderCallback(void *inRefCon, +OSStatus audioUnitRenderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index cbd195f..e351128 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -226,10 +226,12 @@ - (NSDictionary *)findMetadata:(AVFormatContext *)fmtctx { AVDictionary *metadata = fmtctx->metadata; AVDictionaryEntry *entry = av_dict_get(metadata, "", NULL, AV_DICT_IGNORE_SUFFIX); while (entry != NULL) { - NSString *key = [NSString stringWithCString:entry->key encoding:NSUTF8StringEncoding]; - NSString *value = [NSString stringWithCString:entry->value encoding:NSUTF8StringEncoding]; - if (key != nil && value != nil) md[key] = value; - entry = av_dict_get(metadata, "", entry, AV_DICT_IGNORE_SUFFIX); + @autoreleasepool { + NSString *key = [NSString stringWithCString:entry->key encoding:NSUTF8StringEncoding]; + NSString *value = [NSString stringWithCString:entry->value encoding:NSUTF8StringEncoding]; + if (key != nil && value != nil) md[key] = value; + entry = av_dict_get(metadata, "", entry, AV_DICT_IGNORE_SUFFIX); + } } return md; @@ -242,11 +244,13 @@ - (int)findVideoStream:(AVFormatContext *)fmtctx context:(AVCodecContext **)cont if (fmtctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { int disposition = fmtctx->streams[i]->disposition; if ((disposition & AV_DISPOSITION_ATTACHED_PIC) == 0) { // Not attached picture - AVCodecContext *codectx = [self openVideoCodec:fmtctx stream:i]; - if (codectx != NULL) { - if (context != NULL) *context = codectx; - stream = i; - break; + @autoreleasepool { + AVCodecContext *codectx = [self openVideoCodec:fmtctx stream:i]; + if (codectx != NULL) { + if (context != NULL) *context = codectx; + stream = i; + break; + } } } else { if (pictureStream != NULL) *pictureStream = i; @@ -284,11 +288,13 @@ - (int)findAudioStream:(AVFormatContext *)fmtctx context:(AVCodecContext **)cont int stream = -1; for (int i = 0; i < fmtctx->nb_streams; ++i) { if (fmtctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - AVCodecContext *codectx = [self openAudioCodec:fmtctx stream:i]; - if (codectx != NULL) { - if (context != NULL) *context = codectx; - stream = i; - break; + @autoreleasepool { + AVCodecContext *codectx = [self openAudioCodec:fmtctx stream:i]; + if (codectx != NULL) { + if (context != NULL) *context = codectx; + stream = i; + break; + } } } } @@ -392,44 +398,46 @@ - (NSArray *)readFrames { BOOL reading = YES; while (reading) { - g_dIOStartTime = [NSDate timeIntervalSinceReferenceDate]; - int ret = av_read_frame(fmtctx, &packet); - if (ret < 0) { - if (ret == AVERROR_EOF) self.isEOF = YES; - char *e = av_err2str(ret); - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer read frame error: %s", e); + @autoreleasepool { + g_dIOStartTime = [NSDate timeIntervalSinceReferenceDate]; + int ret = av_read_frame(fmtctx, &packet); + if (ret < 0) { + if (ret == AVERROR_EOF) self.isEOF = YES; + char *e = av_err2str(ret); + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"DLGPlayer read frame error: %s", e); + } + break; } - break; - } - - /* - * https://ffmpeg.org/doxygen/3.1/group__lavc__encdec.html - */ - NSArray *fs = nil; - - if (packet.stream_index == vstream) { - fs = [self handleVideoPacket:&packet byContext:vcodectx andFrame:vframe andSwsContext:swsctx andSwsFrame:vswsframe]; - reading = NO; - } else if (packet.stream_index == astream) { - fs = [self handleAudioPacket:&packet byContext:acodectx andFrame:aframe andSwrContext:swrctx andSwrBuffer:swrbuf andSwrBufferSize:swrbufsize]; - if (!_hasVideo) { + /* + * https://ffmpeg.org/doxygen/3.1/group__lavc__encdec.html + */ + NSArray *fs = nil; + + if (packet.stream_index == vstream) { + fs = [self handleVideoPacket:&packet byContext:vcodectx andFrame:vframe andSwsContext:swsctx andSwsFrame:vswsframe]; reading = NO; + } else if (packet.stream_index == astream) { + fs = [self handleAudioPacket:&packet byContext:acodectx andFrame:aframe andSwrContext:swrctx andSwrBuffer:swrbuf andSwrBufferSize:swrbufsize]; + + if (!_hasVideo) { + reading = NO; + } + } else if (packet.stream_index == picstream) { + fs = [self handlePicturePacket:&packet]; + + if (!_hasVideo && !_hasAudio) { + reading = NO; + } } - } else if (packet.stream_index == picstream) { - fs = [self handlePicturePacket:&packet]; - if (!_hasVideo && !_hasAudio) { - reading = NO; + if (fs != nil && fs.count > 0) { + [frames addObjectsFromArray:fs]; } + + av_packet_unref(&packet); } - - if (fs != nil && fs.count > 0) { - [frames addObjectsFromArray:fs]; - } - - av_packet_unref(&packet); } return frames; @@ -487,73 +495,75 @@ - (NSArray *)readFrames { int ret = avcodec_send_packet(context, packet); if (ret != 0) { if (DLGPlayerUtils.debugEnabled) { - NSLog(@"avcodec_send_packet: %d, size: %d", ret); + NSLog(@"avcodec_send_packet: %d", ret); } return nil; } NSMutableArray *frames = [NSMutableArray array]; do { - ret = avcodec_receive_frame(context, frame); - if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { - break; - } else if (ret < 0) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"avcodec_receive_frame: %d", ret); + @autoreleasepool { + ret = avcodec_receive_frame(context, frame); + if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { + break; + } else if (ret < 0) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"avcodec_receive_frame: %d", ret); + } + break; + } + + DLGPlayerVideoFrame *f = nil; + const int width = context->width; + const int height = context->height; + if (_isYUV) { + DLGPlayerVideoYUVFrame *yuv = [[DLGPlayerVideoYUVFrame alloc] init]; + yuv.Y = [DLGPlayerDecoder dataFromVideoFrame:frame->data[0] + linesize:frame->linesize[0] + width:width + height:height]; + yuv.Cb = [DLGPlayerDecoder dataFromVideoFrame:frame->data[1] + linesize:frame->linesize[1] + width:width / 2 + height:height / 2]; + yuv.Cr = [DLGPlayerDecoder dataFromVideoFrame:frame->data[2] + linesize:frame->linesize[2] + width:width / 2 + height:height / 2]; + f = yuv; + } else { + sws_scale(swsctx, + (uint8_t const **)frame->data, + frame->linesize, + 0, + context->height, + swsframe->data, + swsframe->linesize); + + DLGPlayerVideoRGBFrame *rgb = [[DLGPlayerVideoRGBFrame alloc] init]; + rgb.linesize = swsframe->linesize[0]; + rgb.data = [NSData dataWithBytes:swsframe->data[0] length:rgb.linesize * height]; + f = rgb; } - break; - } - - DLGPlayerVideoFrame *f = nil; - const int width = context->width; - const int height = context->height; - if (_isYUV) { - DLGPlayerVideoYUVFrame *yuv = [[DLGPlayerVideoYUVFrame alloc] init]; - yuv.Y = [DLGPlayerDecoder dataFromVideoFrame:frame->data[0] - linesize:frame->linesize[0] - width:width - height:height]; - yuv.Cb = [DLGPlayerDecoder dataFromVideoFrame:frame->data[1] - linesize:frame->linesize[1] - width:width / 2 - height:height / 2]; - yuv.Cr = [DLGPlayerDecoder dataFromVideoFrame:frame->data[2] - linesize:frame->linesize[2] - width:width / 2 - height:height / 2]; - f = yuv; - } else { - sws_scale(swsctx, - (uint8_t const **)frame->data, - frame->linesize, - 0, - context->height, - swsframe->data, - swsframe->linesize); - DLGPlayerVideoRGBFrame *rgb = [[DLGPlayerVideoRGBFrame alloc] init]; - rgb.linesize = swsframe->linesize[0]; - rgb.data = [NSData dataWithBytes:swsframe->data[0] length:rgb.linesize * height]; - f = rgb; - } - - f.width = width; - f.height = height; - f.position = frame->best_effort_timestamp * _videoTimebase; - - double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevVideo; - - if (duration > 0) { - f.duration = duration * _videoTimebase / _speed; - f.duration += (frame->repeat_pict * _videoTimebase * 0.5) / _speed; - } else { - f.duration = 1 / _videoFPS / _speed; + f.width = width; + f.height = height; + f.position = frame->best_effort_timestamp * _videoTimebase; + + double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevVideo; + + if (duration > 0) { + f.duration = duration * _videoTimebase / _speed; + f.duration += (frame->repeat_pict * _videoTimebase * 0.5) / _speed; + } else { + f.duration = 1 / _videoFPS / _speed; + } + + [frames addObject:f]; + + ptsPrevVideo = frame->pts; } - [frames addObject:f]; - - ptsPrevVideo = frame->pts; - } while(ret == 0); return frames; @@ -570,83 +580,85 @@ - (NSArray *)readFrames { NSMutableArray *frames = [NSMutableArray array]; do { - ret = avcodec_receive_frame(context, frame); - if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { - break; - } else if (ret < 0) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"avcodec_receive_frame: %d", ret); - } - break; - } - if (frame->data[0] == NULL) continue; - - const float sampleRate = _audioSampleRate; - const UInt32 channels = _audioChannels; - - void *data = NULL; - NSInteger samplesPerChannel = 0; - if (swrctx != NULL && swrbuf != NULL) { - float sampleRatio = sampleRate / context->sample_rate; - float channelRatio = channels / context->channels; - float ratio = MAX(1, sampleRatio) * MAX(1, channelRatio) * 2; - int samples = frame->nb_samples * ratio; - int bufsize = av_samples_get_buffer_size(NULL, - channels, - samples, - AV_SAMPLE_FMT_S16, - 1); - if (*swrbuf == NULL || *swrbufsize < bufsize) { - *swrbufsize = bufsize; - *swrbuf = realloc(*swrbuf, bufsize); - } - - Byte *o[2] = { *swrbuf, 0 }; - samplesPerChannel = swr_convert(swrctx, o, samples, (const uint8_t **)frame->data, frame->nb_samples); - if (samplesPerChannel < 0) { + @autoreleasepool { + ret = avcodec_receive_frame(context, frame); + if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { + break; + } else if (ret < 0) { if (DLGPlayerUtils.debugEnabled) { - NSLog(@"failed to resample audio"); + NSLog(@"avcodec_receive_frame: %d", ret); } - return nil; + break; } + if (frame->data[0] == NULL) continue; - data = *swrbuf; - } else { - if (context->sample_fmt != AV_SAMPLE_FMT_S16) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"invalid audio format"); + const float sampleRate = _audioSampleRate; + const UInt32 channels = _audioChannels; + + void *data = NULL; + NSInteger samplesPerChannel = 0; + if (swrctx != NULL && swrbuf != NULL) { + float sampleRatio = sampleRate / context->sample_rate; + float channelRatio = channels / context->channels; + float ratio = MAX(1, sampleRatio) * MAX(1, channelRatio) * 2; + int samples = frame->nb_samples * ratio; + int bufsize = av_samples_get_buffer_size(NULL, + channels, + samples, + AV_SAMPLE_FMT_S16, + 1); + if (*swrbuf == NULL || *swrbufsize < bufsize) { + *swrbufsize = bufsize; + *swrbuf = realloc(*swrbuf, bufsize); } - return nil; + + Byte *o[2] = { *swrbuf, 0 }; + samplesPerChannel = swr_convert(swrctx, o, samples, (const uint8_t **)frame->data, frame->nb_samples); + if (samplesPerChannel < 0) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"failed to resample audio"); + } + return nil; + } + + data = *swrbuf; + } else { + if (context->sample_fmt != AV_SAMPLE_FMT_S16) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"invalid audio format"); + } + return nil; + } + + data = frame->data[0]; + samplesPerChannel = frame->nb_samples; } - data = frame->data[0]; - samplesPerChannel = frame->nb_samples; - } - - NSUInteger elements = samplesPerChannel * channels; - NSUInteger dataLength = elements * sizeof(float); - NSMutableData *mdata = [NSMutableData dataWithLength:dataLength]; - - float scalar = 1.0f / INT16_MAX; - vDSP_vflt16(data, 1, mdata.mutableBytes, 1, elements); - vDSP_vsmul(mdata.mutableBytes, 1, &scalar, mdata.mutableBytes, 1, elements); - - DLGPlayerAudioFrame *f = [[DLGPlayerAudioFrame alloc] init]; - f.data = mdata; - f.position = frame->best_effort_timestamp * _audioTimebase; - - - double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevAudio; - - if (duration > 0) { - f.duration = duration * _audioTimebase / _speed; - } else { - f.duration = f.data.length / (sizeof(float) * channels * sampleRate) / _speed; + NSUInteger elements = samplesPerChannel * channels; + NSUInteger dataLength = elements * sizeof(float); + NSMutableData *mdata = [NSMutableData dataWithLength:dataLength]; + + float scalar = 1.0f / INT16_MAX; + vDSP_vflt16(data, 1, mdata.mutableBytes, 1, elements); + vDSP_vsmul(mdata.mutableBytes, 1, &scalar, mdata.mutableBytes, 1, elements); + + DLGPlayerAudioFrame *f = [[DLGPlayerAudioFrame alloc] init]; + f.data = mdata; + f.position = frame->best_effort_timestamp * _audioTimebase; + + + double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevAudio; + + if (duration > 0) { + f.duration = duration * _audioTimebase / _speed; + } else { + f.duration = f.data.length / (sizeof(float) * channels * sampleRate) / _speed; + } + + ptsPrevAudio = frame->pts; + + [frames addObject:f]; } - - ptsPrevAudio = frame->pts; - - [frames addObject:f]; } while(ret == 0); return frames; diff --git a/DLGPlayer/view/MetalPlayerView.m b/DLGPlayer/view/MetalPlayerView.m index d52c416..2bed36d 100644 --- a/DLGPlayer/view/MetalPlayerView.m +++ b/DLGPlayer/view/MetalPlayerView.m @@ -70,8 +70,9 @@ - (void)layoutSubviews { #pragma mark - Private Methods - (void)setUpPipelineState { + NSString *name = _isYUV ? @"YUVColorConversion" : @"RGBColorConversion"; + @autoreleasepool { - NSString *name = _isYUV ? @"YUVColorConversion" : @"RGBColorConversion"; id kernelFunction = [defaultLibrary newFunctionWithName:name]; if (!kernelFunction && DLGPlayerUtils.debugEnabled) { @@ -124,7 +125,7 @@ - (void)drawInMTKView:(nonnull MTKView *)view { #endif - (void)initProperties { - metalView = [MTKView new]; + metalView = [[MTKView alloc] init]; metalView.autoResizeDrawable = NO; metalView.framebufferOnly = NO; metalView.contentScaleFactor = UIScreen.mainScreen.scale; @@ -205,17 +206,15 @@ - (UIImage *)snapshot { return nil; } - @autoreleasepool { - const id texture = metalView.currentDrawable.texture; - const NSInteger w = texture.width; - const NSInteger h = texture.height; - CIContext *context = [CIContext contextWithMTLDevice:metalView.device]; - CIImage *outputImage = [[CIImage alloc] initWithMTLTexture:texture options:@{kCIImageColorSpace: (__bridge_transfer id) CGColorSpaceCreateDeviceRGB()}]; - CGImageRef cgImg = [context createCGImage:outputImage fromRect:CGRectMake(0, 0, w, h)]; - UIImage *resultImg = [UIImage imageWithCGImage:cgImg scale:UIScreen.mainScreen.scale orientation:UIImageOrientationDownMirrored]; - CGImageRelease(cgImg); - return resultImg; - } + const id texture = metalView.currentDrawable.texture; + const NSInteger w = texture.width; + const NSInteger h = texture.height; + CIContext *context = [CIContext contextWithMTLDevice:metalView.device]; + CIImage *outputImage = [[CIImage alloc] initWithMTLTexture:texture options:@{kCIImageColorSpace: (__bridge_transfer id) CGColorSpaceCreateDeviceRGB()}]; + CGImageRef cgImg = [context createCGImage:outputImage fromRect:CGRectMake(0, 0, w, h)]; + UIImage *resultImg = [UIImage imageWithCGImage:cgImg scale:UIScreen.mainScreen.scale orientation:UIImageOrientationDownMirrored]; + CGImageRelease(cgImg); + return resultImg; #endif } diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index a42f6de..4f004f6 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -137,8 +137,9 @@ final class RootViewController: UIViewController { } if isPlaying { - vc.stop() + vc.player.closeAudio() } else { + vc.stop() vc.url = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" vc.open() } @@ -146,7 +147,7 @@ final class RootViewController: UIViewController { isPlaying = !isPlaying if #available(iOS 10.0, *) { - Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { [weak self] _ in + Timer.scheduledTimer(withTimeInterval: 1.5, repeats: true) { [weak self] _ in self?.stopButtonClicked() } } else { From ab1cce3e14f6ee53175657dfe226b2610f208b6a Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 20 May 2020 14:58:20 +0900 Subject: [PATCH 204/215] Updated: performance improvement. --- DLGPlayer/DLGPlayer.h | 1 + DLGPlayer/DLGPlayer.m | 318 ++++++++++++---------- DLGPlayer/DLGSimplePlayerViewController.h | 1 + DLGPlayer/DLGSimplePlayerViewController.m | 7 +- DLGPlayer/codec/DLGPlayerAudioManager.h | 1 + DLGPlayer/codec/DLGPlayerAudioManager.m | 2 +- DLGPlayerDemo/RootViewController.swift | 2 +- 7 files changed, 178 insertions(+), 154 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index a3a04bf..9609a7d 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -42,6 +42,7 @@ typedef void (^onPauseComplete)(void); - (void)open:(NSString *)url; - (void)close; - (void)closeAudio; +- (void)closeCompletely; - (void)play; - (void)pause; - (UIImage *)snapshot; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index a01a9c5..a961f3d 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -18,8 +18,16 @@ #import "MetalPlayerView.h" @interface DLGPlayer () +@property (nonatomic) BOOL closing; +@property (nonatomic) BOOL opening; +@property (nonatomic) BOOL frameDropped; @property (nonatomic) BOOL notifiedBufferStart; +@property (nonatomic) BOOL renderBegan; @property (nonatomic) BOOL requestSeek; +@property (nonatomic) double bufferedDuration; +@property (nonatomic) double mediaPosition; +@property (nonatomic) double mediaSyncPosition; +@property (nonatomic) double mediaSyncTime; @property (nonatomic) double requestSeekPosition; @property (nonatomic) NSUInteger playingAudioFrameDataPosition; @property (nonatomic, strong) NSMutableArray *vframes; @@ -33,19 +41,37 @@ @interface DLGPlayer () @property (nonatomic, strong) DLGPlayerDecoder *decoder; @property (nonatomic, strong) DLGPlayerAudioManager *audio; @property (nonatomic, strong) id view; - -@property (nonatomic) BOOL closing; -@property (nonatomic) BOOL opening; -@property (nonatomic) BOOL renderBegan; -@property (nonatomic) BOOL frameDropped; -@property (nonatomic) double bufferedDuration; -@property (nonatomic) double mediaPosition; -@property (nonatomic) double mediaSyncTime; -@property (nonatomic) double mediaSyncPosition; @end @implementation DLGPlayer +#pragma mark - Public Properties + +- (UIView *)playerView { + return (UIView *) _view; +} + +- (void)setPosition:(double)position { + self.requestSeekPosition = position; + self.requestSeek = YES; +} + +- (double)position { + return self.mediaPosition; +} + +- (void)setSpeed:(double)speed { + _speed = speed; + self.decoder.speed = speed; +} + +- (void)setMute:(BOOL)mute { + _mute = mute; + self.audio.mute = mute; +} + +#pragma mark - Con(De)structors + - (id)init { self = [super init]; if (self) { @@ -60,6 +86,131 @@ - (void)dealloc { } } +#pragma mark - Public Methods + +- (void)open:(NSString *)url { + __weak typeof(self)weakSelf = self; + + dispatch_async(self.processingQueue, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (!strongSelf || strongSelf.opening || strongSelf.closing) { + return; + } + + strongSelf.opening = YES; + + if (!strongSelf.audio.opened && [strongSelf.audio open:nil]) { + strongSelf.decoder.audioChannels = [strongSelf.audio channels]; + strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:self]; + } + + NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + [strongSelf handleError:error]; + return; + } + + strongSelf.duration = strongSelf.decoder.duration; + strongSelf.metadata = strongSelf.decoder.metadata; + strongSelf.opening = NO; + strongSelf.buffering = NO; + strongSelf.playing = NO; + strongSelf.bufferedDuration = 0; + strongSelf.mediaPosition = 0; + strongSelf.mediaSyncTime = 0; + strongSelf.view.isYUV = [strongSelf.decoder isYUV]; + strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; + strongSelf.view.rotation = strongSelf.decoder.rotation; + strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + + dispatch_async(dispatch_get_main_queue(), ^{ + if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { + DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; + [view setCurrentEAGLContext]; + } + + strongSelf.opened = YES; + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; + }); + }); +} + +- (void)close { + [self close:NO]; +} + +- (void)closeAudio { + __weak typeof(self)weakSelf = self; + + dispatch_async(self.processingQueue, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf && [strongSelf.audio close:nil]) { + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:strongSelf]; + } + }); +} + +- (void)closeCompletely { + [self close:YES]; +} + +- (void)play { + __weak typeof(self)weakSelf = self; + + NSDate *now = [NSDate date]; + + dispatch_async(self.processingQueue, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { + return; + } + + strongSelf.playing = YES; + + [strongSelf.audio play]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [strongSelf render]; + }); + + dispatch_async(strongSelf.frameReaderQueue, ^{ + [strongSelf runFrameReader]; + }); + }); +} + +- (void)pause { + __weak typeof(self)weakSelf = self; + + dispatch_async(self.processingQueue, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf.playing) { + strongSelf.playing = NO; + + [strongSelf.audio pause]; + } + }); +} + +- (UIImage *)snapshot { + return [_view snapshot]; +} + +#pragma mark - Private Methods + - (void)initAll { [self initVars]; [self initAudio]; @@ -111,6 +262,7 @@ - (void)initView { } else { _view = [[DLGPlayerView alloc] init]; } + ((UIView *) _view).contentMode = UIViewContentModeScaleToFill; } - (void)initDecoder { @@ -148,75 +300,7 @@ - (void)clearVars { self.playingAudioFrame = nil; } -- (void)open:(NSString *)url { - __weak typeof(self)weakSelf = self; - - dispatch_async(self.processingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (!strongSelf || strongSelf.opening || strongSelf.closing) { - return; - } - - strongSelf.opening = YES; - - if ([strongSelf.audio open:nil]) { - strongSelf.decoder.audioChannels = [strongSelf.audio channels]; - strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:self]; - } - - dispatch_async(strongSelf.frameReaderQueue, ^{ - NSError *error = nil; - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - [strongSelf handleError:error]; - return; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - if (!strongSelf || !strongSelf.opening || strongSelf.closing) { - return; - } - - if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { - DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; - [view setCurrentEAGLContext]; - } - - strongSelf.view.isYUV = [strongSelf.decoder isYUV]; - strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; - strongSelf.view.rotation = strongSelf.decoder.rotation; - strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); - - if ([strongSelf.view isKindOfClass:[UIView class]]) { - ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; - } - - strongSelf.duration = strongSelf.decoder.duration; - strongSelf.metadata = strongSelf.decoder.metadata; - strongSelf.opening = NO; - strongSelf.buffering = NO; - strongSelf.playing = NO; - strongSelf.bufferedDuration = 0; - strongSelf.mediaPosition = 0; - strongSelf.mediaSyncTime = 0; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - - strongSelf.opened = YES; - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; - }); - }); - }); -} - -- (void)close { +- (void)close:(BOOL)completely { __weak typeof(self)weakSelf = self; dispatch_async(self.processingQueue, ^{ @@ -229,7 +313,11 @@ - (void)close { strongSelf.closing = YES; strongSelf.playing = NO; - [strongSelf closeAudio]; + if (completely) { + [strongSelf.audio close:nil]; + } else { + [strongSelf.audio pause]; + } dispatch_async(strongSelf.frameReaderQueue, ^{ [strongSelf.decoder prepareClose]; @@ -242,54 +330,6 @@ - (void)close { }); } -- (void)closeAudio { - if ([self.audio close:nil]) { - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:self]; - } -} - -- (void)play { - __weak typeof(self)weakSelf = self; - - dispatch_async(self.processingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { - return; - } - - strongSelf.playing = YES; - - [strongSelf.audio play]; - - dispatch_async(dispatch_get_main_queue(), ^{ - [strongSelf render]; - }); - - dispatch_async(strongSelf.frameReaderQueue, ^{ - [strongSelf runFrameReader]; - }); - }); -} - -- (void)pause { - __weak typeof(self)weakSelf = self; - - dispatch_async(self.processingQueue, ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf.playing) { - strongSelf.playing = NO; - - [strongSelf.audio pause]; - } - }); -} - -- (UIImage *)snapshot { - return [_view snapshot]; -} - - (void)runFrameReader { while (self.playing && !self.closing) { [self readFrame]; @@ -641,30 +681,6 @@ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)chan } } -- (UIView *)playerView { - return (UIView *) _view; -} - -- (void)setPosition:(double)position { - self.requestSeekPosition = position; - self.requestSeek = YES; -} - -- (double)position { - return self.mediaPosition; -} - -- (void)setSpeed:(double)speed { - _speed = speed; - self.decoder.speed = speed; -} - -- (void)setMute:(BOOL)mute { - _mute = mute; - self.audio.mute = mute; -} - -#pragma mark - Handle Error - (void)handleError:(NSError *)error { if (error == nil) { return; diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index 279063b..7c6ef46 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -40,4 +40,5 @@ - (void)play; - (void)pause; - (void)stop; +- (void)stopCompletely; @end diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 600738a..b10b3f7 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -178,7 +178,12 @@ - (void)stop { [UIApplication sharedApplication].idleTimerDisabled = NO; [_player close]; } - + +- (void)stopCompletely { + self.status = DLGPlayerStatusClosing; + [UIApplication sharedApplication].idleTimerDisabled = NO; + [_player closeCompletely]; +} #pragma mark - UI - (void)addPlayerView { diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.h b/DLGPlayer/codec/DLGPlayerAudioManager.h index 8744dd8..93a493c 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.h +++ b/DLGPlayer/codec/DLGPlayerAudioManager.h @@ -13,6 +13,7 @@ typedef void(^DLGPlayerAudioManagerFrameReaderBlock)(float *data, UInt32 num, UI @interface DLGPlayerAudioManager : NSObject @property (nonatomic) BOOL mute; +@property (nonatomic) BOOL opened; @property (nonatomic) float volume; @property (nonatomic, copy) DLGPlayerAudioManagerFrameReaderBlock frameReaderBlock; @property (nonatomic) NSTimeInterval bufferDuration; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 057df04..19ea6a4 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -28,7 +28,6 @@ OSStatus audioUnitRenderCallback(void *inRefCon, @interface DLGPlayerAudioManager () { BOOL _registeredKVO; - BOOL _opened; BOOL _closing; BOOL _shouldPlayAfterInterruption; BOOL _playing; @@ -72,6 +71,7 @@ - (void)dealloc { } [self unregisterNotifications]; + [self close]; if (_audioData) { free(_audioData); diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 4f004f6..1ef37a3 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -29,7 +29,7 @@ final class RootViewController: UIViewController { let pv = DLGSimplePlayerViewController() pv.view.translatesAutoresizingMaskIntoConstraints = true pv.delegate = self - pv.isAllowsFrameDrop = true +// pv.isAllowsFrameDrop = true pv.isAutoplay = true // pv.isMute = true pv.preventFromScreenLock = true From bf4910189cc17df74b7aa513b3482deaa5e4d79c Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 22 May 2020 18:20:06 +0900 Subject: [PATCH 205/215] Fixed: solve memory leak of decoder. Updated: change mute logic. --- DLGPlayer/DLGPlayer.h | 10 +- DLGPlayer/DLGPlayer.m | 403 +++++++++++----------- DLGPlayer/DLGSimplePlayerViewController.m | 24 +- DLGPlayer/codec/DLGPlayerAudioManager.h | 1 + DLGPlayer/codec/DLGPlayerAudioManager.m | 34 +- DLGPlayer/codec/DLGPlayerDecoder.m | 185 +++++----- DLGPlayer/common/DLGPlayerDef.h | 2 +- DLGPlayer/frame/DLGPlayerVideoFrame.h | 4 +- DLGPlayer/frame/DLGPlayerVideoFrame.m | 4 +- DLGPlayer/frame/DLGPlayerVideoRGBFrame.m | 12 +- DLGPlayer/frame/DLGPlayerVideoYUVFrame.m | 30 +- DLGPlayer/view/DLGPlayerView.m | 28 +- DLGPlayer/view/MetalPlayerView.m | 68 ++-- DLGPlayerDemo/Info.plist | 2 + DLGPlayerDemo/RootViewController.swift | 4 +- DLGPlayerDemo/ViewController.swift | 1 + 16 files changed, 411 insertions(+), 401 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 9609a7d..2a0da59 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -9,15 +9,15 @@ #import #import "DLGPlayerAudioFrame.h" #import "DLGPlayerAudioManager.h" +#import "DLGPlayerControlStatus.h" #import "DLGPlayerDef.h" #import "DLGPlayerDecoder.h" #import "DLGPlayerFrame.h" +#import "DLGPlayerUtils.h" #import "DLGPlayerVideoFrame.h" #import "DLGPlayerVideoRGBFrame.h" #import "DLGPlayerVideoYUVFrame.h" #import "DLGPlayerViewController.h" -#import "DLGPlayerUtils.h" -#import "DLGPlayerControlStatus.h" #import "DLGSimplePlayerViewController.h" typedef void (^onPauseComplete)(void); @@ -26,9 +26,9 @@ typedef void (^onPauseComplete)(void); @property (readonly, strong) UIView *playerView; @property (nonatomic) BOOL allowsFrameDrop; @property (nonatomic) BOOL mute; -@property (nonatomic) BOOL playing; -@property (nonatomic) BOOL buffering; -@property (nonatomic) BOOL opened; +@property (atomic) BOOL playing; +@property (atomic) BOOL buffering; +@property (atomic) BOOL opened; @property (nonatomic) float brightness; @property (nonatomic) double frameDropDuration; @property (nonatomic) double minBufferDuration; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index a961f3d..61dc5d3 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -18,8 +18,8 @@ #import "MetalPlayerView.h" @interface DLGPlayer () -@property (nonatomic) BOOL closing; -@property (nonatomic) BOOL opening; +@property (atomic) BOOL closing; +@property (atomic) BOOL opening; @property (nonatomic) BOOL frameDropped; @property (nonatomic) BOOL notifiedBufferStart; @property (nonatomic) BOOL renderBegan; @@ -30,13 +30,13 @@ @interface DLGPlayer () @property (nonatomic) double mediaSyncTime; @property (nonatomic) double requestSeekPosition; @property (nonatomic) NSUInteger playingAudioFrameDataPosition; -@property (nonatomic, strong) NSMutableArray *vframes; -@property (nonatomic, strong) NSMutableArray *aframes; @property (nonatomic, strong) dispatch_queue_t frameReaderQueue; @property (nonatomic, strong) dispatch_queue_t processingQueue; @property (nonatomic, strong) dispatch_queue_t renderingQueue; @property (nonatomic, strong) dispatch_semaphore_t vFramesLock; @property (nonatomic, strong) dispatch_semaphore_t aFramesLock; +@property (nonatomic, strong) NSMutableArray *vframes; +@property (nonatomic, strong) NSMutableArray *aframes; @property (nonatomic, strong) DLGPlayerAudioFrame *playingAudioFrame; @property (nonatomic, strong) DLGPlayerDecoder *decoder; @property (nonatomic, strong) DLGPlayerAudioManager *audio; @@ -66,8 +66,33 @@ - (void)setSpeed:(double)speed { } - (void)setMute:(BOOL)mute { + if (mute == _mute) { + return; + } + _mute = mute; self.audio.mute = mute; + + __weak typeof(self)weakSelf = self; + + dispatch_async(self.processingQueue, ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (!strongSelf) { + return; + } + + if (mute) { + if ([strongSelf.audio close]) { + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:strongSelf]; + } + } else if (self.playing) { + if ([strongSelf.audio open]) { + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; + } + [strongSelf.audio play]; + } + }); } #pragma mark - Con(De)structors @@ -100,11 +125,10 @@ - (void)open:(NSString *)url { strongSelf.opening = YES; - if (!strongSelf.audio.opened && [strongSelf.audio open:nil]) { + if (!strongSelf.audio.opened && [strongSelf.audio open]) { strongSelf.decoder.audioChannels = [strongSelf.audio channels]; strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:self]; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; } NSError *error = nil; @@ -114,32 +138,36 @@ - (void)open:(NSString *)url { return; } - strongSelf.duration = strongSelf.decoder.duration; - strongSelf.metadata = strongSelf.decoder.metadata; - strongSelf.opening = NO; - strongSelf.buffering = NO; - strongSelf.playing = NO; - strongSelf.bufferedDuration = 0; - strongSelf.mediaPosition = 0; - strongSelf.mediaSyncTime = 0; - strongSelf.view.isYUV = [strongSelf.decoder isYUV]; - strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; - strongSelf.view.rotation = strongSelf.decoder.rotation; - strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - dispatch_async(dispatch_get_main_queue(), ^{ if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; [view setCurrentEAGLContext]; } + + strongSelf.view.isYUV = [strongSelf.decoder isYUV]; + strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; + strongSelf.view.rotation = strongSelf.decoder.rotation; + strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); + + if ([strongSelf.view isKindOfClass:[UIView class]]) { + ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; + } + + strongSelf.duration = strongSelf.decoder.duration; + strongSelf.metadata = strongSelf.decoder.metadata; + strongSelf.opening = NO; + strongSelf.buffering = NO; + strongSelf.playing = NO; + strongSelf.bufferedDuration = 0; + strongSelf.mediaPosition = 0; + strongSelf.mediaSyncTime = 0; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; strongSelf.opened = YES; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; }); }); @@ -155,7 +183,7 @@ - (void)closeAudio { dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; - if (strongSelf && [strongSelf.audio close:nil]) { + if (strongSelf && [strongSelf.audio close]) { [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:strongSelf]; } }); @@ -168,8 +196,6 @@ - (void)closeCompletely { - (void)play { __weak typeof(self)weakSelf = self; - NSDate *now = [NSDate date]; - dispatch_async(self.processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; @@ -222,6 +248,12 @@ - (void)initVars { _allowsFrameDrop = NO; _requestSeek = NO; _renderBegan = NO; + _buffering = NO; + _closing = NO; + _opening = NO; + _playing = NO; + _opened = NO; + _frameDropped = NO; _frameDropDuration = DLGPlayerFrameDropDuration; _minBufferDuration = DLGPlayerMinBufferDuration; _maxBufferDuration = DLGPlayerMaxBufferDuration; @@ -229,40 +261,37 @@ - (void)initVars { _brightness = 1; _requestSeekPosition = 0; _speed = 1.0; - - self.buffering = NO; - self.closing = NO; - self.opening = NO; - self.playing = NO; - self.opened = NO; - self.frameDropped = NO; - self.bufferedDuration = 0; - self.mediaPosition = 0; - self.playingAudioFrameDataPosition = 0; - self.playingAudioFrame = nil; + _bufferedDuration = 0; + _mediaPosition = 0; + _playingAudioFrameDataPosition = 0; + _playingAudioFrame = nil; _aFramesLock = dispatch_semaphore_create(1); _vFramesLock = dispatch_semaphore_create(1); _vframes = [NSMutableArray arrayWithCapacity:128]; _aframes = [NSMutableArray arrayWithCapacity:128]; - @autoreleasepool { - NSString *frameReaderQueueName = [NSString stringWithFormat:@"DLGPlayer.frameReaderQueue::%zd", self.hash]; - NSString *processingQueueName = [NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash]; - NSString *renderingQueueName = [NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash]; - _frameReaderQueue = dispatch_queue_create(frameReaderQueueName.UTF8String, DISPATCH_QUEUE_SERIAL); - _processingQueue = dispatch_queue_create(processingQueueName.UTF8String, DISPATCH_QUEUE_SERIAL); - _renderingQueue = dispatch_queue_create(renderingQueueName.UTF8String, DISPATCH_QUEUE_SERIAL); + const char *frameReaderQueueName = [NSString stringWithFormat:@"DLGPlayer.frameReaderQueue::%zd", self.hash].UTF8String; + const char *processingQueueName = [NSString stringWithFormat:@"DLGPlayer.processingQueue::%zd", self.hash].UTF8String; + const char *renderingQueueName = [NSString stringWithFormat:@"DLGPlayer.renderingQueue::%zd", self.hash].UTF8String; + + if (@available(iOS 10.0, *)) { + _frameReaderQueue = dispatch_queue_create(frameReaderQueueName, DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + _processingQueue = dispatch_queue_create(processingQueueName, DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + _renderingQueue = dispatch_queue_create(renderingQueueName, DISPATCH_QUEUE_SERIAL_WITH_AUTORELEASE_POOL); + } else { + _frameReaderQueue = dispatch_queue_create(frameReaderQueueName, DISPATCH_QUEUE_SERIAL); + _processingQueue = dispatch_queue_create(processingQueueName, DISPATCH_QUEUE_SERIAL); + _renderingQueue = dispatch_queue_create(renderingQueueName, DISPATCH_QUEUE_SERIAL); } } - (void)initView { if (@available(iOS 9.0, *)) { - _view = [DLGPlayerUtils isMetalSupport] ? [[MetalPlayerView alloc] init] : [[DLGPlayerView alloc] init]; + _view = [DLGPlayerUtils isMetalSupport] ? [MetalPlayerView new] : [DLGPlayerView new]; } else { - _view = [[DLGPlayerView alloc] init]; + _view = [DLGPlayerView new]; } - ((UIView *) _view).contentMode = UIViewContentModeScaleToFill; } - (void)initDecoder { @@ -311,21 +340,22 @@ - (void)close:(BOOL)completely { } strongSelf.closing = YES; - strongSelf.playing = NO; if (completely) { - [strongSelf.audio close:nil]; + if ([strongSelf.audio close]) { + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:strongSelf]; + } } else { [strongSelf.audio pause]; } - + dispatch_async(strongSelf.frameReaderQueue, ^{ [strongSelf.decoder prepareClose]; [strongSelf.decoder close]; }); - [strongSelf.view clear]; [strongSelf clearVars]; + [strongSelf.view clear]; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; }); } @@ -346,93 +376,61 @@ - (void)readFrame { self.buffering = YES; double tempDuration = 0; + double maxDuration = self.allowsFrameDrop && !self.frameDropped ? self.frameDropDuration : self.maxBufferDuration; NSMutableArray *tempVFrames = [NSMutableArray arrayWithCapacity:8]; NSMutableArray *tempAFrames = [NSMutableArray arrayWithCapacity:8]; dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); - while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek) { - // Drop frames - if (self.allowsFrameDrop && !self.frameDropped) { - if (self.bufferedDuration > self.frameDropDuration / self.speed) { - if (dispatch_semaphore_wait(self.vFramesLock, t) == 0) { - for (DLGPlayerFrame *f in self.vframes) { - f.dropFrame = YES; - } - dispatch_semaphore_signal(self.vFramesLock); - } - - if (dispatch_semaphore_wait(self.aFramesLock, t) == 0) { - for (DLGPlayerFrame *f in self.aframes) { - f.dropFrame = YES; - } - dispatch_semaphore_signal(self.aFramesLock); - } - - self.frameDropped = YES; - - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); - } - continue; - } - } else if (self.bufferedDuration > self.maxBufferDuration / self.speed) { - continue; - } - + while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek + && (self.bufferedDuration + tempDuration) < maxDuration) { @autoreleasepool { NSArray *fs = [self.decoder readFrames]; if (fs == nil) { break; } if (fs.count == 0) { continue; } - { - for (DLGPlayerFrame *f in fs) { - if (f.type == kDLGPlayerFrameTypeVideo) { - [tempVFrames addObject:f]; - tempDuration += f.duration; - } + for (DLGPlayerFrame *f in fs) { + if (f.type == kDLGPlayerFrameTypeVideo) { + [tempVFrames addObject:f]; + tempDuration += f.duration; } - - long timeout = dispatch_semaphore_wait(self.vFramesLock, t); - if (timeout == 0) { - if (tempVFrames.count > 0) { - self.bufferedDuration += tempDuration; - tempDuration = 0; - - [self.vframes addObjectsFromArray:tempVFrames]; - [tempVFrames removeAllObjects]; + + if (!self.mute && f.type == kDLGPlayerFrameTypeAudio) { + [tempAFrames addObject:f]; + if (!self.decoder.hasVideo) { + tempDuration += f.duration; } - dispatch_semaphore_signal(self.vFramesLock); } } - { - if (self.mute) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer skip audio frames cause mute is enabled."); - } - } else { - for (DLGPlayerFrame *f in fs) { - if (f.type == kDLGPlayerFrameTypeAudio) { - [tempAFrames addObject:f]; - if (!self.decoder.hasVideo) tempDuration += f.duration; - } - } + + long timeout = dispatch_semaphore_wait(self.vFramesLock, t); + if (timeout == 0) { + if (tempVFrames.count > 0) { + self.bufferedDuration += tempDuration; + tempDuration = 0; - long timeout = dispatch_semaphore_wait(self.aFramesLock, t); - if (timeout == 0) { - if (tempAFrames.count > 0) { - if (!self.decoder.hasVideo) { - self.bufferedDuration += tempDuration; - tempDuration = 0; - } - [self.aframes addObjectsFromArray:tempAFrames]; - [tempAFrames removeAllObjects]; + [self.vframes addObjectsFromArray:tempVFrames]; + [tempVFrames removeAllObjects]; + } + dispatch_semaphore_signal(self.vFramesLock); + } + + if (!self.mute) { + long timeout = dispatch_semaphore_wait(self.aFramesLock, t); + if (timeout == 0) { + if (tempAFrames.count > 0) { + if (!self.decoder.hasVideo) { + self.bufferedDuration += tempDuration; + tempDuration = 0; } - dispatch_semaphore_signal(self.aFramesLock); + [self.aframes addObjectsFromArray:tempAFrames]; + [tempAFrames removeAllObjects]; } + dispatch_semaphore_signal(self.aFramesLock); } } } + [self dropFrames]; } { @@ -460,12 +458,37 @@ - (void)readFrame { dispatch_semaphore_signal(self.aFramesLock); } } + [self dropFrames]; } } self.buffering = NO; } +- (void)dropFrames { + if (self.allowsFrameDrop && !self.frameDropped && self.bufferedDuration > self.frameDropDuration / self.speed) { + if (dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_NOW) == 0) { + for (DLGPlayerFrame *f in self.vframes) { + f.dropFrame = YES; + } + dispatch_semaphore_signal(self.vFramesLock); + } + + if (dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW) == 0) { + for (DLGPlayerFrame *f in self.aframes) { + f.dropFrame = YES; + } + dispatch_semaphore_signal(self.aFramesLock); + } + + self.frameDropped = YES; + + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); + } + } +} + - (void)seekPositionInFrameReader { [self.decoder seek:self.requestSeekPosition]; @@ -502,11 +525,11 @@ - (void)render { if (noframes && !self.notifiedBufferStart) { self.notifiedBufferStart = YES; - NSDictionary *userInfo = @{ DLGPlayerNotificationBufferStateKey : @(self.notifiedBufferStart) }; + NSDictionary *userInfo = @{DLGPlayerNotificationBufferStateKey: @(self.notifiedBufferStart)}; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationBufferStateChanged object:self userInfo:userInfo]; } else if (!noframes && self.notifiedBufferStart && self.bufferedDuration >= self.minBufferDuration / self.speed) { self.notifiedBufferStart = NO; - NSDictionary *userInfo = @{ DLGPlayerNotificationBufferStateKey : @(self.notifiedBufferStart) }; + NSDictionary *userInfo = @{DLGPlayerNotificationBufferStateKey: @(self.notifiedBufferStart)}; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationBufferStateChanged object:self userInfo:userInfo]; } @@ -527,11 +550,7 @@ - (void)render { if (self.vframes.count <= 0 || !self.decoder.hasVideo || self.notifiedBufferStart) { __weak typeof(self)weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf) { - [strongSelf render]; - } + [weakSelf render]; }); return; } @@ -560,11 +579,7 @@ - (void)render { __weak typeof(self)weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (t * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf) { - [strongSelf render]; - } + [weakSelf render]; }); } @@ -617,66 +632,70 @@ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)chan } while(frames > 0) { - if (self.playingAudioFrame == nil) { - { - if (self.aframes.count <= 0) { - memset(data, 0, frames * channels * sizeof(float)); - return; - } - - long timeout = dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW); - if (timeout == 0) { - DLGPlayerAudioFrame *frame = self.aframes[0]; + @autoreleasepool { + if (self.playingAudioFrame == nil) { + { + if (self.aframes.count <= 0) { + memset(data, 0, frames * channels * sizeof(float)); + return; + } - if (self.decoder.hasVideo) { - const double dt = self.mediaPosition - frame.position; - - if (dt < -0.1 && self.vframes.count > 0) { // audio is faster than video, silence - memset(data, 0, frames * channels * sizeof(float)); - dispatch_semaphore_signal(self.aFramesLock); - break; - } else if (dt > 0.1) { // audio is slower than video, skip - [self.aframes removeObjectAtIndex:0]; - dispatch_semaphore_signal(self.aFramesLock); - continue; - } else { - self.playingAudioFrameDataPosition = 0; - self.playingAudioFrame = frame; - [self.aframes removeObjectAtIndex:0]; + long timeout = dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW); + if (timeout == 0) { + @autoreleasepool { + DLGPlayerAudioFrame *frame = self.aframes[0]; + + if (self.decoder.hasVideo) { + const double dt = self.mediaPosition - frame.position; + + if (dt < -0.1 && self.vframes.count > 0) { // audio is faster than video, silence + memset(data, 0, frames * channels * sizeof(float)); + dispatch_semaphore_signal(self.aFramesLock); + break; + } else if (dt > 0.1) { // audio is slower than video, skip + [self.aframes removeObjectAtIndex:0]; + dispatch_semaphore_signal(self.aFramesLock); + continue; + } else { + self.playingAudioFrameDataPosition = 0; + self.playingAudioFrame = frame; + [self.aframes removeObjectAtIndex:0]; + } + } else { + self.playingAudioFrameDataPosition = 0; + self.playingAudioFrame = frame; + [self.aframes removeObjectAtIndex:0]; + self.mediaPosition = frame.position; + self.bufferedDuration -= frame.duration; + } } - } else { - self.playingAudioFrameDataPosition = 0; - self.playingAudioFrame = frame; - [self.aframes removeObjectAtIndex:0]; - self.mediaPosition = frame.position; - self.bufferedDuration -= frame.duration; - } - dispatch_semaphore_signal(self.aFramesLock); - } else return; + dispatch_semaphore_signal(self.aFramesLock); + } else return; + } + } + + NSData *frameData = self.playingAudioFrame.data; + NSUInteger pos = self.playingAudioFrameDataPosition; + if (frameData == nil) { + memset(data, 0, frames * channels * sizeof(float)); + return; + } + + const void *bytes = (Byte *)frameData.bytes + pos; + const NSUInteger remainingBytes = frameData.length - pos; + const NSUInteger channelSize = channels * sizeof(float); + const NSUInteger bytesToCopy = MIN(frames * channelSize, remainingBytes); + const NSUInteger framesToCopy = bytesToCopy / channelSize; + + memcpy(data, bytes, bytesToCopy); + frames -= framesToCopy; + data += framesToCopy * channels; + + if (bytesToCopy < remainingBytes) { + self.playingAudioFrameDataPosition += bytesToCopy; + } else { + self.playingAudioFrame = nil; } - } - - NSData *frameData = self.playingAudioFrame.data; - NSUInteger pos = self.playingAudioFrameDataPosition; - if (frameData == nil) { - memset(data, 0, frames * channels * sizeof(float)); - return; - } - - const void *bytes = (Byte *)frameData.bytes + pos; - const NSUInteger remainingBytes = frameData.length - pos; - const NSUInteger channelSize = channels * sizeof(float); - const NSUInteger bytesToCopy = MIN(frames * channelSize, remainingBytes); - const NSUInteger framesToCopy = bytesToCopy / channelSize; - - memcpy(data, bytes, bytesToCopy); - frames -= framesToCopy; - data += framesToCopy * channels; - - if (bytesToCopy < remainingBytes) { - self.playingAudioFrameDataPosition += bytesToCopy; - } else { - self.playingAudioFrame = nil; } } } @@ -685,8 +704,8 @@ - (void)handleError:(NSError *)error { if (error == nil) { return; } - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:self userInfo:@{DLGPlayerNotificationErrorKey: error}]; + NSDictionary *userInfo = @{DLGPlayerNotificationErrorKey: error}; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationError object:self userInfo:userInfo]; } @end diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index b10b3f7..bfe5dac 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -192,19 +192,17 @@ - (void)addPlayerView { [self.view addSubview:v]; - @autoreleasepool { - NSDictionary *views = NSDictionaryOfVariableBindings(v); - NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" - options:0 - metrics:nil - views:views]; - [self.view addConstraints:ch]; - NSArray *cv = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" - options:0 - metrics:nil - views:views]; - [self.view addConstraints:cv]; - } + NSDictionary *views = NSDictionaryOfVariableBindings(v); + NSArray *ch = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:ch]; + NSArray *cv = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[v]|" + options:0 + metrics:nil + views:views]; + [self.view addConstraints:cv]; } #pragma mark - Notifications diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.h b/DLGPlayer/codec/DLGPlayerAudioManager.h index 93a493c..0913123 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.h +++ b/DLGPlayer/codec/DLGPlayerAudioManager.h @@ -18,6 +18,7 @@ typedef void(^DLGPlayerAudioManagerFrameReaderBlock)(float *data, UInt32 num, UI @property (nonatomic, copy) DLGPlayerAudioManagerFrameReaderBlock frameReaderBlock; @property (nonatomic) NSTimeInterval bufferDuration; +- (BOOL)open; - (BOOL)open:(NSError **)error; - (BOOL)play; - (BOOL)play:(NSError **)error; diff --git a/DLGPlayer/codec/DLGPlayerAudioManager.m b/DLGPlayer/codec/DLGPlayerAudioManager.m index 19ea6a4..6f1e9a8 100644 --- a/DLGPlayer/codec/DLGPlayerAudioManager.m +++ b/DLGPlayer/codec/DLGPlayerAudioManager.m @@ -73,24 +73,29 @@ - (void)dealloc { [self unregisterNotifications]; [self close]; - if (_audioData) { - free(_audioData); - _audioData = NULL; - } + free(_audioData); + _audioData = NULL; +} + +- (BOOL)open { + return [self open:nil]; } /* * https://developer.apple.com/library/content/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html */ - (BOOL)open:(NSError **)error { + if (self.mute) { + return NO; + } + if (DLGPlayerUtils.debugEnabled) { NSLog(@"[Audio] %zd -> opening", self.hash); } NSError *rawError = nil; AVAudioSession *session = [AVAudioSession sharedInstance]; - AVAudioSessionCategory category = self.mute ? AVAudioSessionCategoryAmbient : AVAudioSessionCategoryPlayback; - if (![session setCategory:category error:&rawError]) { + if (![session setCategory:AVAudioSessionCategoryPlayback error:&rawError]) { [DLGPlayerUtils createError:error withDomain:DLGPlayerErrorDomainAudioManager andCode:DLGPlayerErrorCodeCannotSetAudioCategory @@ -422,6 +427,7 @@ - (OSStatus)render:(AudioBufferList *)ioData count:(UInt32)inNumberFrames { } } + return noErr; } @@ -444,14 +450,6 @@ - (void)registerNotifications { selector:@selector(notifyAudioSessionInterruptionNotification:) name:AVAudioSessionInterruptionNotification object:nil]; - [nc addObserver:self - selector:@selector(notifyAudioSessionMediaServicesWereLostNotification:) - name:AVAudioSessionMediaServicesWereLostNotification - object:nil]; - [nc addObserver:self - selector:@selector(notifyAudioSessionMediaServicesWereResetNotification:) - name:AVAudioSessionMediaServicesWereResetNotification - object:nil]; if (!_registeredKVO) { AVAudioSession *session = [AVAudioSession sharedInstance]; @@ -494,14 +492,6 @@ - (void)notifyAudioSessionInterruptionNotification:(NSNotification *)notif { } } -- (void)notifyAudioSessionMediaServicesWereLostNotification:(NSNotification *)notif { - [self clear]; -} - -- (void)notifyAudioSessionMediaServicesWereResetNotification:(NSNotification *)notif { - [self clear]; -} - - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { AVAudioSession *session = [AVAudioSession sharedInstance]; if (object == session && [keyPath isEqualToString:@"outputVolume"]) { diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index e351128..ccad36a 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -63,6 +63,7 @@ - (void)dealloc { if (DLGPlayerUtils.debugEnabled) { NSLog(@"DLGPlayerDecoder dealloc"); } + free(m_pAudioSwrBuffer); } - (BOOL)open:(NSString *)url error:(NSError **)error { @@ -398,18 +399,18 @@ - (NSArray *)readFrames { BOOL reading = YES; while (reading) { - @autoreleasepool { - g_dIOStartTime = [NSDate timeIntervalSinceReferenceDate]; - int ret = av_read_frame(fmtctx, &packet); - if (ret < 0) { - if (ret == AVERROR_EOF) self.isEOF = YES; - char *e = av_err2str(ret); - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer read frame error: %s", e); - } - break; + g_dIOStartTime = [NSDate timeIntervalSinceReferenceDate]; + int ret = av_read_frame(fmtctx, &packet); + if (ret < 0) { + if (ret == AVERROR_EOF) self.isEOF = YES; + char *e = av_err2str(ret); + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"DLGPlayer read frame error: %s", e); } - + break; + } + + @autoreleasepool { /* * https://ffmpeg.org/doxygen/3.1/group__lavc__encdec.html */ @@ -435,9 +436,9 @@ - (NSArray *)readFrames { if (fs != nil && fs.count > 0) { [frames addObjectsFromArray:fs]; } - - av_packet_unref(&packet); } + + av_packet_unref(&packet); } return frames; @@ -479,12 +480,15 @@ - (NSArray *)readFrames { CGDataProviderRelease(provider); NSMutableArray *frames = [NSMutableArray array]; - DLGPlayerVideoRGBFrame *frame = [[DLGPlayerVideoRGBFrame alloc] init]; - frame.data = [NSData dataWithBytes:imageData length:length]; - frame.width = (int)width; - frame.height = (int)height; - frame.hasAlpha = YES; - [frames addObject:frame]; + + @autoreleasepool { + DLGPlayerVideoRGBFrame *frame = [[DLGPlayerVideoRGBFrame alloc] init]; + frame.data = [NSData dataWithBytes:imageData length:length]; + frame.width = (int)width; + frame.height = (int)height; + frame.hasAlpha = YES; + [frames addObject:frame]; + } free(imageData); @@ -502,7 +506,6 @@ - (NSArray *)readFrames { NSMutableArray *frames = [NSMutableArray array]; do { - @autoreleasepool { ret = avcodec_receive_frame(context, frame); if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { break; @@ -512,7 +515,8 @@ - (NSArray *)readFrames { } break; } - + + @autoreleasepool { DLGPlayerVideoFrame *f = nil; const int width = context->width; const int height = context->height; @@ -580,85 +584,84 @@ - (NSArray *)readFrames { NSMutableArray *frames = [NSMutableArray array]; do { - @autoreleasepool { - ret = avcodec_receive_frame(context, frame); - if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { - break; - } else if (ret < 0) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"avcodec_receive_frame: %d", ret); - } - break; + ret = avcodec_receive_frame(context, frame); + if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) { + break; + } else if (ret < 0) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"avcodec_receive_frame: %d", ret); } - if (frame->data[0] == NULL) continue; + break; + } + if (frame->data[0] == NULL) continue; + + const float sampleRate = _audioSampleRate; + const UInt32 channels = _audioChannels; + + void *data = NULL; + NSInteger samplesPerChannel = 0; + if (swrctx != NULL && swrbuf != NULL) { + float sampleRatio = sampleRate / context->sample_rate; + float channelRatio = channels / context->channels; + float ratio = MAX(1, sampleRatio) * MAX(1, channelRatio) * 2; + int samples = frame->nb_samples * ratio; + int bufsize = av_samples_get_buffer_size(NULL, + channels, + samples, + AV_SAMPLE_FMT_S16, + 1); - const float sampleRate = _audioSampleRate; - const UInt32 channels = _audioChannels; + if (*swrbuf == NULL || *swrbufsize < bufsize) { + *swrbufsize = bufsize; + *swrbuf = realloc(*swrbuf, bufsize); + } - void *data = NULL; - NSInteger samplesPerChannel = 0; - if (swrctx != NULL && swrbuf != NULL) { - float sampleRatio = sampleRate / context->sample_rate; - float channelRatio = channels / context->channels; - float ratio = MAX(1, sampleRatio) * MAX(1, channelRatio) * 2; - int samples = frame->nb_samples * ratio; - int bufsize = av_samples_get_buffer_size(NULL, - channels, - samples, - AV_SAMPLE_FMT_S16, - 1); - if (*swrbuf == NULL || *swrbufsize < bufsize) { - *swrbufsize = bufsize; - *swrbuf = realloc(*swrbuf, bufsize); - } - - Byte *o[2] = { *swrbuf, 0 }; - samplesPerChannel = swr_convert(swrctx, o, samples, (const uint8_t **)frame->data, frame->nb_samples); - if (samplesPerChannel < 0) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"failed to resample audio"); - } - return nil; - } - - data = *swrbuf; - } else { - if (context->sample_fmt != AV_SAMPLE_FMT_S16) { - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"invalid audio format"); - } - return nil; + Byte *o[2] = { *swrbuf, 0 }; + samplesPerChannel = swr_convert(swrctx, o, samples, (const uint8_t **)frame->data, frame->nb_samples); + if (samplesPerChannel < 0) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"failed to resample audio"); } - - data = frame->data[0]; - samplesPerChannel = frame->nb_samples; + return nil; } - NSUInteger elements = samplesPerChannel * channels; - NSUInteger dataLength = elements * sizeof(float); - NSMutableData *mdata = [NSMutableData dataWithLength:dataLength]; - - float scalar = 1.0f / INT16_MAX; - vDSP_vflt16(data, 1, mdata.mutableBytes, 1, elements); - vDSP_vsmul(mdata.mutableBytes, 1, &scalar, mdata.mutableBytes, 1, elements); - - DLGPlayerAudioFrame *f = [[DLGPlayerAudioFrame alloc] init]; - f.data = mdata; - f.position = frame->best_effort_timestamp * _audioTimebase; - - - double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevAudio; - - if (duration > 0) { - f.duration = duration * _audioTimebase / _speed; - } else { - f.duration = f.data.length / (sizeof(float) * channels * sampleRate) / _speed; + data = *swrbuf; + } else { + if (context->sample_fmt != AV_SAMPLE_FMT_S16) { + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"invalid audio format"); + } + return nil; } - ptsPrevAudio = frame->pts; - - [frames addObject:f]; + data = frame->data[0]; + samplesPerChannel = frame->nb_samples; } + + NSUInteger elements = samplesPerChannel * channels; + NSUInteger dataLength = elements * sizeof(float); + NSMutableData *mdata = [NSMutableData dataWithLength:dataLength]; + + float scalar = 1.0f / INT16_MAX; + vDSP_vflt16(data, 1, mdata.mutableBytes, 1, elements); + vDSP_vsmul(mdata.mutableBytes, 1, &scalar, mdata.mutableBytes, 1, elements); + + DLGPlayerAudioFrame *f = [[DLGPlayerAudioFrame alloc] init]; + f.data = mdata; + f.position = frame->best_effort_timestamp * _audioTimebase; + + + double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevAudio; + + if (duration > 0) { + f.duration = duration * _audioTimebase / _speed; + } else { + f.duration = f.data.length / (sizeof(float) * channels * sampleRate) / _speed; + } + + ptsPrevAudio = frame->pts; + + [frames addObject:f]; } while(ret == 0); return frames; diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index f639e11..7e91686 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -11,7 +11,7 @@ #define DLGPlayerLocalizedStringTable @"DLGPlayerStrings" -#define DLGPlayerFrameDropDuration 3 +#define DLGPlayerFrameDropDuration 4 #define DLGPlayerMinBufferDuration 1 #define DLGPlayerMaxBufferDuration 5 diff --git a/DLGPlayer/frame/DLGPlayerVideoFrame.h b/DLGPlayer/frame/DLGPlayerVideoFrame.h index e5655e9..b79db7d 100644 --- a/DLGPlayer/frame/DLGPlayerVideoFrame.h +++ b/DLGPlayer/frame/DLGPlayerVideoFrame.h @@ -25,7 +25,7 @@ typedef enum : NSUInteger { @property (nonatomic) float brightness; - (BOOL)prepareProgram:(GLuint)program; -- (BOOL)prepareDevice:(id)device; -- (BOOL)render:(id)encoder; +- (BOOL)prepareDevice:(__weak id)device; +- (BOOL)render:(__weak id)encoder; @end diff --git a/DLGPlayer/frame/DLGPlayerVideoFrame.m b/DLGPlayer/frame/DLGPlayerVideoFrame.m index aa4b2d7..d6b1ccd 100644 --- a/DLGPlayer/frame/DLGPlayerVideoFrame.m +++ b/DLGPlayer/frame/DLGPlayerVideoFrame.m @@ -27,11 +27,11 @@ - (BOOL)prepareProgram:(GLuint)program { return NO; } -- (BOOL)prepareDevice:(id)device { +- (BOOL)prepareDevice:(__weak id)device { return NO; } -- (BOOL)render:(id)encoder { +- (BOOL)render:(__weak id)encoder { return NO; } diff --git a/DLGPlayer/frame/DLGPlayerVideoRGBFrame.m b/DLGPlayer/frame/DLGPlayerVideoRGBFrame.m index 432f50f..f48c177 100644 --- a/DLGPlayer/frame/DLGPlayerVideoRGBFrame.m +++ b/DLGPlayer/frame/DLGPlayerVideoRGBFrame.m @@ -85,7 +85,7 @@ - (BOOL)prepareProgram:(GLuint)program { return YES; } -- (BOOL)prepareDevice:(id)device { +- (BOOL)prepareDevice:(__weak id)device { const NSInteger w = self.width; const NSInteger h = self.height; @@ -96,7 +96,7 @@ - (BOOL)prepareDevice:(id)device { return YES; } -- (BOOL)render:(id)encoder { +- (BOOL)render:(__weak id)encoder { if (!self.prepared) { return NO; } @@ -123,11 +123,9 @@ - (void)createMTLTextures:(id)device { const NSInteger w = self.width; const NSInteger h = self.height; - @autoreleasepool { - MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:w height:h mipmapped:NO]; - - _mtlTexture = [device newTextureWithDescriptor:descriptor]; - } + MTLTextureDescriptor *descriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:w height:h mipmapped:NO]; + + _mtlTexture = [device newTextureWithDescriptor:descriptor]; } - (void)updateMTLTextures { diff --git a/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m b/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m index 4d7a4bc..c25d958 100644 --- a/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m +++ b/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m @@ -42,7 +42,7 @@ - (id)init { #pragma mark - Destructor - (void)dealloc { - [self deleteTexture]; + [self deleteTextures]; } #pragma mark - Overidden: DLGPlayerVideoFrame @@ -98,10 +98,12 @@ - (BOOL)prepareProgram:(GLuint)program { glUniform1f(glGetUniformLocation(program, "f_brightness"), self.brightness); + free(data); + return YES; } -- (BOOL)prepareDevice:(id)device { +- (BOOL)prepareDevice:(__weak id)device { const NSInteger w = self.width; const NSInteger h = self.height; @@ -114,7 +116,7 @@ - (BOOL)prepareDevice:(id)device { return YES; } -- (BOOL)render:(id)encoder { +- (BOOL)render:(__weak id)encoder { if (!self.prepared) { return NO; } @@ -128,10 +130,12 @@ - (BOOL)render:(id)encoder { #pragma mark - Private Methods (OpenGL ES) -- (void)deleteTexture { +- (void)deleteTextures { if (_texture[0] != 0) { glDeleteTextures(3, _texture); - for (int i = 0; i < 3; ++i) _texture[i] = 0; + for (int i = 0; i < 3; ++i) { + _texture[i] = 0; + } } } @@ -161,15 +165,13 @@ - (void)createMTLTextures:(id)device { const NSInteger w = self.width; const NSInteger h = self.height; - @autoreleasepool { - MTLTextureDescriptor *y = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:w height:h mipmapped:NO]; - MTLTextureDescriptor *u = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:w / 2 height:h / 2 mipmapped:NO]; - MTLTextureDescriptor *v = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:w / 2 height:h / 2 mipmapped:NO]; - - _yTexture = [device newTextureWithDescriptor:y]; - _uTexture = [device newTextureWithDescriptor:u]; - _vTexture = [device newTextureWithDescriptor:v]; - } + MTLTextureDescriptor *y = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:w height:h mipmapped:NO]; + MTLTextureDescriptor *u = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:w / 2 height:h / 2 mipmapped:NO]; + MTLTextureDescriptor *v = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR8Uint width:w / 2 height:h / 2 mipmapped:NO]; + + _yTexture = [device newTextureWithDescriptor:y]; + _uTexture = [device newTextureWithDescriptor:u]; + _vTexture = [device newTextureWithDescriptor:v]; } - (void)updateMTLTextures { diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index fe1c1b5..98f5081 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -190,19 +190,21 @@ - (void)createGLProgram { } // Load shaders - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - NSString *vertexShaderFilename = @"DLGPlayerVertexShader"; - if (_shouldScale) vertexShaderFilename = @"DLGPlayerRotationScaleVertexShader"; - else if (_shouldRotate) vertexShaderFilename = @"DLGPlayerRotationVertexShader"; - NSString *vertexShaderFile = [bundle pathForResource:vertexShaderFilename ofType:@"glsl"]; - GLuint vertexShader = [DLGPlayerView loadShader:GL_VERTEX_SHADER withFile:vertexShaderFile]; - NSString *fragmentShaderResource = _isYUV ? @"DLGPlayerYUVFragmentShader" : @"DLGPlayerRGBFragmentShader"; - NSString *fragmentShaderFile = [bundle pathForResource:fragmentShaderResource ofType:@"glsl"]; - GLuint fragmentShader = [DLGPlayerView loadShader:GL_FRAGMENT_SHADER withFile:fragmentShaderFile]; - - // Attach shaders - glAttachShader(program, vertexShader); - glAttachShader(program, fragmentShader); + @autoreleasepool { + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + NSString *vertexShaderFilename = @"DLGPlayerVertexShader"; + if (_shouldScale) vertexShaderFilename = @"DLGPlayerRotationScaleVertexShader"; + else if (_shouldRotate) vertexShaderFilename = @"DLGPlayerRotationVertexShader"; + NSString *vertexShaderFile = [bundle pathForResource:vertexShaderFilename ofType:@"glsl"]; + GLuint vertexShader = [DLGPlayerView loadShader:GL_VERTEX_SHADER withFile:vertexShaderFile]; + NSString *fragmentShaderResource = _isYUV ? @"DLGPlayerYUVFragmentShader" : @"DLGPlayerRGBFragmentShader"; + NSString *fragmentShaderFile = [bundle pathForResource:fragmentShaderResource ofType:@"glsl"]; + GLuint fragmentShader = [DLGPlayerView loadShader:GL_FRAGMENT_SHADER withFile:fragmentShaderFile]; + + // Attach shaders + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + } // Bind glBindAttribLocation(program, VERTEX_ATTRIBUTE_POSITION, "position"); diff --git a/DLGPlayer/view/MetalPlayerView.m b/DLGPlayer/view/MetalPlayerView.m index 2bed36d..7b19b2a 100644 --- a/DLGPlayer/view/MetalPlayerView.m +++ b/DLGPlayer/view/MetalPlayerView.m @@ -72,19 +72,17 @@ - (void)layoutSubviews { - (void)setUpPipelineState { NSString *name = _isYUV ? @"YUVColorConversion" : @"RGBColorConversion"; - @autoreleasepool { - id kernelFunction = [defaultLibrary newFunctionWithName:name]; - - if (!kernelFunction && DLGPlayerUtils.debugEnabled) { - NSLog(@"Error creating compute shader"); - return; - } - - pipelineState = [metalView.device newComputePipelineStateWithFunction:kernelFunction error:nil]; - - if (!pipelineState && DLGPlayerUtils.debugEnabled) { - NSLog(@"Error creating the pipeline state"); - } + id kernelFunction = [defaultLibrary newFunctionWithName:name]; + + if (!kernelFunction && DLGPlayerUtils.debugEnabled) { + NSLog(@"Error creating compute shader"); + return; + } + + pipelineState = [metalView.device newComputePipelineStateWithFunction:kernelFunction error:nil]; + + if (!pipelineState && DLGPlayerUtils.debugEnabled) { + NSLog(@"Error creating the pipeline state"); } } @@ -97,28 +95,26 @@ - (void)drawInMTKView:(nonnull MTKView *)view { return; } - @autoreleasepool { - id commandBuffer = [commandQueue commandBuffer]; - - if (!commandBuffer) { - return; - } + id commandBuffer = [commandQueue commandBuffer]; + + if (!commandBuffer) { + return; + } + + id commandEncoder = [commandBuffer computeCommandEncoder]; + + if (commandEncoder) { + float brightness = currentFrame.brightness; - id commandEncoder = [commandBuffer computeCommandEncoder]; + [commandEncoder setComputePipelineState:pipelineState]; + [commandEncoder setBytes:&brightness length:sizeof(brightness) atIndex:0]; + [currentFrame render:commandEncoder]; + [commandEncoder setTexture:metalView.currentDrawable.texture atIndex:3]; + [commandEncoder dispatchThreadgroups:threadgroupsPerGrid threadsPerThreadgroup:threadsPerThreadgroup]; + [commandEncoder endEncoding]; - if (commandEncoder) { - float brightness = currentFrame.brightness; - - [commandEncoder setComputePipelineState:pipelineState]; - [commandEncoder setBytes:&brightness length:sizeof(brightness) atIndex:0]; - [currentFrame render:commandEncoder]; - [commandEncoder setTexture:metalView.currentDrawable.texture atIndex:3]; - [commandEncoder dispatchThreadgroups:threadgroupsPerGrid threadsPerThreadgroup:threadsPerThreadgroup]; - [commandEncoder endEncoding]; - - [commandBuffer presentDrawable:metalView.currentDrawable]; - [commandBuffer commit]; - } + [commandBuffer presentDrawable:metalView.currentDrawable]; + [commandBuffer commit]; } } @@ -142,10 +138,8 @@ - (void)initProperties { commandQueue = [metalView.device newCommandQueue]; if (@available(iOS 10.0, *)) { - @autoreleasepool { - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - defaultLibrary = [metalView.device newDefaultLibraryWithBundle:bundle error:nil]; - } + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + defaultLibrary = [metalView.device newDefaultLibraryWithBundle:bundle error:nil]; } else { defaultLibrary = [metalView.device newDefaultLibrary]; } diff --git a/DLGPlayerDemo/Info.plist b/DLGPlayerDemo/Info.plist index 16be3b6..9671f43 100644 --- a/DLGPlayerDemo/Info.plist +++ b/DLGPlayerDemo/Info.plist @@ -28,6 +28,8 @@ armv7 + UIStatusBarHidden + UISupportedInterfaceOrientations UIInterfaceOrientationPortrait diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 1ef37a3..f3a28c0 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -29,7 +29,7 @@ final class RootViewController: UIViewController { let pv = DLGSimplePlayerViewController() pv.view.translatesAutoresizingMaskIntoConstraints = true pv.delegate = self -// pv.isAllowsFrameDrop = true + pv.isAllowsFrameDrop = true pv.isAutoplay = true // pv.isMute = true pv.preventFromScreenLock = true @@ -49,7 +49,7 @@ final class RootViewController: UIViewController { } private func removePlayers() { players.forEach { - $0.stop() + $0.stopCompletely() $0.removeFromParent() $0.view.removeFromSuperview() } diff --git a/DLGPlayerDemo/ViewController.swift b/DLGPlayerDemo/ViewController.swift index ea8a49d..0de77a0 100644 --- a/DLGPlayerDemo/ViewController.swift +++ b/DLGPlayerDemo/ViewController.swift @@ -18,6 +18,7 @@ class ViewController: UIViewController { super.viewDidLoad() navigationItem.rightBarButtonItem = .init(title: "open", style: .plain, target: self, action: #selector(clicked)) + clicked() } @objc private func clicked() { From 2fa82ea2f9f961ed9a24ab570bfac20be2ee8bdf Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Mon, 25 May 2020 18:21:57 +0900 Subject: [PATCH 206/215] Updated: improvement mute logic. Updated: reduce client delay by frame drop. --- DLGPlayer/DLGPlayer.h | 10 +- DLGPlayer/DLGPlayer.m | 316 +++++++++++++---------- DLGPlayer/codec/DLGPlayerDecoder.h | 4 +- DLGPlayer/codec/DLGPlayerDecoder.m | 116 ++++++--- DLGPlayer/common/DLGPlayerDef.h | 2 +- DLGPlayer/frame/DLGPlayerVideoYUVFrame.m | 2 - DLGPlayerDemo/RootViewController.swift | 8 +- 7 files changed, 265 insertions(+), 193 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 2a0da59..734c791 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -23,26 +23,26 @@ typedef void (^onPauseComplete)(void); @interface DLGPlayer : NSObject -@property (readonly, strong) UIView *playerView; @property (nonatomic) BOOL allowsFrameDrop; @property (nonatomic) BOOL mute; @property (atomic) BOOL playing; @property (atomic) BOOL buffering; @property (atomic) BOOL opened; @property (nonatomic) float brightness; -@property (nonatomic) double frameDropDuration; -@property (nonatomic) double minBufferDuration; -@property (nonatomic) double maxBufferDuration; +@property (atomic) double frameDropDuration; +@property (atomic) double minBufferDuration; +@property (atomic) double maxBufferDuration; @property (nonatomic) double position; @property (nonatomic) double duration; @property (nonatomic) double speed; @property (nonatomic, strong) NSDictionary *metadata; +@property (nonatomic, readonly) UIView *playerView; @property (nonatomic, readonly) DLGPlayerAudioManager *audio; -- (void)open:(NSString *)url; - (void)close; - (void)closeAudio; - (void)closeCompletely; +- (void)open:(NSString *)url; - (void)play; - (void)pause; - (UIImage *)snapshot; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 61dc5d3..d13e063 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -17,10 +17,13 @@ #import "DLGPlayerVideoFrameView.h" #import "MetalPlayerView.h" +#define DLGPlayerFrameDropLimit 0.4 + @interface DLGPlayer () @property (atomic) BOOL closing; @property (atomic) BOOL opening; -@property (nonatomic) BOOL frameDropped; +@property (nonatomic, readonly) BOOL frameDropAvailable; +@property (atomic) BOOL frameDropFinished; @property (nonatomic) BOOL notifiedBufferStart; @property (nonatomic) BOOL renderBegan; @property (nonatomic) BOOL requestSeek; @@ -52,17 +55,17 @@ - (UIView *)playerView { } - (void)setPosition:(double)position { - self.requestSeekPosition = position; - self.requestSeek = YES; + _requestSeekPosition = position; + _requestSeek = YES; } - (double)position { - return self.mediaPosition; + return _mediaPosition; } - (void)setSpeed:(double)speed { _speed = speed; - self.decoder.speed = speed; + _decoder.speed = speed; } - (void)setMute:(BOOL)mute { @@ -71,11 +74,11 @@ - (void)setMute:(BOOL)mute { } _mute = mute; - self.audio.mute = mute; + _audio.mute = mute; __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ + dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf) { @@ -86,15 +89,23 @@ - (void)setMute:(BOOL)mute { if ([strongSelf.audio close]) { [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioClosed object:strongSelf]; } - } else if (self.playing) { - if ([strongSelf.audio open]) { + } else if (strongSelf.playing) { + if (!strongSelf.audio.opened && [strongSelf.audio open]) { + strongSelf.decoder.audioChannels = [strongSelf.audio channels]; + strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; } [strongSelf.audio play]; } + + strongSelf.decoder.mute = mute; }); } +- (BOOL)frameDropAvailable { + return _allowsFrameDrop && !_frameDropFinished; +} + #pragma mark - Con(De)structors - (id)init { @@ -116,7 +127,7 @@ - (void)dealloc { - (void)open:(NSString *)url { __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ + dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || strongSelf.opening || strongSelf.closing) { @@ -180,7 +191,7 @@ - (void)close { - (void)closeAudio { __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ + dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf && [strongSelf.audio close]) { @@ -196,7 +207,7 @@ - (void)closeCompletely { - (void)play { __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ + dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || !strongSelf.opened || strongSelf.playing || strongSelf.closing) { @@ -220,7 +231,7 @@ - (void)play { - (void)pause { __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ + dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf.playing) { @@ -246,6 +257,7 @@ - (void)initAll { - (void)initVars { _allowsFrameDrop = NO; + _frameDropFinished = NO; _requestSeek = NO; _renderBegan = NO; _buffering = NO; @@ -253,7 +265,6 @@ - (void)initVars { _opening = NO; _playing = NO; _opened = NO; - _frameDropped = NO; _frameDropDuration = DLGPlayerFrameDropDuration; _minBufferDuration = DLGPlayerMinBufferDuration; _maxBufferDuration = DLGPlayerMaxBufferDuration; @@ -295,44 +306,44 @@ - (void)initView { } - (void)initDecoder { - self.decoder = [[DLGPlayerDecoder alloc] init]; - self.decoder.speed = self.speed; + _decoder = [[DLGPlayerDecoder alloc] init]; + _decoder.speed = _speed; } - (void)initAudio { - self.audio = [[DLGPlayerAudioManager alloc] init]; + _audio = [[DLGPlayerAudioManager alloc] init]; } - (void)clearVars { { - dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_FOREVER); - [self.vframes removeAllObjects]; - dispatch_semaphore_signal(self.vFramesLock); + dispatch_semaphore_wait(_vFramesLock, DISPATCH_TIME_FOREVER); + [_vframes removeAllObjects]; + dispatch_semaphore_signal(_vFramesLock); } { - dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_FOREVER); - [self.aframes removeAllObjects]; - dispatch_semaphore_signal(self.aFramesLock); + dispatch_semaphore_wait(_aFramesLock, DISPATCH_TIME_FOREVER); + [_aframes removeAllObjects]; + dispatch_semaphore_signal(_aFramesLock); } - self.buffering = NO; - self.closing = NO; - self.frameDropped = NO; - self.opened = NO; - self.opening = NO; - self.playing = NO; - self.renderBegan = NO; - self.bufferedDuration = 0; - self.mediaPosition = 0; - self.mediaSyncTime = 0; - self.playingAudioFrameDataPosition = 0; - self.playingAudioFrame = nil; + _buffering = NO; + _closing = NO; + _frameDropFinished = NO; + _opened = NO; + _opening = NO; + _playing = NO; + _renderBegan = NO; + _bufferedDuration = 0; + _mediaPosition = 0; + _mediaSyncTime = 0; + _playingAudioFrameDataPosition = 0; + _playingAudioFrame = nil; } - (void)close:(BOOL)completely { __weak typeof(self)weakSelf = self; - dispatch_async(self.processingQueue, ^{ + dispatch_async(_processingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf || strongSelf.closing || !strongSelf.opened) { @@ -340,6 +351,7 @@ - (void)close:(BOOL)completely { } strongSelf.closing = YES; + strongSelf.playing = NO; if (completely) { if ([strongSelf.audio close]) { @@ -361,10 +373,10 @@ - (void)close:(BOOL)completely { } - (void)runFrameReader { - while (self.playing && !self.closing) { + while (_playing && !_closing) { [self readFrame]; - if (self.requestSeek) { + if (_requestSeek) { [self seekPositionInFrameReader]; } else { [NSThread sleepForTimeInterval:1.5]; @@ -373,18 +385,17 @@ - (void)runFrameReader { } - (void)readFrame { - self.buffering = YES; - + _buffering = YES; + double tempDuration = 0; - double maxDuration = self.allowsFrameDrop && !self.frameDropped ? self.frameDropDuration : self.maxBufferDuration; - NSMutableArray *tempVFrames = [NSMutableArray arrayWithCapacity:8]; - NSMutableArray *tempAFrames = [NSMutableArray arrayWithCapacity:8]; + NSMutableArray *tempVFrames = [NSMutableArray arrayWithCapacity:15]; + NSMutableArray *tempAFrames = [NSMutableArray arrayWithCapacity:15]; dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); - while (self.playing && !self.closing && !self.decoder.isEOF && !self.requestSeek - && (self.bufferedDuration + tempDuration) < maxDuration) { + while (_playing && !_closing && !_decoder.isEOF && !_requestSeek + && (self.frameDropAvailable || (_bufferedDuration + tempDuration) < _maxBufferDuration)) { @autoreleasepool { - NSArray *fs = [self.decoder readFrames]; + NSArray *fs = [_decoder readFrames]; if (fs == nil) { break; } if (fs.count == 0) { continue; } @@ -395,38 +406,38 @@ - (void)readFrame { tempDuration += f.duration; } - if (!self.mute && f.type == kDLGPlayerFrameTypeAudio) { + if (!_mute && f.type == kDLGPlayerFrameTypeAudio) { [tempAFrames addObject:f]; - if (!self.decoder.hasVideo) { + if (!_decoder.hasVideo) { tempDuration += f.duration; } } } - long timeout = dispatch_semaphore_wait(self.vFramesLock, t); + long timeout = dispatch_semaphore_wait(_vFramesLock, t); if (timeout == 0) { if (tempVFrames.count > 0) { - self.bufferedDuration += tempDuration; + _bufferedDuration += tempDuration; tempDuration = 0; - [self.vframes addObjectsFromArray:tempVFrames]; + [_vframes addObjectsFromArray:tempVFrames]; [tempVFrames removeAllObjects]; } - dispatch_semaphore_signal(self.vFramesLock); + dispatch_semaphore_signal(_vFramesLock); } - if (!self.mute) { - long timeout = dispatch_semaphore_wait(self.aFramesLock, t); + if (!_mute) { + long timeout = dispatch_semaphore_wait(_aFramesLock, t); if (timeout == 0) { if (tempAFrames.count > 0) { - if (!self.decoder.hasVideo) { - self.bufferedDuration += tempDuration; + if (!_decoder.hasVideo) { + _bufferedDuration += tempDuration; tempDuration = 0; } - [self.aframes addObjectsFromArray:tempAFrames]; + [_aframes addObjectsFromArray:tempAFrames]; [tempAFrames removeAllObjects]; } - dispatch_semaphore_signal(self.aFramesLock); + dispatch_semaphore_signal(_aFramesLock); } } } @@ -437,84 +448,101 @@ - (void)readFrame { // add the rest video frames while (tempVFrames.count > 0 || tempAFrames.count > 0) { if (tempVFrames.count > 0) { - long timeout = dispatch_semaphore_wait(self.vFramesLock, t); + long timeout = dispatch_semaphore_wait(_vFramesLock, t); if (timeout == 0) { - self.bufferedDuration += tempDuration; + _bufferedDuration += tempDuration; tempDuration = 0; - [self.vframes addObjectsFromArray:tempVFrames]; + [_vframes addObjectsFromArray:tempVFrames]; [tempVFrames removeAllObjects]; - dispatch_semaphore_signal(self.vFramesLock); + dispatch_semaphore_signal(_vFramesLock); } } if (tempAFrames.count > 0) { - long timeout = dispatch_semaphore_wait(self.aFramesLock, t); + long timeout = dispatch_semaphore_wait(_aFramesLock, t); if (timeout == 0) { - if (!self.decoder.hasVideo) { - self.bufferedDuration += tempDuration; + if (!_decoder.hasVideo) { + _bufferedDuration += tempDuration; tempDuration = 0; } - [self.aframes addObjectsFromArray:tempAFrames]; + [_aframes addObjectsFromArray:tempAFrames]; [tempAFrames removeAllObjects]; - dispatch_semaphore_signal(self.aFramesLock); + dispatch_semaphore_signal(_aFramesLock); } } [self dropFrames]; } } - self.buffering = NO; + _buffering = NO; } - (void)dropFrames { - if (self.allowsFrameDrop && !self.frameDropped && self.bufferedDuration > self.frameDropDuration / self.speed) { - if (dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_NOW) == 0) { - for (DLGPlayerFrame *f in self.vframes) { + if (!_allowsFrameDrop) + return; + + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"_bufferedDuration -> %f", _bufferedDuration); + } + + if (!_frameDropFinished && _bufferedDuration > _frameDropDuration / _speed) { + if (dispatch_semaphore_wait(_vFramesLock, DISPATCH_TIME_NOW) == 0) { + for (DLGPlayerFrame *f in _vframes) { f.dropFrame = YES; } - dispatch_semaphore_signal(self.vFramesLock); + dispatch_semaphore_signal(_vFramesLock); } - if (dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW) == 0) { - for (DLGPlayerFrame *f in self.aframes) { + if (dispatch_semaphore_wait(_aFramesLock, DISPATCH_TIME_NOW) == 0) { + for (DLGPlayerFrame *f in _aframes) { f.dropFrame = YES; } - dispatch_semaphore_signal(self.aFramesLock); + dispatch_semaphore_signal(_aFramesLock); } - self.frameDropped = YES; - if (DLGPlayerUtils.debugEnabled) { NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); } } } +- (void)resetFrameDropFlag { + if (!_allowsFrameDrop) + return; + + if (!_frameDropFinished && _bufferedDuration < DLGPlayerFrameDropLimit / _speed) { + _frameDropFinished = YES; + } else if (_frameDropFinished && _bufferedDuration > _frameDropDuration / _speed) { + _frameDropFinished = NO; + } +} + - (void)seekPositionInFrameReader { - [self.decoder seek:self.requestSeekPosition]; + [_decoder seek:_requestSeekPosition]; { - dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_FOREVER); - [self.vframes removeAllObjects]; - dispatch_semaphore_signal(self.vFramesLock); + dispatch_semaphore_wait(_vFramesLock, DISPATCH_TIME_FOREVER); + [_vframes removeAllObjects]; + dispatch_semaphore_signal(_vFramesLock); } { - dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_FOREVER); - [self.aframes removeAllObjects]; - dispatch_semaphore_signal(self.aFramesLock); + dispatch_semaphore_wait(_aFramesLock, DISPATCH_TIME_FOREVER); + [_aframes removeAllObjects]; + dispatch_semaphore_signal(_aFramesLock); } - self.bufferedDuration = 0; - self.requestSeek = NO; - self.mediaSyncTime = 0; - self.mediaPosition = self.requestSeekPosition; + _bufferedDuration = 0; + _requestSeek = NO; + _mediaSyncTime = 0; + _mediaPosition = _requestSeekPosition; } - (void)render { - if (!self.playing) return; + if (!_playing) + return; - BOOL eof = self.decoder.isEOF; - BOOL noframes = ((self.decoder.hasVideo && self.vframes.count <= 0) && - (self.decoder.hasAudio && self.aframes.count <= 0)); + BOOL eof = _decoder.isEOF; + BOOL noframes = ((_decoder.hasVideo && _vframes.count <= 0) && + (_decoder.hasAudio && _aframes.count <= 0)); // Check if reach the end and play all frames. if (noframes && eof) { @@ -523,31 +551,31 @@ - (void)render { return; } - if (noframes && !self.notifiedBufferStart) { - self.notifiedBufferStart = YES; - NSDictionary *userInfo = @{DLGPlayerNotificationBufferStateKey: @(self.notifiedBufferStart)}; + if (noframes && !_notifiedBufferStart) { + _notifiedBufferStart = YES; + NSDictionary *userInfo = @{DLGPlayerNotificationBufferStateKey: @(_notifiedBufferStart)}; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationBufferStateChanged object:self userInfo:userInfo]; - } else if (!noframes && self.notifiedBufferStart && self.bufferedDuration >= self.minBufferDuration / self.speed) { - self.notifiedBufferStart = NO; - NSDictionary *userInfo = @{DLGPlayerNotificationBufferStateKey: @(self.notifiedBufferStart)}; + } else if (!noframes && _notifiedBufferStart && _bufferedDuration >= _minBufferDuration / _speed) { + _notifiedBufferStart = NO; + NSDictionary *userInfo = @{DLGPlayerNotificationBufferStateKey: @(_notifiedBufferStart)}; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationBufferStateChanged object:self userInfo:userInfo]; } // Render if has picture - if (self.decoder.hasPicture && self.vframes.count > 0) { - DLGPlayerVideoFrame *frame = self.vframes[0]; + if (_decoder.hasPicture && _vframes.count > 0) { + DLGPlayerVideoFrame *frame = _vframes[0]; frame.brightness = _brightness; _view.contentSize = CGSizeMake(frame.width, frame.height); - if (dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_NOW) == 0) { - [self.vframes removeObjectAtIndex:0]; - dispatch_semaphore_signal(self.vFramesLock); + if (dispatch_semaphore_wait(_vFramesLock, DISPATCH_TIME_NOW) == 0) { + [_vframes removeObjectAtIndex:0]; + dispatch_semaphore_signal(_vFramesLock); [self renderView:frame]; } } // Check whether render is neccessary - if (self.vframes.count <= 0 || !self.decoder.hasVideo || self.notifiedBufferStart) { + if (_vframes.count <= 0 || !_decoder.hasVideo || _notifiedBufferStart) { __weak typeof(self)weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf render]; @@ -558,25 +586,27 @@ - (void)render { // Render video DLGPlayerVideoFrame *frame = nil; { - if (dispatch_semaphore_wait(self.vFramesLock, DISPATCH_TIME_NOW) == 0) { - frame = self.vframes[0]; - [self.vframes removeObjectAtIndex:0]; + if (dispatch_semaphore_wait(_vFramesLock, DISPATCH_TIME_NOW) == 0) { + frame = _vframes[0]; + [_vframes removeObjectAtIndex:0]; frame.brightness = _brightness; - self.mediaPosition = frame.position; - self.bufferedDuration -= frame.duration; - dispatch_semaphore_signal(self.vFramesLock); + _mediaPosition = frame.position; + _bufferedDuration -= frame.duration; + dispatch_semaphore_signal(_vFramesLock); } } - + [self renderView:frame]; NSTimeInterval t; - if (self.speed > 1) { + if (_speed > 1) { t = frame.duration; } else { t = frame.dropFrame ? 0.01 : MAX(frame.duration + [self syncTime], 0.01); } + [self resetFrameDropFlag]; + __weak typeof(self)weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (t * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf render]; @@ -586,7 +616,7 @@ - (void)render { - (void)renderView:(DLGPlayerVideoFrame *)frame { __weak typeof(self)weakSelf = self; - dispatch_sync(self.renderingQueue, ^{ + dispatch_sync(_renderingQueue, ^{ __strong typeof(weakSelf)strongSelf = weakSelf; if (!strongSelf) { @@ -605,19 +635,19 @@ - (void)renderView:(DLGPlayerVideoFrame *)frame { - (double)syncTime { const double now = [NSDate timeIntervalSinceReferenceDate]; - if (self.mediaSyncTime == 0) { - self.mediaSyncTime = now; - self.mediaSyncPosition = self.mediaPosition; + if (_mediaSyncTime == 0) { + _mediaSyncTime = now; + _mediaSyncPosition = _mediaPosition; return 0; } - double dp = self.mediaPosition - self.mediaSyncPosition; - double dt = now - self.mediaSyncTime; + double dp = _mediaPosition - _mediaSyncPosition; + double dt = now - _mediaSyncTime; double sync = dp - dt; if (sync > 1 || sync < -1) { sync = 0; - self.mediaSyncTime = 0; + _mediaSyncTime = 0; } return sync; @@ -627,55 +657,55 @@ - (double)syncTime { * For audioUnitRenderCallback, (DLGPlayerAudioManagerFrameReaderBlock)readFrameBlock */ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)channels { - if (!self.playing) { + if (!_playing) { return; } while(frames > 0) { @autoreleasepool { - if (self.playingAudioFrame == nil) { + if (_playingAudioFrame == nil) { { - if (self.aframes.count <= 0) { + if (_aframes.count <= 0) { memset(data, 0, frames * channels * sizeof(float)); return; } - long timeout = dispatch_semaphore_wait(self.aFramesLock, DISPATCH_TIME_NOW); + long timeout = dispatch_semaphore_wait(_aFramesLock, DISPATCH_TIME_NOW); if (timeout == 0) { @autoreleasepool { - DLGPlayerAudioFrame *frame = self.aframes[0]; + DLGPlayerAudioFrame *frame = _aframes[0]; - if (self.decoder.hasVideo) { - const double dt = self.mediaPosition - frame.position; + if (_decoder.hasVideo) { + const double dt = _mediaPosition - frame.position; - if (dt < -0.1 && self.vframes.count > 0) { // audio is faster than video, silence + if (dt < -0.1 && _vframes.count > 0) { // audio is faster than video, silence memset(data, 0, frames * channels * sizeof(float)); - dispatch_semaphore_signal(self.aFramesLock); + dispatch_semaphore_signal(_aFramesLock); break; } else if (dt > 0.1) { // audio is slower than video, skip - [self.aframes removeObjectAtIndex:0]; - dispatch_semaphore_signal(self.aFramesLock); + [_aframes removeObjectAtIndex:0]; + dispatch_semaphore_signal(_aFramesLock); continue; } else { - self.playingAudioFrameDataPosition = 0; - self.playingAudioFrame = frame; - [self.aframes removeObjectAtIndex:0]; + _playingAudioFrameDataPosition = 0; + _playingAudioFrame = frame; + [_aframes removeObjectAtIndex:0]; } } else { - self.playingAudioFrameDataPosition = 0; - self.playingAudioFrame = frame; - [self.aframes removeObjectAtIndex:0]; - self.mediaPosition = frame.position; - self.bufferedDuration -= frame.duration; + _playingAudioFrameDataPosition = 0; + _playingAudioFrame = frame; + [_aframes removeObjectAtIndex:0]; + _mediaPosition = frame.position; + _bufferedDuration -= frame.duration; } } - dispatch_semaphore_signal(self.aFramesLock); + dispatch_semaphore_signal(_aFramesLock); } else return; } } - NSData *frameData = self.playingAudioFrame.data; - NSUInteger pos = self.playingAudioFrameDataPosition; + NSData *frameData = _playingAudioFrame.data; + NSUInteger pos = _playingAudioFrameDataPosition; if (frameData == nil) { memset(data, 0, frames * channels * sizeof(float)); return; @@ -692,9 +722,9 @@ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)chan data += framesToCopy * channels; if (bytesToCopy < remainingBytes) { - self.playingAudioFrameDataPosition += bytesToCopy; + _playingAudioFrameDataPosition += bytesToCopy; } else { - self.playingAudioFrame = nil; + _playingAudioFrame = nil; } } } diff --git a/DLGPlayer/codec/DLGPlayerDecoder.h b/DLGPlayer/codec/DLGPlayerDecoder.h index 63483fc..c498fe3 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.h +++ b/DLGPlayer/codec/DLGPlayerDecoder.h @@ -15,6 +15,7 @@ @property (nonatomic) BOOL hasPicture; @property (nonatomic) BOOL isEOF; @property (nonatomic) BOOL isYUV; +@property (nonatomic) BOOL mute; @property (nonatomic) double rotation; @property (nonatomic) double duration; @@ -28,13 +29,12 @@ @property (nonatomic) double videoTimebase; @property (nonatomic) double audioTimebase; -- (BOOL)open:(NSString *)url error:(NSError **)error; - (void)close; - (void)prepareClose; - (NSArray *)readFrames; +- (BOOL)open:(NSString *)url error:(NSError **)error; - (void)seek:(double)position; - (int)videoWidth; - (int)videoHeight; -- (BOOL)isYUV; @end diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index ccad36a..d219ed4 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -59,6 +59,15 @@ @interface DLGPlayerDecoder () { @implementation DLGPlayerDecoder +- (void)setMute:(BOOL)mute { + if (mute == _mute) + return; + + _mute = mute; + + [self setAudioSwrContext]; +} + - (void)dealloc { if (DLGPlayerUtils.debugEnabled) { NSLog(@"DLGPlayerDecoder dealloc"); @@ -152,26 +161,29 @@ - (BOOL)open:(NSString *)url error:(NSError **)error { astream = -1; if (acodectx != NULL) avcodec_free_context(&acodectx); } - aswrctx = swr_alloc_set_opts(NULL, - av_get_default_channel_layout(_audioChannels), - AV_SAMPLE_FMT_S16, - _audioSampleRate, - av_get_default_channel_layout(acodectx->channels), - acodectx->sample_fmt, - acodectx->sample_rate, - 0, - NULL); - if (aswrctx == NULL) { - astream = -1; - if (acodectx != NULL) avcodec_free_context(&acodectx); - if (aframe != NULL) av_frame_free(&aframe); - } else { - ret = swr_init(aswrctx); - if (ret < 0) { + + if (!_mute) { + aswrctx = swr_alloc_set_opts(NULL, + av_get_default_channel_layout(_audioChannels), + AV_SAMPLE_FMT_S16, + _audioSampleRate, + av_get_default_channel_layout(acodectx->channels), + acodectx->sample_fmt, + acodectx->sample_rate, + 0, + NULL); + if (aswrctx == NULL) { astream = -1; - if (aswrctx != NULL) swr_free(&aswrctx); if (acodectx != NULL) avcodec_free_context(&acodectx); if (aframe != NULL) av_frame_free(&aframe); + } else { + ret = swr_init(aswrctx); + if (ret < 0) { + astream = -1; + if (aswrctx != NULL) swr_free(&aswrctx); + if (acodectx != NULL) avcodec_free_context(&acodectx); + if (aframe != NULL) av_frame_free(&aframe); + } } } } @@ -201,17 +213,17 @@ - (BOOL)open:(NSString *)url error:(NSError **)error { ptsPrevAudio = 0; ptsPrevVideo = 0; - self.isYUV = isYUV; - self.hasVideo = vstream >= 0; - self.hasAudio = astream >= 0; - self.hasPicture = picstream >= 0; - self.isEOF = NO; + _isYUV = isYUV; + _hasVideo = vstream >= 0; + _hasAudio = astream >= 0; + _hasPicture = picstream >= 0; + _isEOF = NO; - self.rotation = rotation; + _rotation = rotation; int64_t duration = fmtctx->duration; - self.duration = (duration == AV_NOPTS_VALUE ? -1 : ((double)duration / AV_TIME_BASE)); - self.duration /= _speed; - self.metadata = [self findMetadata:fmtctx]; + _duration = (duration == AV_NOPTS_VALUE ? -1 : ((double)duration / AV_TIME_BASE)); + _duration /= _speed; + _metadata = [self findMetadata:fmtctx]; g_bPrepareClose = FALSE; AVIOInterruptCB icb = {interruptCallback, NULL}; @@ -220,6 +232,39 @@ - (BOOL)open:(NSString *)url error:(NSError **)error { return YES; } +- (void)setAudioSwrContext { + if (m_pAudioSwrContext || !m_pAudioCodecContext || _mute) + return; + + int ret; + SwrContext *aswrctx = NULL; + + aswrctx = swr_alloc_set_opts(NULL, + av_get_default_channel_layout(_audioChannels), + AV_SAMPLE_FMT_S16, + _audioSampleRate, + av_get_default_channel_layout(m_pAudioCodecContext->channels), + m_pAudioCodecContext->sample_fmt, + m_pAudioCodecContext->sample_rate, + 0, + NULL); + if (aswrctx == NULL) { + m_nAudioStream = -1; + if (m_pAudioCodecContext != NULL) avcodec_free_context(&m_pAudioCodecContext); + if (m_pAudioFrame != NULL) av_frame_free(&m_pAudioFrame); + } else { + ret = swr_init(aswrctx); + if (ret < 0) { + m_nAudioStream = -1; + if (aswrctx != NULL) swr_free(&m_pAudioSwrContext); + if (m_pAudioCodecContext != NULL) avcodec_free_context(&m_pAudioCodecContext); + if (m_pAudioFrame != NULL) av_frame_free(&m_pAudioFrame); + } + } + + m_pAudioSwrContext = aswrctx; +} + - (NSDictionary *)findMetadata:(AVFormatContext *)fmtctx { if (fmtctx == NULL || fmtctx->metadata == NULL) return nil; @@ -338,11 +383,11 @@ - (void)close { [self closePictureStream]; if (m_pFormatContext != NULL) avformat_close_input(&m_pFormatContext); avformat_network_deinit(); - self.isYUV = NO; - self.hasVideo = NO; - self.hasAudio = NO; - self.hasPicture = NO; - self.isEOF = NO; + _isYUV = NO; + _hasVideo = NO; + _hasAudio = NO; + _hasPicture = NO; + _isEOF = NO; } - (void)closeVideoStream { @@ -375,7 +420,7 @@ - (void)flush:(AVCodecContext *)codectx frame:(AVFrame *)frame { #pragma mark - Handle Frames - (NSArray *)readFrames { - if ((m_nVideoStream < 0 && m_nAudioStream < 0) || self.isEOF) { + if ((m_nVideoStream < 0 && m_nAudioStream < 0) || _isEOF) { return nil; } @@ -402,9 +447,9 @@ - (NSArray *)readFrames { g_dIOStartTime = [NSDate timeIntervalSinceReferenceDate]; int ret = av_read_frame(fmtctx, &packet); if (ret < 0) { - if (ret == AVERROR_EOF) self.isEOF = YES; - char *e = av_err2str(ret); + if (ret == AVERROR_EOF) _isEOF = YES; if (DLGPlayerUtils.debugEnabled) { + char *e = av_err2str(ret); NSLog(@"DLGPlayer read frame error: %s", e); } break; @@ -554,7 +599,7 @@ - (NSArray *)readFrames { f.height = height; f.position = frame->best_effort_timestamp * _videoTimebase; - double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevVideo; + double duration = frame->pts - ptsPrevVideo; if (duration > 0) { f.duration = duration * _videoTimebase / _speed; @@ -650,7 +695,6 @@ - (NSArray *)readFrames { f.data = mdata; f.position = frame->best_effort_timestamp * _audioTimebase; - double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevAudio; if (duration > 0) { diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index 7e91686..7582aa4 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -11,7 +11,7 @@ #define DLGPlayerLocalizedStringTable @"DLGPlayerStrings" -#define DLGPlayerFrameDropDuration 4 +#define DLGPlayerFrameDropDuration 1.2 #define DLGPlayerMinBufferDuration 1 #define DLGPlayerMaxBufferDuration 5 diff --git a/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m b/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m index c25d958..053e04b 100644 --- a/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m +++ b/DLGPlayer/frame/DLGPlayerVideoYUVFrame.m @@ -98,8 +98,6 @@ - (BOOL)prepareProgram:(GLuint)program { glUniform1f(glGetUniformLocation(program, "f_brightness"), self.brightness); - free(data); - return YES; } diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index f3a28c0..eb09803 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -31,7 +31,7 @@ final class RootViewController: UIViewController { pv.delegate = self pv.isAllowsFrameDrop = true pv.isAutoplay = true -// pv.isMute = true + pv.isMute = true pv.preventFromScreenLock = true pv.restorePlayAfterAppEnterForeground = true pv.minBufferDuration = 0 @@ -57,8 +57,8 @@ final class RootViewController: UIViewController { } private func playAll() { players.forEach { - $0.url = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" -// $0.url = "rtmps://devmedia010.toastcam.com:10082/flvplayback/AAAAAADIQF?token=b6e503e4-f47c-4238-baca-51cbdfc10001" +// $0.url = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4" + $0.url = "rtmps://devmedia011.toastcam.com:10082/flvplayback/AAAAAADJMO?token=b6e503e4-f47c-4238-baca-51cbdfc10001" $0.open() } } @@ -114,7 +114,7 @@ final class RootViewController: UIViewController { } @IBAction private func muteButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected -// playerViewController?.isMute = !sender.isSelected + players.first?.isMute = !sender.isSelected } @IBAction private func playOrPauseButtonClicked(_ sender: UIButton) { sender.isSelected = !sender.isSelected From 3c7559d284f4ca2945e31dea15a1a737cad26a70 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Tue, 26 May 2020 11:44:26 +0900 Subject: [PATCH 207/215] Updated: add skip logic for dropped frame of audio. --- DLGPlayer/DLGPlayer.m | 90 +++++++++++++++----------- DLGPlayerDemo/RootViewController.swift | 7 +- 2 files changed, 55 insertions(+), 42 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index d13e063..fc55507 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -24,6 +24,7 @@ @interface DLGPlayer () @property (atomic) BOOL opening; @property (nonatomic, readonly) BOOL frameDropAvailable; @property (atomic) BOOL frameDropFinished; +@property (atomic) BOOL frameDropStarted; @property (nonatomic) BOOL notifiedBufferStart; @property (nonatomic) BOOL renderBegan; @property (nonatomic) BOOL requestSeek; @@ -141,45 +142,47 @@ - (void)open:(NSString *)url { strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; } - - NSError *error = nil; - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - [strongSelf handleError:error]; - return; - } - dispatch_async(dispatch_get_main_queue(), ^{ - if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { - DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; - [view setCurrentEAGLContext]; + dispatch_async(strongSelf.frameReaderQueue, ^{ + NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + [strongSelf handleError:error]; + return; } - strongSelf.view.isYUV = [strongSelf.decoder isYUV]; - strongSelf.view.keepLastFrame = [strongSelf.decoder hasPicture] && ![strongSelf.decoder hasVideo]; - strongSelf.view.rotation = strongSelf.decoder.rotation; - strongSelf.view.contentSize = CGSizeMake([strongSelf.decoder videoWidth], [strongSelf.decoder videoHeight]); + dispatch_async(dispatch_get_main_queue(), ^{ + if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { + DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; + [view setCurrentEAGLContext]; + } - if ([strongSelf.view isKindOfClass:[UIView class]]) { - ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; - } - - strongSelf.duration = strongSelf.decoder.duration; - strongSelf.metadata = strongSelf.decoder.metadata; - strongSelf.opening = NO; - strongSelf.buffering = NO; - strongSelf.playing = NO; - strongSelf.bufferedDuration = 0; - strongSelf.mediaPosition = 0; - strongSelf.mediaSyncTime = 0; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - - strongSelf.opened = YES; - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; + strongSelf.view.isYUV = strongSelf.decoder.isYUV; + strongSelf.view.keepLastFrame = strongSelf.decoder.hasPicture && !strongSelf.decoder.hasVideo; + strongSelf.view.rotation = strongSelf.decoder.rotation; + strongSelf.view.contentSize = CGSizeMake(strongSelf.decoder.videoWidth, strongSelf.decoder.videoHeight); + + if ([strongSelf.view isKindOfClass:[UIView class]]) { + ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; + } + + strongSelf.duration = strongSelf.decoder.duration; + strongSelf.metadata = strongSelf.decoder.metadata; + strongSelf.opening = NO; + strongSelf.buffering = NO; + strongSelf.playing = NO; + strongSelf.bufferedDuration = 0; + strongSelf.mediaPosition = 0; + strongSelf.mediaSyncTime = 0; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + + strongSelf.opened = YES; + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; + }); }); }); } @@ -258,6 +261,7 @@ - (void)initAll { - (void)initVars { _allowsFrameDrop = NO; _frameDropFinished = NO; + _frameDropStarted = NO; _requestSeek = NO; _renderBegan = NO; _buffering = NO; @@ -329,6 +333,7 @@ - (void)clearVars { _buffering = NO; _closing = NO; _frameDropFinished = NO; + _frameDropStarted = NO; _opened = NO; _opening = NO; _playing = NO; @@ -485,6 +490,8 @@ - (void)dropFrames { } if (!_frameDropFinished && _bufferedDuration > _frameDropDuration / _speed) { + _frameDropStarted = YES; + if (dispatch_semaphore_wait(_vFramesLock, DISPATCH_TIME_NOW) == 0) { for (DLGPlayerFrame *f in _vframes) { f.dropFrame = YES; @@ -509,9 +516,10 @@ - (void)resetFrameDropFlag { if (!_allowsFrameDrop) return; - if (!_frameDropFinished && _bufferedDuration < DLGPlayerFrameDropLimit / _speed) { + if (_frameDropStarted && _bufferedDuration < DLGPlayerFrameDropLimit / _speed) { + _frameDropStarted = NO; _frameDropFinished = YES; - } else if (_frameDropFinished && _bufferedDuration > _frameDropDuration / _speed) { + } else if (_frameDropFinished && _bufferedDuration > _maxBufferDuration / _speed) { _frameDropFinished = NO; } } @@ -604,7 +612,7 @@ - (void)render { } else { t = frame.dropFrame ? 0.01 : MAX(frame.duration + [self syncTime], 0.01); } - + [self resetFrameDropFlag]; __weak typeof(self)weakSelf = self; @@ -675,6 +683,12 @@ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)chan @autoreleasepool { DLGPlayerAudioFrame *frame = _aframes[0]; + if (frame.dropFrame) { + [_aframes removeObjectAtIndex:0]; + dispatch_semaphore_signal(_aFramesLock); + continue; + } + if (_decoder.hasVideo) { const double dt = _mediaPosition - frame.position; diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index eb09803..6ce0427 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -31,7 +31,7 @@ final class RootViewController: UIViewController { pv.delegate = self pv.isAllowsFrameDrop = true pv.isAutoplay = true - pv.isMute = true +// pv.isMute = true pv.preventFromScreenLock = true pv.restorePlayAfterAppEnterForeground = true pv.minBufferDuration = 0 @@ -71,12 +71,11 @@ final class RootViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() + DLGPlayerUtils.setDebugEnabled(true) + for i in 0.. Date: Thu, 28 May 2020 18:39:58 +0900 Subject: [PATCH 208/215] Updated: change frame drop logic. Updated: ffmpeg and speex are allows to enable bitcode. --- Carthage.xcconfig | 2 + DLGPlayer/DLGPlayer.m | 110 ++++++++++--------------- DLGPlayer/codec/DLGPlayerDecoder.m | 2 +- DLGPlayer/common/DLGPlayerDef.h | 2 +- DLGPlayerDemo/RootViewController.swift | 2 +- libs/build.sh | 2 +- libs/tools/do-compile-ogg.sh | 10 +-- libs/tools/do-compile-speex.sh | 11 ++- 8 files changed, 60 insertions(+), 81 deletions(-) diff --git a/Carthage.xcconfig b/Carthage.xcconfig index 812885a..22945b3 100644 --- a/Carthage.xcconfig +++ b/Carthage.xcconfig @@ -1 +1,3 @@ ONLY_ACTIVE_ARCH = YES +ENABLE_BITCODE = YES +OTHER_CFLAGS = "-fembed-bitcode" diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index fc55507..827330e 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -22,13 +22,11 @@ @interface DLGPlayer () @property (atomic) BOOL closing; @property (atomic) BOOL opening; -@property (nonatomic, readonly) BOOL frameDropAvailable; -@property (atomic) BOOL frameDropFinished; -@property (atomic) BOOL frameDropStarted; +@property (atomic) BOOL frameDropEnabled; @property (nonatomic) BOOL notifiedBufferStart; @property (nonatomic) BOOL renderBegan; @property (nonatomic) BOOL requestSeek; -@property (nonatomic) double bufferedDuration; +@property (atomic) double bufferedDuration; @property (nonatomic) double mediaPosition; @property (nonatomic) double mediaSyncPosition; @property (nonatomic) double mediaSyncTime; @@ -103,10 +101,6 @@ - (void)setMute:(BOOL)mute { }); } -- (BOOL)frameDropAvailable { - return _allowsFrameDrop && !_frameDropFinished; -} - #pragma mark - Con(De)structors - (id)init { @@ -181,6 +175,11 @@ - (void)open:(NSString *)url { }; strongSelf.opened = YES; + + if (strongSelf.allowsFrameDrop) { + strongSelf.frameDropEnabled = YES; + } + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; }); }); @@ -260,8 +259,7 @@ - (void)initAll { - (void)initVars { _allowsFrameDrop = NO; - _frameDropFinished = NO; - _frameDropStarted = NO; + _frameDropEnabled = NO; _requestSeek = NO; _renderBegan = NO; _buffering = NO; @@ -332,8 +330,7 @@ - (void)clearVars { _buffering = NO; _closing = NO; - _frameDropFinished = NO; - _frameDropStarted = NO; + _frameDropEnabled = NO; _opened = NO; _opening = NO; _playing = NO; @@ -393,12 +390,17 @@ - (void)readFrame { _buffering = YES; double tempDuration = 0; + double droppedDuration = 0; NSMutableArray *tempVFrames = [NSMutableArray arrayWithCapacity:15]; NSMutableArray *tempAFrames = [NSMutableArray arrayWithCapacity:15]; dispatch_time_t t = dispatch_time(DISPATCH_TIME_NOW, 0.02 * NSEC_PER_SEC); + if (DLGPlayerUtils.debugEnabled && _frameDropEnabled) { + NSLog(@"DLGPlayer fram drop began!"); + } + while (_playing && !_closing && !_decoder.isEOF && !_requestSeek - && (self.frameDropAvailable || (_bufferedDuration + tempDuration) < _maxBufferDuration)) { + && (_frameDropEnabled || (_bufferedDuration + tempDuration) < _maxBufferDuration)) { @autoreleasepool { NSArray *fs = [_decoder readFrames]; @@ -407,18 +409,27 @@ - (void)readFrame { for (DLGPlayerFrame *f in fs) { if (f.type == kDLGPlayerFrameTypeVideo) { + if (_frameDropEnabled) { + f.dropFrame = YES; + droppedDuration += f.duration; + } + [tempVFrames addObject:f]; tempDuration += f.duration; } if (!_mute && f.type == kDLGPlayerFrameTypeAudio) { - [tempAFrames addObject:f]; if (!_decoder.hasVideo) { + if (_frameDropEnabled) { + f.dropFrame = YES; + droppedDuration += f.duration; + } tempDuration += f.duration; } + [tempAFrames addObject:f]; } } - + long timeout = dispatch_semaphore_wait(_vFramesLock, t); if (timeout == 0) { if (tempVFrames.count > 0) { @@ -446,7 +457,19 @@ - (void)readFrame { } } } - [self dropFrames]; + + if (DLGPlayerUtils.debugEnabled && _frameDropEnabled) { + NSLog(@"_bufferedDuration -> %f", _bufferedDuration); + } + + if (_frameDropEnabled && droppedDuration > _frameDropDuration) { + _frameDropEnabled = NO; + droppedDuration = 0; + + if (DLGPlayerUtils.debugEnabled) { + NSLog(@"DLGPlayer fram drop ended!"); + } + } } { @@ -474,56 +497,12 @@ - (void)readFrame { dispatch_semaphore_signal(_aFramesLock); } } - [self dropFrames]; } } _buffering = NO; } -- (void)dropFrames { - if (!_allowsFrameDrop) - return; - - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"_bufferedDuration -> %f", _bufferedDuration); - } - - if (!_frameDropFinished && _bufferedDuration > _frameDropDuration / _speed) { - _frameDropStarted = YES; - - if (dispatch_semaphore_wait(_vFramesLock, DISPATCH_TIME_NOW) == 0) { - for (DLGPlayerFrame *f in _vframes) { - f.dropFrame = YES; - } - dispatch_semaphore_signal(_vFramesLock); - } - - if (dispatch_semaphore_wait(_aFramesLock, DISPATCH_TIME_NOW) == 0) { - for (DLGPlayerFrame *f in _aframes) { - f.dropFrame = YES; - } - dispatch_semaphore_signal(_aFramesLock); - } - - if (DLGPlayerUtils.debugEnabled) { - NSLog(@"DLGPlayer occurred drop frames beacuse buffer duration is over than frame drop duration."); - } - } -} - -- (void)resetFrameDropFlag { - if (!_allowsFrameDrop) - return; - - if (_frameDropStarted && _bufferedDuration < DLGPlayerFrameDropLimit / _speed) { - _frameDropStarted = NO; - _frameDropFinished = YES; - } else if (_frameDropFinished && _bufferedDuration > _maxBufferDuration / _speed) { - _frameDropFinished = NO; - } -} - - (void)seekPositionInFrameReader { [_decoder seek:_requestSeekPosition]; @@ -596,24 +575,23 @@ - (void)render { { if (dispatch_semaphore_wait(_vFramesLock, DISPATCH_TIME_NOW) == 0) { frame = _vframes[0]; - [_vframes removeObjectAtIndex:0]; frame.brightness = _brightness; _mediaPosition = frame.position; _bufferedDuration -= frame.duration; + [_vframes removeObjectAtIndex:0]; dispatch_semaphore_signal(_vFramesLock); } } [self renderView:frame]; + double syncTime = [self syncTime]; NSTimeInterval t; if (_speed > 1) { t = frame.duration; } else { - t = frame.dropFrame ? 0.01 : MAX(frame.duration + [self syncTime], 0.01); + t = frame.dropFrame ? 0.01 : MAX(frame.duration + syncTime, 0.01); } - - [self resetFrameDropFlag]; __weak typeof(self)weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t) (t * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ @@ -682,7 +660,7 @@ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)chan if (timeout == 0) { @autoreleasepool { DLGPlayerAudioFrame *frame = _aframes[0]; - + if (frame.dropFrame) { [_aframes removeObjectAtIndex:0]; dispatch_semaphore_signal(_aFramesLock); @@ -692,7 +670,7 @@ - (void)readAudioFrame:(float *)data frames:(UInt32)frames channels:(UInt32)chan if (_decoder.hasVideo) { const double dt = _mediaPosition - frame.position; - if (dt < -0.1 && _vframes.count > 0) { // audio is faster than video, silence + if (dt < -0.1) { // audio is faster than video, silence memset(data, 0, frames * channels * sizeof(float)); dispatch_semaphore_signal(_aFramesLock); break; diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index d219ed4..fd7401e 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -599,7 +599,7 @@ - (NSArray *)readFrames { f.height = height; f.position = frame->best_effort_timestamp * _videoTimebase; - double duration = frame->pts - ptsPrevVideo; + double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevVideo; if (duration > 0) { f.duration = duration * _videoTimebase / _speed; diff --git a/DLGPlayer/common/DLGPlayerDef.h b/DLGPlayer/common/DLGPlayerDef.h index 7582aa4..7e91686 100644 --- a/DLGPlayer/common/DLGPlayerDef.h +++ b/DLGPlayer/common/DLGPlayerDef.h @@ -11,7 +11,7 @@ #define DLGPlayerLocalizedStringTable @"DLGPlayerStrings" -#define DLGPlayerFrameDropDuration 1.2 +#define DLGPlayerFrameDropDuration 4 #define DLGPlayerMinBufferDuration 1 #define DLGPlayerMaxBufferDuration 5 diff --git a/DLGPlayerDemo/RootViewController.swift b/DLGPlayerDemo/RootViewController.swift index 6ce0427..fce6e0a 100644 --- a/DLGPlayerDemo/RootViewController.swift +++ b/DLGPlayerDemo/RootViewController.swift @@ -35,7 +35,7 @@ final class RootViewController: UIViewController { pv.preventFromScreenLock = true pv.restorePlayAfterAppEnterForeground = true pv.minBufferDuration = 0 - pv.maxBufferDuration = 3 + pv.maxBufferDuration = 5 pv.view.backgroundColor = .red addChild(pv) diff --git a/libs/build.sh b/libs/build.sh index d37b2f2..5efe93a 100755 --- a/libs/build.sh +++ b/libs/build.sh @@ -50,7 +50,7 @@ function buildTargets() { if [ ! $TARGETS ] then - buildTargets "ogg speex ffmpeg" + buildTargets "speex ffmpeg" else buildTargets $TARGETS fi diff --git a/libs/tools/do-compile-ogg.sh b/libs/tools/do-compile-ogg.sh index 6313d35..bfb1531 100755 --- a/libs/tools/do-compile-ogg.sh +++ b/libs/tools/do-compile-ogg.sh @@ -89,25 +89,25 @@ FF_GASPP_EXPORT= if [ "$FF_ARCH" = "i386" ]; then FF_BUILD_NAME="ogg/i386" FF_XCRUN_PLATFORM="iPhoneSimulator" - FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0 -fembed-bitcode" OGG_CFG_FLAGS="$OGG_CFG_FLAGS_SIMULATOR $OGG_CFG_FLAGS" elif [ "$FF_ARCH" = "x86_64" ]; then FF_BUILD_NAME="ogg/x86_64" FF_XCRUN_PLATFORM="iPhoneSimulator" - FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0 -fembed-bitcode" OGG_CFG_FLAGS="$OGG_CFG_FLAGS_SIMULATOR $OGG_CFG_FLAGS" elif [ "$FF_ARCH" = "armv7" ]; then FF_BUILD_NAME="ogg/armv7" - FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0 -fembed-bitcode" OGG_CFG_FLAGS="$OGG_CFG_FLAGS_ARM $OGG_CFG_FLAGS" elif [ "$FF_ARCH" = "armv7s" ]; then FF_BUILD_NAME="ogg/armv7s" OGG_CFG_CPU="--cpu=swift" - FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0 -fembed-bitcode" OGG_CFG_FLAGS="$OGG_CFG_FLAGS_ARM $OGG_CFG_FLAGS" elif [ "$FF_ARCH" = "arm64" ]; then FF_BUILD_NAME="ogg/arm64" - FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0" + FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0 -fembed-bitcode" OGG_CFG_FLAGS="$OGG_CFG_FLAGS_ARM $OGG_CFG_FLAGS" FF_GASPP_EXPORT="GASPP_FIX_XCODE5=1" else diff --git a/libs/tools/do-compile-speex.sh b/libs/tools/do-compile-speex.sh index 4fd3052..1ac2edc 100755 --- a/libs/tools/do-compile-speex.sh +++ b/libs/tools/do-compile-speex.sh @@ -90,30 +90,29 @@ if [ "$FF_ARCH" = "i386" ]; then FF_BUILD_NAME="speex/i386" FF_BUILD_NAME_OGG=ogg/i386 FF_XCRUN_PLATFORM="iPhoneSimulator" - FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0 -fembed-bitcode" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" elif [ "$FF_ARCH" = "x86_64" ]; then FF_BUILD_NAME="speex/x86_64" FF_BUILD_NAME_OGG=ogg/x86_64 FF_XCRUN_PLATFORM="iPhoneSimulator" - FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0" + FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0 -fembed-bitcode" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_SIMULATOR $SPEEX_CFG_FLAGS" elif [ "$FF_ARCH" = "armv7" ]; then FF_BUILD_NAME="speex/armv7" FF_BUILD_NAME_OGG=ogg/armv7 - FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0 -fembed-bitcode" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" -# OPENSSL_CFG_CPU="--cpu=cortex-a8" elif [ "$FF_ARCH" = "armv7s" ]; then FF_BUILD_NAME="speex/armv7s" FF_BUILD_NAME_OGG=ogg/armv7s SPEEX_CFG_CPU="--cpu=swift" - FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0" + FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0 -fembed-bitcode" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" elif [ "$FF_ARCH" = "arm64" ]; then FF_BUILD_NAME="speex/arm64" FF_BUILD_NAME_OGG=ogg/arm64 - FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0" + FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0 -fembed-bitcode" SPEEX_CFG_FLAGS="$SPEEX_CFG_FLAGS_ARM $SPEEX_CFG_FLAGS" FF_GASPP_EXPORT="GASPP_FIX_XCODE5=1" else From 74d999aab64b2b8246e260ac94bcc81abbe7605c Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 29 May 2020 15:36:34 +0900 Subject: [PATCH 209/215] Fixed: add limit to sync media. --- DLGPlayer/DLGPlayer.m | 84 +++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 827330e..37d7aa8 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -136,52 +136,50 @@ - (void)open:(NSString *)url { strongSelf.decoder.audioSampleRate = [strongSelf.audio sampleRate]; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; } + + NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + [strongSelf handleError:error]; + return; + } - dispatch_async(strongSelf.frameReaderQueue, ^{ - NSError *error = nil; - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - [strongSelf handleError:error]; - return; + dispatch_async(dispatch_get_main_queue(), ^{ + if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { + DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; + [view setCurrentEAGLContext]; } - dispatch_async(dispatch_get_main_queue(), ^{ - if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { - DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; - [view setCurrentEAGLContext]; - } - - strongSelf.view.isYUV = strongSelf.decoder.isYUV; - strongSelf.view.keepLastFrame = strongSelf.decoder.hasPicture && !strongSelf.decoder.hasVideo; - strongSelf.view.rotation = strongSelf.decoder.rotation; - strongSelf.view.contentSize = CGSizeMake(strongSelf.decoder.videoWidth, strongSelf.decoder.videoHeight); + strongSelf.view.isYUV = strongSelf.decoder.isYUV; + strongSelf.view.keepLastFrame = strongSelf.decoder.hasPicture && !strongSelf.decoder.hasVideo; + strongSelf.view.rotation = strongSelf.decoder.rotation; + strongSelf.view.contentSize = CGSizeMake(strongSelf.decoder.videoWidth, strongSelf.decoder.videoHeight); - if ([strongSelf.view isKindOfClass:[UIView class]]) { - ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; - } - - strongSelf.duration = strongSelf.decoder.duration; - strongSelf.metadata = strongSelf.decoder.metadata; - strongSelf.opening = NO; - strongSelf.buffering = NO; - strongSelf.playing = NO; - strongSelf.bufferedDuration = 0; - strongSelf.mediaPosition = 0; - strongSelf.mediaSyncTime = 0; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - - strongSelf.opened = YES; - - if (strongSelf.allowsFrameDrop) { - strongSelf.frameDropEnabled = YES; - } - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; - }); + if ([strongSelf.view isKindOfClass:[UIView class]]) { + ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; + } + + strongSelf.duration = strongSelf.decoder.duration; + strongSelf.metadata = strongSelf.decoder.metadata; + strongSelf.opening = NO; + strongSelf.buffering = NO; + strongSelf.playing = NO; + strongSelf.bufferedDuration = 0; + strongSelf.mediaPosition = 0; + strongSelf.mediaSyncTime = 0; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + + strongSelf.opened = YES; + + if (strongSelf.allowsFrameDrop) { + strongSelf.frameDropEnabled = YES; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; }); }); } @@ -590,7 +588,7 @@ - (void)render { if (_speed > 1) { t = frame.duration; } else { - t = frame.dropFrame ? 0.01 : MAX(frame.duration + syncTime, 0.01); + t = frame.dropFrame ? 0.01 : MIN(frame.duration, MAX(frame.duration + syncTime, 0.01)); } __weak typeof(self)weakSelf = self; From bdb2440e4615dd78f9a1df01058706906fb3b9d4 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Fri, 29 May 2020 16:18:02 +0900 Subject: [PATCH 210/215] Updated: other linker flags. --- DLGPlayer.xcodeproj/project.pbxproj | 2 -- 1 file changed, 2 deletions(-) diff --git a/DLGPlayer.xcodeproj/project.pbxproj b/DLGPlayer.xcodeproj/project.pbxproj index f79f426..cc77c21 100644 --- a/DLGPlayer.xcodeproj/project.pbxproj +++ b/DLGPlayer.xcodeproj/project.pbxproj @@ -704,7 +704,6 @@ OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", - "-l\"ogg\"", "-l\"speex\"", "-l\"avcodec\"", "-l\"avdevice\"", @@ -773,7 +772,6 @@ OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", - "-l\"ogg\"", "-l\"speex\"", "-l\"avcodec\"", "-l\"avdevice\"", From dd24de6e9d2c19bcc0af26bb5e8f424797369bdd Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 3 Jun 2020 13:43:05 +0900 Subject: [PATCH 211/215] Updated: add property keepLastFrame. --- DLGPlayer/DLGPlayer.h | 1 + DLGPlayer/DLGPlayer.m | 3 +- DLGPlayer/DLGSimplePlayerViewController.h | 1 + DLGPlayer/DLGSimplePlayerViewController.m | 45 +++++++++++++---------- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index 734c791..f3f3c32 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -24,6 +24,7 @@ typedef void (^onPauseComplete)(void); @interface DLGPlayer : NSObject @property (nonatomic) BOOL allowsFrameDrop; +@property (nonatomic) BOOL keepLastFrame; @property (nonatomic) BOOL mute; @property (atomic) BOOL playing; @property (atomic) BOOL buffering; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 37d7aa8..b7c75e8 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -151,7 +151,7 @@ - (void)open:(NSString *)url { } strongSelf.view.isYUV = strongSelf.decoder.isYUV; - strongSelf.view.keepLastFrame = strongSelf.decoder.hasPicture && !strongSelf.decoder.hasVideo; + strongSelf.view.keepLastFrame = strongSelf.keepLastFrame && strongSelf.decoder.hasPicture && !strongSelf.decoder.hasVideo; strongSelf.view.rotation = strongSelf.decoder.rotation; strongSelf.view.contentSize = CGSizeMake(strongSelf.decoder.videoWidth, strongSelf.decoder.videoHeight); @@ -258,6 +258,7 @@ - (void)initAll { - (void)initVars { _allowsFrameDrop = NO; _frameDropEnabled = NO; + _keepLastFrame = YES; _requestSeek = NO; _renderBegan = NO; _buffering = NO; diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index 7c6ef46..032c651 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -22,6 +22,7 @@ @property (nonatomic, readonly) BOOL hasUrl; @property (nonatomic) BOOL isAllowsFrameDrop; @property (nonatomic) BOOL isAutoplay; +@property (nonatomic) BOOL isKeepLastFrame; @property (nonatomic) BOOL isMute; @property (nonatomic, readonly) BOOL isPlaying; @property (nonatomic) BOOL isRepeat; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index bfe5dac..3b1f2a5 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -77,29 +77,15 @@ - (void)viewWillDisappear:(BOOL)animated { #pragma mark - getter/setter - (BOOL)hasUrl { - @autoreleasepool { - NSString *trimmed = [_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet]; - return _url != nil && trimmed.length > 0; - } + NSString *trimmed = [_url stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceCharacterSet]; + return _url != nil && trimmed.length > 0; } -- (BOOL)isPlaying { - return _player.playing; +- (BOOL)isKeepLastFrame { + return _player.keepLastFrame; } - -- (void)setStatus:(DLGPlayerStatus)status { - _status = status; - [_controlStatus setStatus:_status]; - - __weak typeof(self)weakSelf = self; - - dispatch_async(dispatch_get_main_queue(), ^{ - __strong typeof(weakSelf)strongSelf = weakSelf; - - if (strongSelf && [strongSelf.delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { - [strongSelf.delegate viewController:strongSelf didChangeStatus:status]; - } - }); +- (BOOL)isKeepLastFrame { + _player.keepLastFrame = isKeepLastFrame; } - (BOOL)isMute { @@ -109,6 +95,10 @@ - (void)setIsMute:(BOOL)isMute { _player.mute = isMute; } +- (BOOL)isPlaying { + return _player.playing; +} + - (double)frameDropDuration { return _player.frameDropDuration; } @@ -144,6 +134,21 @@ - (void)setSpeed:(double)speed { _player.speed = speed; } +- (void)setStatus:(DLGPlayerStatus)status { + _status = status; + [_controlStatus setStatus:_status]; + + __weak typeof(self)weakSelf = self; + + dispatch_async(dispatch_get_main_queue(), ^{ + __strong typeof(weakSelf)strongSelf = weakSelf; + + if (strongSelf && [strongSelf.delegate respondsToSelector:@selector(viewController:didChangeStatus:)]) { + [strongSelf.delegate viewController:strongSelf didChangeStatus:status]; + } + }); +} + #pragma mark - Init - (void)initAll { _player = [[DLGPlayer alloc] init]; From d65d2dc9da73ac05b8ba4c8b13aeb6d9d0ed532f Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 3 Jun 2020 16:13:47 +0900 Subject: [PATCH 212/215] Updated: add property isKeepLastFrame. --- DLGPlayer/DLGSimplePlayerViewController.m | 2 +- DLGPlayer/view/DLGPlayerView.m | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index 3b1f2a5..aa6907f 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -84,7 +84,7 @@ - (BOOL)hasUrl { - (BOOL)isKeepLastFrame { return _player.keepLastFrame; } -- (BOOL)isKeepLastFrame { +- (void)setIsKeepLastFrame:(BOOL)isKeepLastFrame { _player.keepLastFrame = isKeepLastFrame; } diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index 98f5081..daab6f7 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -106,8 +106,9 @@ - (void)reload { } - (void)clear { - _keepLastFrame = NO; - _lastFrame = nil; + if (!_keepLastFrame) { + _lastFrame = nil; + } [self render:nil]; } From eda6f151ab5d14c83dd34082a834e84ff7bc46a9 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 3 Jun 2020 16:54:37 +0900 Subject: [PATCH 213/215] Fixed: solve issue what crash to read frames. --- DLGPlayer/DLGPlayer.m | 82 ++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index b7c75e8..743d774 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -137,49 +137,51 @@ - (void)open:(NSString *)url { [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationAudioOpened object:strongSelf]; } - NSError *error = nil; - if (![strongSelf.decoder open:url error:&error]) { - strongSelf.opening = NO; - [strongSelf handleError:error]; - return; - } - - dispatch_async(dispatch_get_main_queue(), ^{ - if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { - DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; - [view setCurrentEAGLContext]; + dispatch_async(strongSelf.frameReaderQueue, ^{ + NSError *error = nil; + if (![strongSelf.decoder open:url error:&error]) { + strongSelf.opening = NO; + [strongSelf handleError:error]; + return; } - strongSelf.view.isYUV = strongSelf.decoder.isYUV; - strongSelf.view.keepLastFrame = strongSelf.keepLastFrame && strongSelf.decoder.hasPicture && !strongSelf.decoder.hasVideo; - strongSelf.view.rotation = strongSelf.decoder.rotation; - strongSelf.view.contentSize = CGSizeMake(strongSelf.decoder.videoWidth, strongSelf.decoder.videoHeight); + dispatch_async(dispatch_get_main_queue(), ^{ + if ([strongSelf.view isKindOfClass:[DLGPlayerView class]]) { + DLGPlayerView *view = (DLGPlayerView *) strongSelf.view; + [view setCurrentEAGLContext]; + } - if ([strongSelf.view isKindOfClass:[UIView class]]) { - ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; - } - - strongSelf.duration = strongSelf.decoder.duration; - strongSelf.metadata = strongSelf.decoder.metadata; - strongSelf.opening = NO; - strongSelf.buffering = NO; - strongSelf.playing = NO; - strongSelf.bufferedDuration = 0; - strongSelf.mediaPosition = 0; - strongSelf.mediaSyncTime = 0; - - __weak typeof(strongSelf)ws = strongSelf; - strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { - [ws readAudioFrame:data frames:frames channels:channels]; - }; - - strongSelf.opened = YES; - - if (strongSelf.allowsFrameDrop) { - strongSelf.frameDropEnabled = YES; - } - - [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; + strongSelf.view.isYUV = strongSelf.decoder.isYUV; + strongSelf.view.keepLastFrame = strongSelf.keepLastFrame && strongSelf.decoder.hasPicture && !strongSelf.decoder.hasVideo; + strongSelf.view.rotation = strongSelf.decoder.rotation; + strongSelf.view.contentSize = CGSizeMake(strongSelf.decoder.videoWidth, strongSelf.decoder.videoHeight); + + if ([strongSelf.view isKindOfClass:[UIView class]]) { + ((UIView *) strongSelf.view).contentMode = UIViewContentModeScaleToFill; + } + + strongSelf.duration = strongSelf.decoder.duration; + strongSelf.metadata = strongSelf.decoder.metadata; + strongSelf.opening = NO; + strongSelf.buffering = NO; + strongSelf.playing = NO; + strongSelf.bufferedDuration = 0; + strongSelf.mediaPosition = 0; + strongSelf.mediaSyncTime = 0; + + __weak typeof(strongSelf)ws = strongSelf; + strongSelf.audio.frameReaderBlock = ^(float *data, UInt32 frames, UInt32 channels) { + [ws readAudioFrame:data frames:frames channels:channels]; + }; + + strongSelf.opened = YES; + + if (strongSelf.allowsFrameDrop) { + strongSelf.frameDropEnabled = YES; + } + + [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationOpened object:strongSelf]; + }); }); }); } From 66fbb7f2eed21dded67081fc51c3dfc90b815e6c Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 3 Jun 2020 17:31:49 +0900 Subject: [PATCH 214/215] Updated: add function named clear contents of view. --- DLGPlayer/DLGPlayer.h | 1 + DLGPlayer/DLGPlayer.m | 6 +++++- DLGPlayer/DLGSimplePlayerViewController.h | 1 + DLGPlayer/DLGSimplePlayerViewController.m | 4 ++++ DLGPlayer/view/DLGPlayerVideoFrameView.h | 2 +- DLGPlayer/view/DLGPlayerView.m | 4 ++-- DLGPlayer/view/MetalPlayerView.m | 6 +++--- 7 files changed, 17 insertions(+), 7 deletions(-) diff --git a/DLGPlayer/DLGPlayer.h b/DLGPlayer/DLGPlayer.h index f3f3c32..7b0d541 100644 --- a/DLGPlayer/DLGPlayer.h +++ b/DLGPlayer/DLGPlayer.h @@ -40,6 +40,7 @@ typedef void (^onPauseComplete)(void); @property (nonatomic, readonly) UIView *playerView; @property (nonatomic, readonly) DLGPlayerAudioManager *audio; +- (void)clearView; - (void)close; - (void)closeAudio; - (void)closeCompletely; diff --git a/DLGPlayer/DLGPlayer.m b/DLGPlayer/DLGPlayer.m index 743d774..962863a 100644 --- a/DLGPlayer/DLGPlayer.m +++ b/DLGPlayer/DLGPlayer.m @@ -119,6 +119,10 @@ - (void)dealloc { #pragma mark - Public Methods +- (void)clearView { + [_view clear:YES]; +} + - (void)open:(NSString *)url { __weak typeof(self)weakSelf = self; @@ -370,7 +374,7 @@ - (void)close:(BOOL)completely { }); [strongSelf clearVars]; - [strongSelf.view clear]; + [strongSelf.view clear:NO]; [[NSNotificationCenter defaultCenter] postNotificationName:DLGPlayerNotificationClosed object:strongSelf]; }); } diff --git a/DLGPlayer/DLGSimplePlayerViewController.h b/DLGPlayer/DLGSimplePlayerViewController.h index 032c651..5dac6bc 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.h +++ b/DLGPlayer/DLGSimplePlayerViewController.h @@ -37,6 +37,7 @@ @property (nonatomic, readonly) DLGPlayerStatus status; @property (nonnull, nonatomic, readonly) DLGPlayer *player; @property (nullable, nonatomic, weak) id delegate; +- (void)clearView; - (void)open; - (void)play; - (void)pause; diff --git a/DLGPlayer/DLGSimplePlayerViewController.m b/DLGPlayer/DLGSimplePlayerViewController.m index aa6907f..76a2272 100644 --- a/DLGPlayer/DLGSimplePlayerViewController.m +++ b/DLGPlayer/DLGSimplePlayerViewController.m @@ -155,6 +155,10 @@ - (void)initAll { _status = DLGPlayerStatusNone; _controlStatus = [[DLGPlayerControlStatus alloc] initWithStatus:_status]; } + +- (void)clearView { + [_player clearView]; +} - (void)open { self.status = DLGPlayerStatusOpening; diff --git a/DLGPlayer/view/DLGPlayerVideoFrameView.h b/DLGPlayer/view/DLGPlayerVideoFrameView.h index fa2fed9..09ae0dc 100644 --- a/DLGPlayer/view/DLGPlayerVideoFrameView.h +++ b/DLGPlayer/view/DLGPlayerVideoFrameView.h @@ -21,7 +21,7 @@ @property (nonatomic) BOOL keepLastFrame; - (void)render:(DLGPlayerVideoFrame *)frame; -- (void)clear; +- (void)clear:(BOOL)forced; - (UIImage *)snapshot; @end diff --git a/DLGPlayer/view/DLGPlayerView.m b/DLGPlayer/view/DLGPlayerView.m index daab6f7..bde6773 100644 --- a/DLGPlayer/view/DLGPlayerView.m +++ b/DLGPlayer/view/DLGPlayerView.m @@ -105,8 +105,8 @@ - (void)reload { [self render:_lastFrame]; } -- (void)clear { - if (!_keepLastFrame) { +- (void)clear:(BOOL)forced { + if (forced || !_keepLastFrame) { _lastFrame = nil; } [self render:nil]; diff --git a/DLGPlayer/view/MetalPlayerView.m b/DLGPlayer/view/MetalPlayerView.m index 7b19b2a..2ec537a 100644 --- a/DLGPlayer/view/MetalPlayerView.m +++ b/DLGPlayer/view/MetalPlayerView.m @@ -39,7 +39,7 @@ - (void)dealloc { if (DLGPlayerUtils.debugEnabled) { NSLog(@"MetalPlayerView dealloc"); } - [self clear]; + [self clear:YES]; } - (id)initWithFrame:(CGRect)frame { @@ -170,8 +170,8 @@ - (void)setIsYUV:(BOOL)isYUV { #endif } -- (void)clear { - if (!_keepLastFrame) { +- (void)clear:(BOOL)forced { + if (forced || !_keepLastFrame) { currentFrame = nil; } From bde10fe4045a75dd99bd019a44310864169d1da2 Mon Sep 17 00:00:00 2001 From: KWANG HYOUN KIM Date: Wed, 3 Jun 2020 19:03:28 +0900 Subject: [PATCH 215/215] Fixed: change duration for frame from pkt_duration to diff of frames. --- DLGPlayer/codec/DLGPlayerDecoder.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DLGPlayer/codec/DLGPlayerDecoder.m b/DLGPlayer/codec/DLGPlayerDecoder.m index fd7401e..0be2c2b 100644 --- a/DLGPlayer/codec/DLGPlayerDecoder.m +++ b/DLGPlayer/codec/DLGPlayerDecoder.m @@ -599,7 +599,7 @@ - (NSArray *)readFrames { f.height = height; f.position = frame->best_effort_timestamp * _videoTimebase; - double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevVideo; + double duration = frame->pts - ptsPrevVideo; if (duration > 0) { f.duration = duration * _videoTimebase / _speed; @@ -695,7 +695,7 @@ - (NSArray *)readFrames { f.data = mdata; f.position = frame->best_effort_timestamp * _audioTimebase; - double duration = frame->pkt_duration > 0 ? frame->pkt_duration : frame->pts - ptsPrevAudio; + double duration = frame->pts - ptsPrevAudio; if (duration > 0) { f.duration = duration * _audioTimebase / _speed;