The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── SGPlayer.xcodeproj
    ├── project.pbxproj
    ├── project.xcworkspace
    │   ├── contents.xcworkspacedata
    │   └── xcshareddata
    │   │   ├── IDEWorkspaceChecks.plist
    │   │   └── SGPlayer.xcscmblueprint
    └── xcshareddata
    │   └── xcschemes
    │       ├── SGPlayer iOS.xcscheme
    │       ├── SGPlayer macOS.xcscheme
    │       └── SGPlayer tvOS.xcscheme
├── SGPlayer
    ├── Classes
    │   ├── Core
    │   │   ├── SGAsset
    │   │   │   ├── SGAsset+Internal.h
    │   │   │   ├── SGAsset.h
    │   │   │   ├── SGAsset.m
    │   │   │   ├── SGMutableAsset.h
    │   │   │   ├── SGMutableAsset.m
    │   │   │   ├── SGMutableTrack.h
    │   │   │   ├── SGMutableTrack.m
    │   │   │   ├── SGPaddingSegment.h
    │   │   │   ├── SGPaddingSegment.m
    │   │   │   ├── SGSegment+Internal.h
    │   │   │   ├── SGSegment.h
    │   │   │   ├── SGSegment.m
    │   │   │   ├── SGTrack+Internal.h
    │   │   │   ├── SGTrack.h
    │   │   │   ├── SGTrack.m
    │   │   │   ├── SGTrackSelection.h
    │   │   │   ├── SGTrackSelection.m
    │   │   │   ├── SGURLAsset.h
    │   │   │   ├── SGURLAsset.m
    │   │   │   ├── SGURLSegment.h
    │   │   │   └── SGURLSegment.m
    │   │   ├── SGAudio
    │   │   │   ├── SGAudioPlayer.h
    │   │   │   └── SGAudioPlayer.m
    │   │   ├── SGCommon
    │   │   │   ├── SGActivity.h
    │   │   │   ├── SGActivity.m
    │   │   │   ├── SGDefines.h
    │   │   │   ├── SGError.h
    │   │   │   ├── SGError.m
    │   │   │   ├── SGLock.h
    │   │   │   ├── SGLock.m
    │   │   │   ├── SGTime.h
    │   │   │   └── SGTime.m
    │   │   ├── SGContainer
    │   │   │   ├── SGObjectPool.h
    │   │   │   ├── SGObjectPool.m
    │   │   │   ├── SGObjectQueue.h
    │   │   │   └── SGObjectQueue.m
    │   │   ├── SGData
    │   │   │   ├── SGAudioFrame.h
    │   │   │   ├── SGAudioFrame.m
    │   │   │   ├── SGCapacity.h
    │   │   │   ├── SGCapacity.m
    │   │   │   ├── SGData.h
    │   │   │   ├── SGFrame+Internal.h
    │   │   │   ├── SGFrame.h
    │   │   │   ├── SGFrame.m
    │   │   │   ├── SGPacket+Internal.h
    │   │   │   ├── SGPacket.h
    │   │   │   ├── SGPacket.m
    │   │   │   ├── SGTimeLayout.h
    │   │   │   ├── SGTimeLayout.m
    │   │   │   ├── SGVideoFrame.h
    │   │   │   └── SGVideoFrame.m
    │   │   ├── SGDecoder
    │   │   │   ├── SGAudioDecoder.h
    │   │   │   ├── SGAudioDecoder.m
    │   │   │   ├── SGCodecContext.h
    │   │   │   ├── SGCodecContext.m
    │   │   │   ├── SGDecodable.h
    │   │   │   ├── SGDecodeContext.h
    │   │   │   ├── SGDecodeContext.m
    │   │   │   ├── SGDecodeLoop.h
    │   │   │   ├── SGDecodeLoop.m
    │   │   │   ├── SGVideoDecoder.h
    │   │   │   └── SGVideoDecoder.m
    │   │   ├── SGDefine
    │   │   │   ├── SGMacro.h
    │   │   │   ├── SGMapping.h
    │   │   │   └── SGMapping.m
    │   │   ├── SGDemuxer
    │   │   │   ├── SGDemuxable.h
    │   │   │   ├── SGExtractingDemuxer.h
    │   │   │   ├── SGExtractingDemuxer.m
    │   │   │   ├── SGMutilDemuxer.h
    │   │   │   ├── SGMutilDemuxer.m
    │   │   │   ├── SGPaddingDemuxer.h
    │   │   │   ├── SGPaddingDemuxer.m
    │   │   │   ├── SGTrackDemuxer.h
    │   │   │   ├── SGTrackDemuxer.m
    │   │   │   ├── SGURLDemuxer.h
    │   │   │   └── SGURLDemuxer.m
    │   │   ├── SGDescription
    │   │   │   ├── SGAudioDescriptor.h
    │   │   │   ├── SGAudioDescriptor.m
    │   │   │   ├── SGCodecDescriptor.h
    │   │   │   ├── SGCodecDescriptor.m
    │   │   │   ├── SGDescriptor+Internal.h
    │   │   │   ├── SGVideoDescriptor.h
    │   │   │   └── SGVideoDescriptor.m
    │   │   ├── SGFFmpeg
    │   │   │   ├── SGFFmpeg.h
    │   │   │   └── SGFFmpeg.m
    │   │   ├── SGMetal
    │   │   │   ├── SGMetal.h
    │   │   │   ├── SGMetalBGRARenderPipeline.h
    │   │   │   ├── SGMetalBGRARenderPipeline.m
    │   │   │   ├── SGMetalModel.h
    │   │   │   ├── SGMetalModel.m
    │   │   │   ├── SGMetalNV12RenderPipeline.h
    │   │   │   ├── SGMetalNV12RenderPipeline.m
    │   │   │   ├── SGMetalPlaneModel.h
    │   │   │   ├── SGMetalPlaneModel.m
    │   │   │   ├── SGMetalProjection.h
    │   │   │   ├── SGMetalProjection.m
    │   │   │   ├── SGMetalRenderPipeline.h
    │   │   │   ├── SGMetalRenderPipeline.m
    │   │   │   ├── SGMetalRenderPipelinePool.h
    │   │   │   ├── SGMetalRenderPipelinePool.m
    │   │   │   ├── SGMetalRenderer.h
    │   │   │   ├── SGMetalRenderer.m
    │   │   │   ├── SGMetalShader.metal
    │   │   │   ├── SGMetalShader_iOS.h
    │   │   │   ├── SGMetalShader_macOS.h
    │   │   │   ├── SGMetalShader_tvOS.h
    │   │   │   ├── SGMetalSphereModel.h
    │   │   │   ├── SGMetalSphereModel.m
    │   │   │   ├── SGMetalTextureLoader.h
    │   │   │   ├── SGMetalTextureLoader.m
    │   │   │   ├── SGMetalTypes.h
    │   │   │   ├── SGMetalViewport.h
    │   │   │   ├── SGMetalViewport.m
    │   │   │   ├── SGMetalYUVRenderPipeline.h
    │   │   │   └── SGMetalYUVRenderPipeline.m
    │   │   ├── SGOption
    │   │   │   ├── SGDecoderOptions.h
    │   │   │   ├── SGDecoderOptions.m
    │   │   │   ├── SGDemuxerOptions.h
    │   │   │   ├── SGDemuxerOptions.m
    │   │   │   ├── SGOptions.h
    │   │   │   ├── SGOptions.m
    │   │   │   ├── SGProcessorOptions.h
    │   │   │   └── SGProcessorOptions.m
    │   │   ├── SGPlatform
    │   │   │   ├── SGPLFColor.h
    │   │   │   ├── SGPLFColor.m
    │   │   │   ├── SGPLFImage.h
    │   │   │   ├── SGPLFImage.m
    │   │   │   ├── SGPLFObject.h
    │   │   │   ├── SGPLFScreen.h
    │   │   │   ├── SGPLFScreen.m
    │   │   │   ├── SGPLFTargets.h
    │   │   │   ├── SGPLFView.h
    │   │   │   └── SGPLFView.m
    │   │   ├── SGProcessor
    │   │   │   ├── SGAudioFormatter.h
    │   │   │   ├── SGAudioFormatter.m
    │   │   │   ├── SGAudioMixer.h
    │   │   │   ├── SGAudioMixer.m
    │   │   │   ├── SGAudioMixerUnit.h
    │   │   │   ├── SGAudioMixerUnit.m
    │   │   │   ├── SGAudioProcessor.h
    │   │   │   ├── SGAudioProcessor.m
    │   │   │   ├── SGProcessor.h
    │   │   │   ├── SGSWResample.h
    │   │   │   ├── SGSWResample.m
    │   │   │   ├── SGSWScale.h
    │   │   │   ├── SGSWScale.m
    │   │   │   ├── SGSonic.h
    │   │   │   ├── SGSonic.m
    │   │   │   ├── SGVideoProcessor.h
    │   │   │   └── SGVideoProcessor.m
    │   │   ├── SGRenderer
    │   │   │   ├── SGAudioRenderer.h
    │   │   │   ├── SGAudioRenderer.m
    │   │   │   ├── SGClock+Internal.h
    │   │   │   ├── SGClock.h
    │   │   │   ├── SGClock.m
    │   │   │   ├── SGRenderTimer.h
    │   │   │   ├── SGRenderTimer.m
    │   │   │   ├── SGRenderable.h
    │   │   │   ├── SGRenderer+Internal.h
    │   │   │   ├── SGVideoRenderer.h
    │   │   │   └── SGVideoRenderer.m
    │   │   ├── SGSession
    │   │   │   ├── SGFrameOutput.h
    │   │   │   ├── SGFrameOutput.m
    │   │   │   ├── SGFrameReader.h
    │   │   │   ├── SGFrameReader.m
    │   │   │   ├── SGPacketOutput.h
    │   │   │   ├── SGPacketOutput.m
    │   │   │   ├── SGPlayerItem+Internal.h
    │   │   │   ├── SGPlayerItem.h
    │   │   │   └── SGPlayerItem.m
    │   │   ├── SGVR
    │   │   │   ├── SGMotionSensor.h
    │   │   │   ├── SGMotionSensor.m
    │   │   │   ├── SGVRProjection.h
    │   │   │   ├── SGVRProjection.m
    │   │   │   ├── SGVRViewport.h
    │   │   │   └── SGVRViewport.m
    │   │   └── Vendor
    │   │   │   └── sonic
    │   │   │       ├── sonic.c
    │   │   │       └── sonic.h
    │   ├── SGPlayer.h
    │   ├── SGPlayer.m
    │   └── SGPlayerHeader.h
    ├── Info.plist
    └── module.modulemap
├── build.sh
├── demo
    ├── demo-assset
    │   ├── google-help-vr.mp4
    │   └── i-see-fire.mp4
    ├── demo-common
    │   ├── SGVideoItem.h
    │   └── SGVideoItem.m
    ├── demo-ios
    │   ├── demo-ios.xcodeproj
    │   │   ├── project.pbxproj
    │   │   ├── project.xcworkspace
    │   │   │   └── contents.xcworkspacedata
    │   │   └── xcshareddata
    │   │   │   └── xcschemes
    │   │   │       └── demo-ios.xcscheme
    │   └── demo-ios
    │   │   ├── AppDelegate.h
    │   │   ├── AppDelegate.m
    │   │   ├── Assets.xcassets
    │   │       └── AppIcon.appiconset
    │   │       │   ├── Contents.json
    │   │       │   ├── Icon-60@2x.png
    │   │       │   ├── Icon-60@3x.png
    │   │       │   ├── Icon-Notification@2x.png
    │   │       │   ├── Icon-Notification@3x.png
    │   │       │   ├── Icon-Small-40@2x.png
    │   │       │   ├── Icon-Small-40@3x.png
    │   │       │   ├── Icon-Small@2x.png
    │   │       │   ├── Icon-Small@3x.png
    │   │       │   └── logo.png
    │   │   ├── Base.lproj
    │   │       ├── LaunchScreen.storyboard
    │   │       └── Main.storyboard
    │   │   ├── Info.plist
    │   │   ├── SGListViewController.h
    │   │   ├── SGListViewController.m
    │   │   ├── SGPlayViewController.h
    │   │   ├── SGPlayViewController.m
    │   │   ├── SGPlayViewController.xib
    │   │   └── main.m
    ├── demo-macos
    │   ├── demo-macos.xcodeproj
    │   │   ├── project.pbxproj
    │   │   ├── project.xcworkspace
    │   │   │   └── contents.xcworkspacedata
    │   │   └── xcshareddata
    │   │   │   └── xcschemes
    │   │   │       └── demo-macos.xcscheme
    │   └── demo-macos
    │   │   ├── AppDelegate.h
    │   │   ├── AppDelegate.m
    │   │   ├── Assets.xcassets
    │   │       └── AppIcon.appiconset
    │   │       │   ├── Contents.json
    │   │       │   ├── icon_128x128.png
    │   │       │   ├── icon_128x128@2x.png
    │   │       │   ├── icon_16x16.png
    │   │       │   ├── icon_16x16@2x.png
    │   │       │   ├── icon_256x256.png
    │   │       │   ├── icon_256x256@2x.png
    │   │       │   ├── icon_32x32.png
    │   │       │   ├── icon_32x32@2x.png
    │   │       │   ├── icon_512x512.png
    │   │       │   └── icon_512x512@2x.png
    │   │   ├── Base.lproj
    │   │       └── Main.storyboard
    │   │   ├── Info.plist
    │   │   ├── SGListViewController.h
    │   │   ├── SGListViewController.m
    │   │   ├── SGPlayViewController.h
    │   │   ├── SGPlayViewController.m
    │   │   └── main.m
    ├── demo-tvos
    │   ├── demo-tvos.xcodeproj
    │   │   ├── project.pbxproj
    │   │   ├── project.xcworkspace
    │   │   │   ├── contents.xcworkspacedata
    │   │   │   └── xcshareddata
    │   │   │   │   └── IDEWorkspaceChecks.plist
    │   │   └── xcshareddata
    │   │   │   └── xcschemes
    │   │   │       └── demo-tvos.xcscheme
    │   └── demo-tvos
    │   │   ├── AppDelegate.h
    │   │   ├── AppDelegate.m
    │   │   ├── Assets.xcassets
    │   │       ├── App Icon & Top Shelf Image.brandassets
    │   │       │   ├── App Icon - App Store.imagestack
    │   │       │   │   ├── Back.imagestacklayer
    │   │       │   │   │   ├── Content.imageset
    │   │       │   │   │   │   └── Contents.json
    │   │       │   │   │   └── Contents.json
    │   │       │   │   ├── Contents.json
    │   │       │   │   ├── Front.imagestacklayer
    │   │       │   │   │   ├── Content.imageset
    │   │       │   │   │   │   └── Contents.json
    │   │       │   │   │   └── Contents.json
    │   │       │   │   └── Middle.imagestacklayer
    │   │       │   │   │   ├── Content.imageset
    │   │       │   │   │       └── Contents.json
    │   │       │   │   │   └── Contents.json
    │   │       │   ├── App Icon.imagestack
    │   │       │   │   ├── Back.imagestacklayer
    │   │       │   │   │   ├── Content.imageset
    │   │       │   │   │   │   └── Contents.json
    │   │       │   │   │   └── Contents.json
    │   │       │   │   ├── Contents.json
    │   │       │   │   ├── Front.imagestacklayer
    │   │       │   │   │   ├── Content.imageset
    │   │       │   │   │   │   └── Contents.json
    │   │       │   │   │   └── Contents.json
    │   │       │   │   └── Middle.imagestacklayer
    │   │       │   │   │   ├── Content.imageset
    │   │       │   │   │       └── Contents.json
    │   │       │   │   │   └── Contents.json
    │   │       │   ├── Contents.json
    │   │       │   ├── Top Shelf Image Wide.imageset
    │   │       │   │   └── Contents.json
    │   │       │   └── Top Shelf Image.imageset
    │   │       │   │   └── Contents.json
    │   │       └── Contents.json
    │   │   ├── Base.lproj
    │   │       └── Main.storyboard
    │   │   ├── Info.plist
    │   │   ├── ViewController.h
    │   │   ├── ViewController.m
    │   │   └── main.m
    └── demo.xcworkspace
    │   ├── contents.xcworkspacedata
    │   └── xcshareddata
    │       ├── IDEWorkspaceChecks.plist
    │       └── demo.xcscmblueprint
├── documents
    ├── banner.jpg
    └── flow-chart.jpg
└── scripts
    ├── avconfig.h
    ├── compile-ffmpeg.sh
    ├── compile-openssl.sh
    ├── config.h
    ├── do-compile-ffmpeg.sh
    ├── do-compile-openssl.sh
    ├── ffversion.h
    ├── init-ffmpeg.sh
    ├── init-openssl.sh
    ├── module.sh
    ├── pull-repo-base.sh
    └── pull-repo-ref.sh


/.gitattributes:
--------------------------------------------------------------------------------
1 | *.h linguist-language=Objective-C


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | build/
 2 | *.pbxuser
 3 | !default.pbxuser
 4 | *.mode1v3
 5 | !default.mode1v3
 6 | *.mode2v3
 7 | !default.mode2v3
 8 | *.perspectivev3
 9 | !default.perspectivev3
10 | xcuserdata
11 | *.xccheckout
12 | *.moved-aside
13 | DerivedData
14 | *.hmap
15 | *.ipa
16 | *.xcuserstate
17 | .DS_Store
18 | framework/


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2017 Single
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 


--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
 1 | ![Logo](https://github.com/libobjc/SGPlayer/blob/master/documents/banner.jpg?raw=true)
 2 | 
 3 | 
 4 | ![Build Status](https://img.shields.io/badge/build-%20passing%20-brightgreen)  ![License](https://img.shields.io/badge/license-MIT-red) ![Platform](https://img.shields.io/badge/Platform-%20iOS%20macOS%20tvOS%20-blue)
 5 | 
 6 | # SGPlayer 
 7 | 
 8 | - SGPlayer is a powerful media play framework for iOS, macOS, and tvOS.
 9 | 
10 | ## Features
11 | 
12 | - iOS, tvOS, macOS.
13 | - 360° panorama video.
14 | - Compose complex asset.
15 | - Background playback.
16 | - RTMP/RTSP streaming.
17 | - Setting playback speed.
18 | - Multiple audio/video tracks.
19 | - H.264/H.265 hardware accelerator.
20 | - Accurate status notifications.
21 | - Thread safety.
22 | 
23 | ## Based On
24 | 
25 | - FFmpeg
26 | - Metal
27 | - AudioToolbox
28 | 
29 | ## Requirements
30 | 
31 | - iOS 13.0 or later
32 | - tvOS 13.0 or later
33 | - macOS 10.15 or later
34 | 
35 | ## Getting Started
36 | 
37 | #### Build FFmpeg and OpenSSL 
38 | 
39 | - Build scripts are used by default for FFmpeg 4.4.4 and OpenSSL 1.1.1w
40 | 
41 | ```obj-c
42 | git clone https://github.com/libobjc/SGPlayer.git
43 | cd SGPlayer
44 | git checkout 2.1.0 -B latest
45 | 
46 | // iOS
47 | ./build.sh iOS build
48 | 
49 | // tvOS
50 | ./build.sh tvOS build
51 | 
52 | // macOS
53 | ./build.sh macOS build
54 | ```
55 | 
56 | #### Open demo project in Xcode
57 | 
58 | - Open demo/demo.xcworkspace. You can see simple use cases.
59 | 
60 | #### Check Dependencies
61 | 
62 | ```obj-c
63 | - SGPlayer.framework
64 | - AVFoundation.framework
65 | - AudioToolBox.framework
66 | - VideoToolBox.framework
67 | - libiconv.tbd
68 | - libbz2.tbd
69 | - libz.tbd
70 | ```
71 | 
72 | ## Flow Chart
73 | 
74 | ![Flow Chart](https://github.com/libobjc/SGPlayer/blob/master/documents/flow-chart.jpg?raw=true)
75 | 
76 | ## Author
77 | 
78 | - GitHub : [Single](https://github.com/libobjc)
79 | - Email : libobjc@gmail.com
80 | 
81 | ## Developed by Author
82 | 
83 | - [KTVHTTPCache](https://github.com/ChangbaDevs/KTVHTTPCache) - A smart media cache framework.
84 | - [KTVVideoProcess](https://github.com/ChangbaDevs/KTVVideoProcess) - A High-Performance video effects processing framework.
85 | 


--------------------------------------------------------------------------------
/SGPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <Workspace
3 |    version = "1.0">
4 |    <FileRef
5 |       location = "self:SGPlayer.xcodeproj">
6 |    </FileRef>
7 | </Workspace>
8 | 


--------------------------------------------------------------------------------
/SGPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>IDEDidComputeMac32BitWarning</key>
6 | 	<true/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/SGPlayer.xcodeproj/project.xcworkspace/xcshareddata/SGPlayer.xcscmblueprint:
--------------------------------------------------------------------------------
 1 | {
 2 |   "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "F23AFB690725856BF6A8F7C02C736922AA443A58",
 3 |   "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
 4 | 
 5 |   },
 6 |   "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
 7 |     "F23AFB690725856BF6A8F7C02C736922AA443A58" : 9223372036854775807,
 8 |     "CF9A9AD861EDA5D4368DC40F74298A8979BAE8C8" : 9223372036854775807
 9 |   },
10 |   "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "A1C462FA-BB77-480D-B6D6-3CBEF27EAC9D",
11 |   "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12 |     "F23AFB690725856BF6A8F7C02C736922AA443A58" : "SGPlayer\/",
13 |     "CF9A9AD861EDA5D4368DC40F74298A8979BAE8C8" : "SGPlayer\/Vendors\/SGPlatform\/"
14 |   },
15 |   "DVTSourceControlWorkspaceBlueprintNameKey" : "SGPlayer",
16 |   "DVTSourceControlWorkspaceBlueprintVersion" : 204,
17 |   "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "SGPlayer.xcodeproj",
18 |   "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19 |     {
20 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:0x010101\/SGPlatform.git",
21 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "CF9A9AD861EDA5D4368DC40F74298A8979BAE8C8"
23 |     },
24 |     {
25 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:0x010101\/SGPlayer.git",
26 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "F23AFB690725856BF6A8F7C02C736922AA443A58"
28 |     }
29 |   ]
30 | }


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGAsset+Internal.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAsset+Internal.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/9/25.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGAsset.h"
10 | #import "SGDemuxable.h"
11 | 
12 | @interface SGAsset ()
13 | 
14 | /*!
15 |  @method newDemuxer
16 |  @abstract
17 |     Create a new demuxer.
18 |  */
19 | - (id<SGDemuxable>)newDemuxer;
20 | 
21 | @end
22 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGAsset.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAsset.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/10.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | 
11 | /*!
12 |  @class SGAsset
13 |  @abstract
14 |     Abstract class for assets.
15 |  
16 |  @discussion
17 |     Use SGURLAsset or SGMutableAsset.
18 |  */
19 | @interface SGAsset : NSObject <NSCopying>
20 | 
21 | /*!
22 |  @method assetWithURL:
23 |  @abstract
24 |     Returns an instance of SGAsset for inspection of a media resource.
25 |  @result
26 |     An instance of SGAsset.
27 |  
28 |  @discussion
29 |     Returns a newly allocated instance of a subclass of SGAsset initialized with the specified URL.
30 |  */
31 | + (instancetype)assetWithURL:(NSURL *)URL;
32 | 
33 | @end
34 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGAsset.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAsset.m
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/10.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGAsset.h"
10 | #import "SGAsset+Internal.h"
11 | #import "SGURLAsset.h"
12 | 
13 | @implementation SGAsset
14 | 
15 | + (instancetype)assetWithURL:(NSURL *)URL
16 | {
17 |     return [[SGURLAsset alloc] initWithURL:URL];
18 | }
19 | 
20 | - (id)copyWithZone:(NSZone *)zone
21 | {
22 |     SGAsset *obj = [[self.class alloc] init];
23 |     return obj;
24 | }
25 | 
26 | - (id<SGDemuxable>)newDemuxer
27 | {
28 |     NSAssert(NO, @"Subclass only.");
29 |     return nil;
30 | }
31 | 
32 | @end
33 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGMutableAsset.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMutableAsset.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/14.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGAsset.h"
10 | #import "SGDefines.h"
11 | #import "SGMutableTrack.h"
12 | 
13 | @interface SGMutableAsset : SGAsset
14 | 
15 | /*!
16 |  @property tracks
17 |  @abstract
18 |     Provides array of mutable asset tracks.
19 | */
20 | @property (nonatomic, copy, readonly) NSArray<SGMutableTrack *> *tracks;
21 | 
22 | /*!
23 |  @method addTrack:
24 |  @abstract
25 |     Add a track to the asset.
26 |  
27 |  @discussion
28 |     Returns a initialized mutable track of the given type.
29 |  */
30 | - (SGMutableTrack *)addTrack:(SGMediaType)type;
31 | 
32 | @end
33 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGMutableAsset.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMutableAsset.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/14.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMutableAsset.h"
10 | #import "SGAsset+Internal.h"
11 | #import "SGTrack+Internal.h"
12 | #import "SGTrackDemuxer.h"
13 | #import "SGMutilDemuxer.h"
14 | 
15 | @interface SGMutableAsset ()
16 | 
17 | {
18 |     NSMutableArray<SGMutableTrack *> *_tracks;
19 | }
20 | 
21 | @end
22 | 
23 | @implementation SGMutableAsset
24 | 
25 | - (id)copyWithZone:(NSZone *)zone
26 | {
27 |     SGMutableAsset *obj = [super copyWithZone:zone];
28 |     obj->_tracks = [self->_tracks mutableCopy];
29 |     return obj;
30 | }
31 | 
32 | - (instancetype)init
33 | {
34 |     if (self = [super init]) {
35 |         self->_tracks = [NSMutableArray array];
36 |     }
37 |     return self;
38 | }
39 | 
40 | - (NSArray<SGMutableTrack *> *)tracks
41 | {
42 |     return [self->_tracks copy];
43 | }
44 | 
45 | - (SGMutableTrack *)addTrack:(SGMediaType)type
46 | {
47 |     NSInteger index = self->_tracks.count;
48 |     SGMutableTrack *obj = [[SGMutableTrack alloc] initWithType:type index:index];
49 |     [self->_tracks addObject:obj];
50 |     return obj;
51 | }
52 | 
53 | - (id<SGDemuxable>)newDemuxer
54 | {
55 |     NSMutableArray *demuxables = [NSMutableArray array];
56 |     for (SGMutableTrack *obj in self->_tracks) {
57 |         SGTrackDemuxer *demuxer = [[SGTrackDemuxer alloc] initWithTrack:obj];
58 |         [demuxables addObject:demuxer];
59 |     }
60 |     return [[SGMutilDemuxer alloc] initWithDemuxables:demuxables];
61 | }
62 | 
63 | @end
64 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGMutableTrack.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMutableTrack.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/29.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGSegment.h"
11 | #import "SGTrack.h"
12 | 
13 | @interface SGMutableTrack : SGTrack
14 | 
15 | /*!
16 |  @property subTracks
17 |  @abstract
18 |     Indicates the sub tracks.
19 |  */
20 | @property (nonatomic, copy, readonly) NSArray<SGTrack *> *subTracks;
21 | 
22 | /*!
23 |  @property segments
24 |  @abstract
25 |     Provides array of SGMutableTrack segments.
26 |  */
27 | @property (nonatomic, copy, readonly) NSArray<SGSegment *> *segments;
28 | 
29 | /*!
30 |  @method appendSegment:
31 |  @abstract
32 |     Append a segment to the track.
33 |  */
34 | - (BOOL)appendSegment:(SGSegment *)segment;
35 | 
36 | @end
37 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGMutableTrack.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMutableTrack.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/29.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMutableTrack.h"
10 | #import "SGTrack+Internal.h"
11 | 
12 | @interface SGMutableTrack ()
13 | 
14 | {
15 |     NSMutableArray<SGSegment *> *_segments;
16 | }
17 | 
18 | @end
19 | 
20 | @implementation SGMutableTrack
21 | 
22 | - (id)copyWithZone:(NSZone *)zone
23 | {
24 |     SGMutableTrack *obj = [super copyWithZone:zone];
25 |     obj->_segments = [self->_segments mutableCopy];
26 |     obj->_subTracks = [self->_subTracks copy];
27 |     return obj;
28 | }
29 | 
30 | - (instancetype)initWithType:(SGMediaType)type index:(NSInteger)index
31 | {
32 |     if (self = [super initWithType:type index:index]) {
33 |         self->_segments = [NSMutableArray array];
34 |     }
35 |     return self;
36 | }
37 | 
38 | - (void *)coreptr
39 | {
40 |     return [self core];
41 | }
42 | 
43 | - (AVStream *)core
44 | {
45 |     void *ret = [super core];
46 |     if (ret) {
47 |         return ret;
48 |     }
49 |     for (SGTrack *obj in self->_subTracks) {
50 |         if (obj.core) {
51 |             ret = obj.core;
52 |             break;
53 |         }
54 |     }
55 |     return ret;
56 | }
57 | 
58 | - (BOOL)appendSegment:(SGSegment *)segment
59 | {
60 |     [self->_segments addObject:segment];
61 |     return YES;
62 | }
63 | 
64 | @end
65 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGPaddingSegment.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPaddingSegment.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/9/19.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGSegment.h"
10 | 
11 | @interface SGPaddingSegment : SGSegment
12 | 
13 | + (instancetype)new NS_UNAVAILABLE;
14 | - (instancetype)init NS_UNAVAILABLE;
15 | 
16 | /**
17 |  *
18 |  */
19 | - (instancetype)initWithDuration:(CMTime)duration;
20 | 
21 | /**
22 |  *
23 |  */
24 | @property (nonatomic, readonly) CMTime duration;
25 | 
26 | @end
27 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGPaddingSegment.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPaddingSegment.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/9/19.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPaddingSegment.h"
10 | #import "SGSegment+Internal.h"
11 | #import "SGPaddingDemuxer.h"
12 | 
13 | @implementation SGPaddingSegment
14 | 
15 | - (id)copyWithZone:(NSZone *)zone
16 | {
17 |     SGPaddingSegment *obj = [super copyWithZone:zone];
18 |     obj->_duration = self->_duration;
19 |     return obj;
20 | }
21 | 
22 | - (instancetype)initWithDuration:(CMTime)duration
23 | {
24 |     if (self = [super init]) {
25 |         self->_duration = duration;
26 |     }
27 |     return self;
28 | }
29 | 
30 | - (NSString *)sharedDemuxerKey
31 | {
32 |     return nil;
33 | }
34 | 
35 | - (id<SGDemuxable>)newDemuxer
36 | {
37 |     return [[SGPaddingDemuxer alloc] initWithDuration:self->_duration];
38 | }
39 | 
40 | - (id<SGDemuxable>)newDemuxerWithSharedDemuxer:(id<SGDemuxable>)demuxer
41 | {
42 |     return [self newDemuxer];
43 | }
44 | 
45 | @end
46 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGSegment+Internal.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGSegment+Internal.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/9/25.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGSegment.h"
10 | #import "SGDemuxable.h"
11 | 
12 | @interface SGSegment ()
13 | 
14 | /**
15 |  *
16 |  */
17 | - (NSString *)sharedDemuxerKey;
18 | 
19 | /**
20 |  *
21 |  */
22 | - (id<SGDemuxable>)newDemuxer;
23 | 
24 | /**
25 |  *
26 |  */
27 | - (id<SGDemuxable>)newDemuxerWithSharedDemuxer:(id<SGDemuxable>)demuxer;
28 | 
29 | @end
30 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGSegment.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGSegment.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/14.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import <CoreMedia/CoreMedia.h>
11 | 
12 | @interface SGSegment : NSObject <NSCopying>
13 | 
14 | /*!
15 |  @method segmentWithDuration:
16 |  @abstract
17 |     Returns an instance of SGSegment with the given duration.
18 |  
19 |  @discussion
20 |     For audio track:
21 |  *
22 |  */
23 | + (instancetype)segmentWithDuration:(CMTime)duration;
24 | 
25 | /**
26 |  *
27 |  */
28 | + (instancetype)segmentWithURL:(NSURL *)URL index:(NSInteger)index;
29 | 
30 | /**
31 |  *
32 |  */
33 | + (instancetype)segmentWithURL:(NSURL *)URL index:(NSInteger)index timeRange:(CMTimeRange)timeRange scale:(CMTime)scale;
34 | 
35 | @end
36 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGSegment.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGSegment.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/14.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGSegment.h"
10 | #import "SGSegment+Internal.h"
11 | #import "SGPaddingSegment.h"
12 | #import "SGURLSegment.h"
13 | 
14 | @implementation SGSegment
15 | 
16 | + (instancetype)segmentWithDuration:(CMTime)duration
17 | {
18 |     return [[SGPaddingSegment alloc] initWithDuration:duration];
19 | }
20 | 
21 | + (instancetype)segmentWithURL:(NSURL *)URL index:(NSInteger)index
22 | {
23 |     return [[SGURLSegment alloc] initWithURL:URL index:index timeRange:kCMTimeRangeInvalid scale:kCMTimeInvalid];
24 | }
25 | 
26 | + (instancetype)segmentWithURL:(NSURL *)URL index:(NSInteger)index timeRange:(CMTimeRange)timeRange scale:(CMTime)scale
27 | {
28 |     return [[SGURLSegment alloc] initWithURL:URL index:index timeRange:timeRange scale:scale];
29 | }
30 | 
31 | - (id)copyWithZone:(NSZone *)zone
32 | {
33 |     SGSegment *obj = [[self.class alloc] init];
34 |     return obj;
35 | }
36 | 
37 | - (NSString *)sharedDemuxerKey
38 | {
39 |     NSAssert(NO, @"Subclass only.");
40 |     return nil;
41 | }
42 | 
43 | - (id<SGDemuxable>)newDemuxer
44 | {
45 |     NSAssert(NO, @"Subclass only.");
46 |     return nil;
47 | }
48 | 
49 | - (id<SGDemuxable>)newDemuxerWithSharedDemuxer:(id<SGDemuxable>)demuxer
50 | {
51 |     NSAssert(NO, @"Subclass only.");
52 |     return nil;
53 | }
54 | 
55 | @end
56 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGTrack+Internal.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGTrack+Internal.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/23.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGTrack.h"
10 | #import "SGFFmpeg.h"
11 | #import "SGMutableTrack.h"
12 | 
13 | @interface SGTrack ()
14 | 
15 | /*!
16 |  @method initWithType:index:
17 |  @abstract
18 |     Initializes an SGTrack.
19 |  */
20 | - (instancetype)initWithType:(SGMediaType)type index:(NSInteger)index;
21 | 
22 | /*!
23 |  @property core
24 |  @abstract
25 |     Indicates the pointer to the AVStream.
26 | */
27 | @property (nonatomic) AVStream *core;
28 | 
29 | @end
30 | 
31 | @interface SGMutableTrack ()
32 | 
33 | /*!
34 |  @property subTracks
35 |  @abstract
36 |     Indicates the sub tracks.
37 |  */
38 | @property (nonatomic, copy) NSArray<SGTrack *> *subTracks;
39 | 
40 | @end
41 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGTrack.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGTrack.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/17.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGDefines.h"
11 | 
12 | @interface SGTrack : NSObject <NSCopying>
13 | 
14 | + (instancetype)new NS_UNAVAILABLE;
15 | - (instancetype)init NS_UNAVAILABLE;
16 | 
17 | /*!
18 |  @property coreptr
19 |  @abstract
20 |     Indicates the pointer to the AVStream.
21 |  */
22 | @property (nonatomic, readonly) void *coreptr;
23 | 
24 | /*!
25 |  @property type
26 |  @abstract
27 |     Indicates the track media type.
28 |  */
29 | @property (nonatomic, readonly) SGMediaType type;
30 | 
31 | /*!
32 |  @property type
33 |  @abstract
34 |     Indicates the track index.
35 |  */
36 | @property (nonatomic, readonly) NSInteger index;
37 | 
38 | /*!
39 |  @method trackWithTracks:type:
40 |  @abstract
41 |    Get track with media type.
42 | */
43 | + (SGTrack *)trackWithTracks:(NSArray<SGTrack *> *)tracks type:(SGMediaType)type;
44 | 
45 | /*!
46 |  @method trackWithTracks:index:
47 |  @abstract
48 |    Get track with index.
49 | */
50 | + (SGTrack *)trackWithTracks:(NSArray<SGTrack *> *)tracks index:(NSInteger)index;
51 | 
52 | /*!
53 |  @method tracksWithTracks:type:
54 |  @abstract
55 |    Get tracks with media types.
56 | */
57 | + (NSArray<SGTrack *> *)tracksWithTracks:(NSArray<SGTrack *> *)tracks type:(SGMediaType)type;
58 | 
59 | @end
60 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGTrack.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGTrack.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/17.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGTrack.h"
10 | #import "SGTrack+Internal.h"
11 | 
12 | @implementation SGTrack
13 | 
14 | - (id)copyWithZone:(NSZone *)zone
15 | {
16 |     SGTrack *obj = [[self.class alloc] init];
17 |     obj->_type = self->_type;
18 |     obj->_index = self->_index;
19 |     obj->_core = self->_core;
20 |     return obj;
21 | }
22 | 
23 | - (instancetype)initWithType:(SGMediaType)type index:(NSInteger)index
24 | {
25 |     if (self = [super init]) {
26 |         self->_type = type;
27 |         self->_index = index;
28 |     }
29 |     return self;
30 | }
31 | 
32 | - (void *)coreptr
33 | {
34 |     return self->_core;
35 | }
36 | 
37 | + (SGTrack *)trackWithTracks:(NSArray<SGTrack *> *)tracks type:(SGMediaType)type
38 | {
39 |     for (SGTrack *obj in tracks) {
40 |         if (obj.type == type) {
41 |             return obj;
42 |         }
43 |     }
44 |     return nil;
45 | }
46 | 
47 | + (SGTrack *)trackWithTracks:(NSArray<SGTrack *> *)tracks index:(NSInteger)index
48 | {
49 |     for (SGTrack *obj in tracks) {
50 |         if (obj.index == index) {
51 |             return obj;
52 |         }
53 |     }
54 |     return nil;
55 | }
56 | 
57 | + (NSArray<SGTrack *> *)tracksWithTracks:(NSArray<SGTrack *> *)tracks type:(SGMediaType)type
58 | {
59 |     NSMutableArray *array = [NSMutableArray array];
60 |     for (SGTrack *obj in tracks) {
61 |         if (obj.type == type) {
62 |             [array addObject:obj];
63 |         }
64 |     }
65 |     return array.count ? [array copy] : nil;
66 | }
67 | 
68 | @end
69 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGTrackSelection.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGTrackSelection.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/8/13.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGTrack.h"
11 | 
12 | typedef NS_OPTIONS(NSUInteger, SGTrackSelectionAction) {
13 |     SGTrackSelectionActionTracks  = 1 << 0,
14 |     SGTrackSelectionActionWeights = 1 << 1,
15 | };
16 | 
17 | @interface SGTrackSelection : NSObject <NSCopying>
18 | 
19 | /*!
20 |  @property tracks
21 |  @abstract
22 |     Provides array of SGTrackSelection tracks.
23 |  */
24 | @property (nonatomic, copy) NSArray<SGTrack *> *tracks;
25 | 
26 | /*!
27 |  @property weights
28 |  @abstract
29 |     Provides array of SGTrackSelection weights.
30 |  */
31 | @property (nonatomic, copy) NSArray<NSNumber *> *weights;
32 | 
33 | @end
34 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGTrackSelection.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGTrackSelection.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/8/13.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGTrackSelection.h"
10 | 
11 | @implementation SGTrackSelection
12 | 
13 | - (id)copyWithZone:(NSZone *)zone
14 | {
15 |     SGTrackSelection *obj = [[SGTrackSelection alloc] init];
16 |     obj->_tracks = self->_tracks;
17 |     obj->_weights = self->_weights;
18 |     return obj;
19 | }
20 | 
21 | @end
22 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGURLAsset.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGURLAsset.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/9/19.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGAsset.h"
10 | 
11 | @interface SGURLAsset : SGAsset
12 | 
13 | + (instancetype)new NS_UNAVAILABLE;
14 | - (instancetype)init NS_UNAVAILABLE;
15 | 
16 | /*!
17 |  @method initWithURL:
18 |  @abstract
19 |     Initializes an SGURLAsset with the given URL.
20 |  */
21 | - (instancetype)initWithURL:(NSURL *)URL;
22 | 
23 | /*!
24 |  @property URL
25 |  @abstract
26 |     Indicates the URL of the asset.
27 |  */
28 | @property (nonatomic, copy, readonly) NSURL *URL;
29 | 
30 | @end
31 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGURLAsset.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGURLAsset.m
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/9/19.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGURLAsset.h"
10 | #import "SGAsset+Internal.h"
11 | #import "SGURLDemuxer.h"
12 | 
13 | @implementation SGURLAsset
14 | 
15 | - (id)copyWithZone:(NSZone *)zone
16 | {
17 |     SGURLAsset *obj = [super copyWithZone:zone];
18 |     obj->_URL = [self->_URL copy];
19 |     return obj;
20 | }
21 | 
22 | - (instancetype)initWithURL:(NSURL *)URL
23 | {
24 |     if (self = [super init]) {
25 |         self->_URL = [URL copy];
26 |     }
27 |     return self;
28 | }
29 | 
30 | - (id<SGDemuxable>)newDemuxer
31 | {
32 |     return [[SGURLDemuxer alloc] initWithURL:self->_URL];
33 | }
34 | 
35 | @end
36 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGURLSegment.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGURLSegment.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/14.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGSegment.h"
10 | 
11 | @interface SGURLSegment : SGSegment
12 | 
13 | + (instancetype)new NS_UNAVAILABLE;
14 | - (instancetype)init NS_UNAVAILABLE;
15 | 
16 | /*!
17 |  @method initWithURL:index:timeRange:scale:
18 |  @abstract
19 |     Initializes an SGURLSegment.
20 |  */
21 | - (instancetype)initWithURL:(NSURL *)URL index:(NSInteger)index timeRange:(CMTimeRange)timeRange scale:(CMTime)scale;
22 | 
23 | /*!
24 |  @property URL
25 |  @abstract
26 |     Indicates the URL of the segment.
27 |  */
28 | @property (nonatomic, copy, readonly) NSURL *URL;
29 | 
30 | /*!
31 |  @property type
32 |  @abstract
33 |     Indicates the index.
34 |  */
35 | @property (nonatomic, readonly) NSInteger index;
36 | 
37 | /*!
38 |  @property timeRange
39 |  @abstract
40 |     Indicates the timeRange of the segment.
41 |  */
42 | @property (nonatomic, readonly) CMTimeRange timeRange;
43 | 
44 | /*!
45 |  @property scale
46 |  @abstract
47 |     Indicates the scale of the segment.
48 |  */
49 | @property (nonatomic, readonly) CMTime scale;
50 | 
51 | @end
52 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAsset/SGURLSegment.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGURLSegment.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/14.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGURLSegment.h"
10 | #import "SGSegment+Internal.h"
11 | #import "SGExtractingDemuxer.h"
12 | #import "SGURLDemuxer.h"
13 | #import "SGTime.h"
14 | 
15 | @implementation SGURLSegment
16 | 
17 | - (id)copyWithZone:(NSZone *)zone
18 | {
19 |     SGURLSegment *obj = [super copyWithZone:zone];
20 |     obj->_URL = [self->_URL copy];
21 |     obj->_index = self->_index;
22 |     obj->_timeRange = self->_timeRange;
23 |     obj->_scale = self->_scale;
24 |     return obj;
25 | }
26 | 
27 | - (instancetype)initWithURL:(NSURL *)URL index:(NSInteger)index timeRange:(CMTimeRange)timeRange scale:(CMTime)scale
28 | {
29 |     scale = SGCMTimeValidate(scale, CMTimeMake(1, 1), NO);
30 |     NSAssert(CMTimeCompare(scale, CMTimeMake(1, 10)) >= 0, @"Invalid Scale.");
31 |     NSAssert(CMTimeCompare(scale, CMTimeMake(10, 1)) <= 0, @"Invalid Scale.");
32 |     if (self = [super init]) {
33 |         self->_URL = [URL copy];
34 |         self->_index = index;
35 |         self->_timeRange = timeRange;
36 |         self->_scale = scale;
37 |     }
38 |     return self;
39 | }
40 | 
41 | - (NSString *)sharedDemuxerKey
42 | {
43 |     return self->_URL.isFileURL ? self->_URL.path : self->_URL.absoluteString;
44 | }
45 | 
46 | - (id<SGDemuxable>)newDemuxer
47 | {
48 |     return [self newDemuxerWithSharedDemuxer:nil];
49 | }
50 | 
51 | - (id<SGDemuxable>)newDemuxerWithSharedDemuxer:(id<SGDemuxable>)demuxer
52 | {
53 |     if (!demuxer) {
54 |         demuxer = [[SGURLDemuxer alloc] initWithURL:self->_URL];
55 |     }
56 |     SGExtractingDemuxer *obj = [[SGExtractingDemuxer alloc] initWithDemuxable:demuxer index:self->_index timeRange:self->_timeRange scale:self->_scale];
57 |     return obj;
58 | }
59 | 
60 | @end
61 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGAudio/SGAudioPlayer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioPlayer.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/16.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import <AudioToolbox/AudioToolbox.h>
11 | 
12 | @class SGAudioPlayer;
13 | 
14 | @protocol SGAudioPlayerDelegate <NSObject>
15 | 
16 | /**
17 |  *
18 |  */
19 | - (void)audioPlayer:(SGAudioPlayer *)player render:(const AudioTimeStamp *)timeStamp data:(AudioBufferList *)data numberOfFrames:(UInt32)numberOfFrames;
20 | 
21 | @optional
22 | /**
23 |  *
24 |  */
25 | - (void)audioPlayer:(SGAudioPlayer *)player willRender:(const AudioTimeStamp *)timestamp;
26 | 
27 | /**
28 |  *
29 |  */
30 | - (void)audioPlayer:(SGAudioPlayer *)player didRender:(const AudioTimeStamp *)timestamp;
31 | 
32 | @end
33 | 
34 | @interface SGAudioPlayer : NSObject
35 | 
36 | /**
37 |  *  Delegate.
38 |  */
39 | @property (nonatomic, weak) id<SGAudioPlayerDelegate> delegate;
40 | 
41 | /**
42 |  *  Rate.
43 |  */
44 | @property (nonatomic) float rate;
45 | 
46 | /**
47 |  *  Pitch.
48 |  */
49 | @property (nonatomic) float pitch;
50 | 
51 | /**
52 |  *  Volume.
53 |  */
54 | @property (nonatomic) float volume;
55 | 
56 | /**
57 |  *  ASBD.
58 |  */
59 | @property (nonatomic) AudioStreamBasicDescription asbd;
60 | 
61 | /**
62 |  *  Playback.
63 |  */
64 | - (BOOL)isPlaying;
65 | 
66 | /**
67 |  *  Play.
68 |  */
69 | - (void)play;
70 | 
71 | /**
72 |  *  Pause.
73 |  */
74 | - (void)pause;
75 | 
76 | /**
77 |  *  Flush.
78 |  */
79 | - (void)flush;
80 | 
81 | @end
82 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGCommon/SGActivity.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPlayerActivity.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/10.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | 
11 | @interface SGActivity : NSObject
12 | 
13 | /**
14 |  *
15 |  */
16 | + (void)addTarget:(id)target;
17 | 
18 | /**
19 |  *
20 |  */
21 | + (void)removeTarget:(id)target;
22 | 
23 | @end
24 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGCommon/SGActivity.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPlayerActivity.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/10.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGActivity.h"
10 | 
11 | @interface SGActivity ()
12 | 
13 | @property (nonatomic, strong, readonly) NSLock *lock;
14 | @property (nonatomic, strong, readonly) NSMutableSet *targets;
15 | 
16 | @end
17 | 
18 | @implementation SGActivity
19 | 
20 | + (void)addTarget:(id)target
21 | {
22 |     [[SGActivity activity] addTarget:target];
23 | }
24 | 
25 | + (void)removeTarget:(id)target
26 | {
27 |     [[SGActivity activity] removeTarget:target];
28 | }
29 | 
30 | + (instancetype)activity
31 | {
32 |     static SGActivity *obj = nil;
33 |     static dispatch_once_t onceToken;
34 |     dispatch_once(&onceToken, ^{
35 |         obj = [[SGActivity alloc] init];
36 |     });
37 |     return obj;
38 | }
39 | 
40 | - (instancetype)init
41 | {
42 |     if (self = [super init]) {
43 |         self->_lock = [[NSLock alloc] init];
44 |         self->_targets = [NSMutableSet set];
45 |     }
46 |     return self;
47 | }
48 | 
49 | - (void)addTarget:(id)target
50 | {
51 |     if (!target) {
52 |         return;
53 |     }
54 |     [self->_lock lock];
55 |     if (![self->_targets containsObject:[self token:target]]) {
56 |         [self->_targets addObject:[self token:target]];
57 |     }
58 |     [self reload];
59 |     [self->_lock unlock];
60 | }
61 | 
62 | - (void)removeTarget:(id)target
63 | {
64 |     if (!target) {
65 |         return;
66 |     }
67 |     [self->_lock lock];
68 |     if ([self->_targets containsObject:[self token:target]]) {
69 |         [self->_targets removeObject:[self token:target]];
70 |     }
71 |     [self reload];
72 |     [self->_lock unlock];
73 | }
74 | 
75 | - (void)reload
76 | {
77 | #if SGPLATFORM_TARGET_OS_IPHONE_OR_TV
78 |     BOOL disable = self.objects.count <= 0;
79 |     dispatch_async(dispatch_get_main_queue(), ^{
80 |         [UIApplication sharedApplication].idleTimerDisabled = disable;
81 |     });
82 | #endif
83 | }
84 | 
85 | - (id)token:(id)target
86 | {
87 |     return [NSString stringWithFormat:@"%p", target];
88 | }
89 | 
90 | @end
91 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGCommon/SGDefines.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGDefines.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/6/25.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import <CoreMedia/CoreMedia.h>
11 | 
12 | #if defined(__cplusplus)
13 | #define SGPLAYER_EXTERN extern "C"
14 | #else
15 | #define SGPLAYER_EXTERN extern
16 | #endif
17 | 
18 | typedef NS_ENUM(NSUInteger, SGMediaType) {
19 |     SGMediaTypeUnknown  = 0,
20 |     SGMediaTypeAudio    = 1,
21 |     SGMediaTypeVideo    = 2,
22 |     SGMediaTypeSubtitle = 3,
23 | };
24 | 
25 | typedef NS_ENUM(NSUInteger, SGPlayerState) {
26 |     SGPlayerStateNone      = 0,
27 |     SGPlayerStatePreparing = 1,
28 |     SGPlayerStateReady     = 2,
29 |     SGPlayerStateFailed    = 3,
30 | };
31 | 
32 | typedef NS_OPTIONS(NSUInteger, SGPlaybackState) {
33 |     SGPlaybackStateNone     = 0,
34 |     SGPlaybackStatePlaying  = 1 << 0,
35 |     SGPlaybackStateSeeking  = 1 << 1,
36 |     SGPlaybackStateFinished = 1 << 2,
37 | };
38 | 
39 | typedef NS_ENUM(NSUInteger, SGLoadingState) {
40 |     SGLoadingStateNone     = 0,
41 |     SGLoadingStatePlaybale = 1,
42 |     SGLoadingStateStalled  = 2,
43 |     SGLoadingStateFinished = 3,
44 | };
45 | 
46 | typedef NS_OPTIONS(NSUInteger, SGInfoAction) {
47 |     SGInfoActionNone          = 0,
48 |     SGInfoActionTimeCached    = 1 << 1,
49 |     SGInfoActionTimePlayback  = 1 << 2,
50 |     SGInfoActionTimeDuration  = 1 << 3,
51 |     SGInfoActionTime          = SGInfoActionTimeCached | SGInfoActionTimePlayback | SGInfoActionTimeDuration,
52 |     SGInfoActionStatePlayer   = 1 << 4,
53 |     SGInfoActionStateLoading  = 1 << 5,
54 |     SGInfoActionStatePlayback = 1 << 6,
55 |     SGInfoActionState         = SGInfoActionStatePlayer | SGInfoActionStateLoading | SGInfoActionStatePlayback,
56 | };
57 | 
58 | typedef struct {
59 |     int num;
60 |     int den;
61 | } SGRational;
62 | 
63 | typedef struct {
64 |     CMTime cached;
65 |     CMTime playback;
66 |     CMTime duration;
67 | } SGTimeInfo;
68 | 
69 | typedef struct {
70 |     SGPlayerState player;
71 |     SGLoadingState loading;
72 |     SGPlaybackState playback;
73 | } SGStateInfo;
74 | 
75 | @class SGPlayer;
76 | 
77 | typedef void (^SGBlock)(void);
78 | typedef void (^SGHandler)(SGPlayer *player);
79 | typedef BOOL (^SGTimeReader)(CMTime *desire, BOOL *drop);
80 | typedef void (^SGSeekResult)(CMTime time, NSError *error);
81 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGCommon/SGError.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGError.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/16.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | 
11 | typedef NS_ENUM(NSUInteger, SGErrorCode) {
12 |     SGErrorCodeUnknown = 0,
13 |     SGErrorImmediateExitRequested,
14 |     SGErrorCodeNoValidFormat,
15 |     SGErrorCodeFormatNotSeekable,
16 |     SGErrorCodePacketOutputCancelSeek,
17 |     SGErrorCodeDemuxerEndOfFile,
18 |     SGErrorCodeInvlidTime,
19 | };
20 | 
21 | typedef NS_ENUM(NSUInteger, SGActionCode) {
22 |     SGActionCodeUnknown = 0,
23 |     SGActionCodeFormatCreate,
24 |     SGActionCodeFormatOpenInput,
25 |     SGActionCodeFormatFindStreamInfo,
26 |     SGActionCodeFormatSeekFrame,
27 |     SGActionCodeFormatReadFrame,
28 |     SGActionCodeFormatGetSeekable,
29 |     SGActionCodeCodecSetParametersToContext,
30 |     SGActionCodeCodecOpen2,
31 |     SGActionCodePacketOutputSeek,
32 |     SGActionCodeURLDemuxerFunnelNext,
33 |     SGActionCodeMutilDemuxerNext,
34 |     SGActionCodeSegmentDemuxerNext,
35 |     SGActionCodeNextFrame,
36 | };
37 | 
38 | NSError * SGGetFFError(int result, SGActionCode operation);
39 | NSError * SGCreateError(NSUInteger code, SGActionCode operation);
40 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGCommon/SGError.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGError.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/16.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGError.h"
10 | #import "SGFFmpeg.h"
11 | 
12 | static NSString * const SGErrorUserInfoKeyOperation = @"SGErrorUserInfoKeyOperation";
13 | 
14 | NSError * SGGetFFError(int result, SGActionCode operation)
15 | {
16 |     if (result >= 0) {
17 |         return nil;
18 |     }
19 |     char *data = malloc(256);
20 |     av_strerror(result, data, 256);
21 |     NSString *domain = [NSString stringWithFormat:@"SGPlayer-Error-FFmpeg code : %d, msg : %s", result, data];
22 |     free(data);
23 |     if (result == AVERROR_EXIT) {
24 |         result = SGErrorImmediateExitRequested;
25 |     } else if (result == AVERROR_EOF) {
26 |         result = SGErrorCodeDemuxerEndOfFile;
27 |     }
28 |     return [NSError errorWithDomain:domain code:result userInfo:@{SGErrorUserInfoKeyOperation : @(operation)}];
29 | }
30 | 
31 | NSError * SGCreateError(NSUInteger code, SGActionCode operation)
32 | {
33 |     return [NSError errorWithDomain:@"SGPlayer-Error-SGErrorCode" code:(NSInteger)code userInfo:@{SGErrorUserInfoKeyOperation : @(operation)}];
34 | }
35 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGCommon/SGLock.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGLock.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/29.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGDefines.h"
11 | 
12 | BOOL SGLockEXE00(id<NSLocking> locking, void (^run)(void));
13 | BOOL SGLockEXE10(id<NSLocking> locking, SGBlock (^run)(void));
14 | BOOL SGLockEXE11(id<NSLocking> locking, SGBlock (^run)(void), BOOL (^finish)(SGBlock block));
15 | 
16 | BOOL SGLockCondEXE00(id<NSLocking> locking, BOOL (^verify)(void), void (^run)(void));
17 | BOOL SGLockCondEXE10(id<NSLocking> locking, BOOL (^verify)(void), SGBlock (^run)(void));
18 | BOOL SGLockCondEXE11(id<NSLocking> locking, BOOL (^verify)(void), SGBlock (^run)(void), BOOL (^finish)(SGBlock block));
19 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGCommon/SGLock.m:
--------------------------------------------------------------------------------
  1 | //
  2 | //  SGLock.m
  3 | //  SGPlayer iOS
  4 | //
  5 | //  Created by Single on 2018/10/29.
  6 | //  Copyright © 2018 single. All rights reserved.
  7 | //
  8 | 
  9 | #import "SGLock.h"
 10 | 
 11 | BOOL SGLockEXE00(id<NSLocking> locking, void (^run)(void))
 12 | {
 13 |     [locking lock];
 14 |     if (run) {
 15 |         run();
 16 |     }
 17 |     [locking unlock];
 18 |     return YES;
 19 | }
 20 | 
 21 | BOOL SGLockEXE10(id<NSLocking> locking, SGBlock (^run)(void))
 22 | {
 23 |     [locking lock];
 24 |     SGBlock r = nil;
 25 |     if (run) {
 26 |         r = run();
 27 |     }
 28 |     [locking unlock];
 29 |     if (r) {
 30 |         r();
 31 |     }
 32 |     return YES;
 33 | }
 34 | 
 35 | BOOL SGLockEXE11(id<NSLocking> locking, SGBlock (^run)(void), BOOL (^finish)(SGBlock block))
 36 | {
 37 |     [locking lock];
 38 |     SGBlock r = nil;
 39 |     if (run) {
 40 |         r = run();
 41 |     }
 42 |     [locking unlock];
 43 |     if (finish) {
 44 |         return finish(r ? r : ^{});
 45 |     } else if (r) {
 46 |         r();
 47 |     }
 48 |     return YES;
 49 | }
 50 | 
 51 | BOOL SGLockCondEXE00(id<NSLocking> locking, BOOL (^verify)(void), void (^run)(void))
 52 | {
 53 |     [locking lock];
 54 |     BOOL s = YES;
 55 |     if (verify) {
 56 |         s = verify();
 57 |     }
 58 |     if (!s) {
 59 |         [locking unlock];
 60 |         return NO;
 61 |     }
 62 |     if (run) {
 63 |         run();
 64 |     }
 65 |     [locking unlock];
 66 |     return YES;
 67 | }
 68 | 
 69 | BOOL SGLockCondEXE10(id<NSLocking> locking, BOOL (^verify)(void), SGBlock (^run)(void))
 70 | {
 71 |     [locking lock];
 72 |     BOOL s = YES;
 73 |     if (verify) {
 74 |         s = verify();
 75 |     }
 76 |     if (!s) {
 77 |         [locking unlock];
 78 |         return NO;
 79 |     }
 80 |     SGBlock r = nil;
 81 |     if (run) {
 82 |         r = run();
 83 |     }
 84 |     [locking unlock];
 85 |     if (r) {
 86 |         r();
 87 |     }
 88 |     return YES;
 89 | }
 90 | 
 91 | BOOL SGLockCondEXE11(id<NSLocking> locking, BOOL (^verify)(void), SGBlock (^run)(void), BOOL (^finish)(SGBlock block))
 92 | {
 93 |     [locking lock];
 94 |     BOOL s = YES;
 95 |     if (verify) {
 96 |         s = verify();
 97 |     }
 98 |     if (!s) {
 99 |         [locking unlock];
100 |         return NO;
101 |     }
102 |     SGBlock r = nil;
103 |     if (run) {
104 |         r = run();
105 |     }
106 |     [locking unlock];
107 |     if (finish) {
108 |         return finish(r ? r : ^{});
109 |     } else if (r) {
110 |         r();
111 |     }
112 |     return YES;
113 | }
114 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGCommon/SGTime.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGTime.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/6/13.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import <CoreMedia/CoreMedia.h>
11 | 
12 | BOOL SGCMTimeIsValid(CMTime time, BOOL infinity);
13 | 
14 | CMTime SGCMTimeValidate(CMTime time, CMTime defaultTime, BOOL infinity);
15 | CMTime SGCMTimeMakeWithSeconds(Float64 seconds);
16 | CMTime SGCMTimeMultiply(CMTime time, CMTime multiplier);
17 | CMTime SGCMTimeDivide(CMTime time, CMTime divisor);
18 | CMTime SGCMTimeDivide(CMTime time, CMTime divisor);
19 | 
20 | CMTimeRange SGCMTimeRangeFitting(CMTimeRange timeRange);
21 | CMTimeRange SGCMTimeRangeGetIntersection(CMTimeRange timeRange1, CMTimeRange timeRange2);
22 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGContainer/SGObjectPool.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGObjectPool.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/22.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGData.h"
11 | 
12 | @interface SGObjectPool : NSObject
13 | 
14 | + (instancetype)sharedPool;
15 | 
16 | /**
17 |  *
18 |  */
19 | - (__kindof id<SGData>)objectWithClass:(Class)class reuseName:(NSString *)reuseName;
20 | 
21 | /**
22 |  *
23 |  */
24 | - (void)comeback:(id<SGData>)object;
25 | 
26 | /**
27 |  *
28 |  */
29 | - (void)flush;
30 | 
31 | @end
32 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGContainer/SGObjectPool.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGObjectPool.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/22.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGObjectPool.h"
10 | 
11 | @interface SGObjectPool ()
12 | 
13 | @property (nonatomic, strong, readonly) NSLock *lock;
14 | @property (nonatomic, strong, readonly) NSMutableDictionary<NSString *, NSMutableSet<id<SGData>> *> *pool;
15 | 
16 | @end
17 | 
18 | @implementation SGObjectPool
19 | 
20 | + (instancetype)sharedPool
21 | {
22 |     static SGObjectPool *obj = nil;
23 |     static dispatch_once_t onceToken;
24 |     dispatch_once(&onceToken, ^{
25 |         obj = [[SGObjectPool alloc] init];
26 |     });
27 |     return obj;
28 | }
29 | 
30 | - (instancetype)init
31 | {
32 |     if (self = [super init]) {
33 |         self->_lock = [[NSLock alloc] init];
34 |         self->_pool = [NSMutableDictionary dictionary];
35 |     }
36 |     return self;
37 | }
38 | 
39 | - (id<SGData>)objectWithClass:(Class)class reuseName:(NSString *)reuseName
40 | {
41 |     [self->_lock lock];
42 |     NSMutableSet <id<SGData>> *set = [self->_pool objectForKey:reuseName];
43 |     if (!set) {
44 |         set = [NSMutableSet set];
45 |         [self->_pool setObject:set forKey:reuseName];
46 |     }
47 |     id<SGData> object = set.anyObject;
48 |     if (object) {
49 |         [set removeObject:object];
50 |     } else {
51 |         object = [[class alloc] init];
52 |     }
53 |     [object lock];
54 |     object.reuseName = reuseName;
55 |     [self->_lock unlock];
56 |     return object;
57 | }
58 | 
59 | - (void)comeback:(id<SGData>)object
60 | {
61 |     [self->_lock lock];
62 |     NSMutableSet <id<SGData>> *set = [self->_pool objectForKey:object.reuseName];
63 |     if (![set containsObject:object]) {
64 |         [set addObject:object];
65 |         [object clear];
66 |     }
67 |     [self->_lock unlock];
68 | }
69 | 
70 | - (void)flush
71 | {
72 |     [self->_lock lock];
73 |     [self->_pool removeAllObjects];
74 |     [self->_lock unlock];
75 | }
76 | 
77 | @end
78 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGContainer/SGObjectQueue.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGObjectQueue.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/22.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGCapacity.h"
11 | #import "SGDefines.h"
12 | #import "SGData.h"
13 | 
14 | @interface SGObjectQueue : NSObject
15 | 
16 | /**
17 |  *
18 |  */
19 | - (instancetype)initWithMaxCount:(uint64_t)maxCount;
20 | 
21 | /**
22 |  *
23 |  */
24 | @property (nonatomic) BOOL shouldSortObjects;
25 | 
26 | /**
27 |  *
28 |  */
29 | - (SGCapacity)capacity;
30 | 
31 | /**
32 |  *
33 |  */
34 | - (BOOL)putObjectSync:(id<SGData>)object;
35 | - (BOOL)putObjectSync:(id<SGData>)object before:(SGBlock)before after:(SGBlock)after;
36 | 
37 | /**
38 |  *
39 |  */
40 | - (BOOL)putObjectAsync:(id<SGData>)object;
41 | 
42 | /**
43 |  *
44 |  */
45 | - (BOOL)getObjectSync:(id<SGData> *)object;
46 | - (BOOL)getObjectSync:(id<SGData> *)object before:(SGBlock)before after:(SGBlock)after;
47 | 
48 | /**
49 |  *
50 |  */
51 | - (BOOL)getObjectAsync:(id<SGData> *)object;
52 | - (BOOL)getObjectAsync:(id<SGData> *)object timeReader:(SGTimeReader)timeReader discarded:(uint64_t *)discarded;
53 | 
54 | /**
55 |  *
56 |  */
57 | - (BOOL)flush;
58 | 
59 | /**
60 |  *
61 |  */
62 | - (BOOL)destroy;
63 | 
64 | @end
65 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGAudioFrame.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioFrame.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/19.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGFrame.h"
10 | #import "SGAudioDescriptor.h"
11 | 
12 | @interface SGAudioFrame : SGFrame
13 | 
14 | /**
15 |  *
16 |  */
17 | @property (nonatomic, strong, readonly) SGAudioDescriptor *descriptor;
18 | 
19 | /**
20 |  *
21 |  */
22 | @property (nonatomic, readonly) int numberOfSamples;
23 | 
24 | /**
25 |  *
26 |  */
27 | - (int *)linesize;
28 | 
29 | /**
30 |  *
31 |  */
32 | - (uint8_t **)data;
33 | 
34 | @end
35 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGCapacity.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGCapacity.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/25.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGTime.h"
11 | 
12 | typedef struct SGCapacity {
13 |     int size;
14 |     int count;
15 |     CMTime duration;
16 | } SGCapacity;
17 | 
18 | SGCapacity SGCapacityCreate(void);
19 | SGCapacity SGCapacityAdd(SGCapacity c1, SGCapacity c2);
20 | SGCapacity SGCapacityMinimum(SGCapacity c1, SGCapacity c2);
21 | SGCapacity SGCapacityMaximum(SGCapacity c1, SGCapacity c2);
22 | 
23 | BOOL SGCapacityIsEqual(SGCapacity c1, SGCapacity c2);
24 | BOOL SGCapacityIsEnough(SGCapacity c1);
25 | BOOL SGCapacityIsEmpty(SGCapacity c1);
26 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGCapacity.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGCapacity.m
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/25.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGCapacity.h"
10 | 
11 | SGCapacity SGCapacityCreate(void)
12 | {
13 |     SGCapacity ret;
14 |     ret.size = 0;
15 |     ret.count = 0;
16 |     ret.duration = kCMTimeZero;
17 |     return ret;
18 | }
19 | 
20 | SGCapacity SGCapacityAdd(SGCapacity c1, SGCapacity c2)
21 | {
22 |     SGCapacity ret = SGCapacityCreate();
23 |     ret.size = c1.size + c2.size;
24 |     ret.count = c1.count + c2.count;
25 |     ret.duration = CMTimeAdd(c1.duration, c2.duration);
26 |     return ret;
27 | }
28 | 
29 | SGCapacity SGCapacityMinimum(SGCapacity c1, SGCapacity c2)
30 | {
31 |     if (CMTimeCompare(c1.duration, c2.duration) < 0) {
32 |         return c1;
33 |     } else if (CMTimeCompare(c1.duration, c2.duration) > 0) {
34 |         return c1;
35 |     }
36 |     if (c1.count < c2.count) {
37 |         return c1;
38 |     } else if (c1.count > c2.count) {
39 |         return c2;
40 |     }
41 |     if (c1.size < c2.size) {
42 |         return c1;
43 |     } else if (c1.size > c2.size) {
44 |         return c2;
45 |     }
46 |     return c1;
47 | }
48 | 
49 | SGCapacity SGCapacityMaximum(SGCapacity c1, SGCapacity c2)
50 | {
51 |     if (CMTimeCompare(c1.duration, c2.duration) < 0) {
52 |         return c2;
53 |     } else if (CMTimeCompare(c1.duration, c2.duration) > 0) {
54 |         return c1;
55 |     }
56 |     if (c1.count < c2.count) {
57 |         return c2;
58 |     } else if (c1.count > c2.count) {
59 |         return c1;
60 |     }
61 |     if (c1.size < c2.size) {
62 |         return c2;
63 |     } else if (c1.size > c2.size) {
64 |         return c1;
65 |     }
66 |     return c1;
67 | }
68 | 
69 | BOOL SGCapacityIsEqual(SGCapacity c1, SGCapacity c2)
70 | {
71 |     return
72 |     c1.size == c2.size &&
73 |     c1.count == c2.count &&
74 |     CMTimeCompare(c1.duration, c2.duration) == 0;
75 | }
76 | 
77 | BOOL SGCapacityIsEnough(SGCapacity c1)
78 | {
79 |     /*
80 |     return
81 |     c1.count >= 30 &&
82 |     CMTimeCompare(c1.duration, CMTimeMake(1, 1)) > 0;
83 |      */
84 |     return
85 |     c1.count >= 50000;
86 | }
87 | 
88 | BOOL SGCapacityIsEmpty(SGCapacity c1)
89 | {
90 |     return
91 |     c1.size == 0 &&
92 |     c1.count == 0 &&
93 |     (CMTIME_IS_INVALID(c1.duration) ||
94 |      CMTimeCompare(c1.duration, kCMTimeZero) == 0);
95 | }
96 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGData.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGDemuxable.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/9/25.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import <CoreMedia/CoreMedia.h>
11 | 
12 | /**
13 |  *
14 |  */
15 | typedef NS_OPTIONS(NSUInteger, SGDataFlags) {
16 |     SGDataFlagPadding = 1 << 0,
17 | };
18 | 
19 | @protocol SGData <NSObject>
20 | 
21 | /**
22 |  *
23 |  */
24 | @property (nonatomic) SGDataFlags flags;
25 | 
26 | /**
27 |  *
28 |  */
29 | @property (nonatomic, copy) NSString *reuseName;
30 | 
31 | /**
32 |  *
33 |  */
34 | - (void)lock;
35 | 
36 | /**
37 |  *
38 |  */
39 | - (void)unlock;
40 | 
41 | /**
42 |  *
43 |  */
44 | - (void)clear;
45 | 
46 | /**
47 |  *
48 |  */
49 | - (CMTime)duration;
50 | 
51 | /**
52 |  *
53 |  */
54 | - (CMTime)timeStamp;
55 | 
56 | /**
57 |  *
58 |  */
59 | - (int)size;
60 | 
61 | @end
62 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGFrame+Internal.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGFrame+Internal.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/23.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGFrame.h"
10 | #import "SGAudioFrame.h"
11 | #import "SGVideoFrame.h"
12 | #import "SGCodecDescriptor.h"
13 | 
14 | @interface SGFrame ()
15 | 
16 | /**
17 |  *
18 |  */
19 | + (instancetype)frame;
20 | 
21 | /**
22 |  *
23 |  */
24 | @property (nonatomic, readonly) AVFrame *core;
25 | 
26 | /**
27 |  *
28 |  */
29 | @property (nonatomic, strong) SGCodecDescriptor *codecDescriptor;
30 | 
31 | /**
32 |  *
33 |  */
34 | - (void)fill;
35 | 
36 | /**
37 |  *
38 |  */
39 | - (void)fillWithFrame:(SGFrame *)frame;
40 | 
41 | /**
42 |  *
43 |  */
44 | - (void)fillWithTimeStamp:(CMTime)timeStamp decodeTimeStamp:(CMTime)decodeTimeStamp duration:(CMTime)duration;
45 | 
46 | @end
47 | 
48 | @interface SGAudioFrame ()
49 | 
50 | /**
51 |  *
52 |  */
53 | + (instancetype)frameWithDescriptor:(SGAudioDescriptor *)descriptor numberOfSamples:(int)numberOfSamples;
54 | 
55 | @end
56 | 
57 | @interface SGVideoFrame ()
58 | 
59 | /**
60 |  *
61 |  */
62 | + (instancetype)frameWithDescriptor:(SGVideoDescriptor *)descriptor;
63 | 
64 | @end
65 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGFrame.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGFrame.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/18.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGTrack.h"
11 | #import "SGData.h"
12 | 
13 | static int const SGFramePlaneCount = 8;
14 | 
15 | @interface SGFrame : NSObject <SGData>
16 | 
17 | /**
18 |  *
19 |  */
20 | @property (nonatomic, readonly) void *coreptr;
21 | 
22 | /**
23 |  *
24 |  */
25 | @property (nonatomic, strong, readonly) SGTrack *track;
26 | 
27 | /**
28 |  *
29 |  */
30 | @property (nonatomic, strong, readonly) NSDictionary *metadata;
31 | 
32 | /**
33 |  *
34 |  */
35 | @property (nonatomic, readonly) CMTime duration;
36 | 
37 | /**
38 |  *
39 |  */
40 | @property (nonatomic, readonly) CMTime timeStamp;
41 | 
42 | /**
43 |  *
44 |  */
45 | @property (nonatomic, readonly) CMTime decodeTimeStamp;
46 | 
47 | /**
48 |  *
49 |  */
50 | @property (nonatomic, readonly) int size;
51 | 
52 | @end
53 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGPacket+Internal.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPacket+Internal.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/23.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPacket.h"
10 | #import "SGCodecDescriptor.h"
11 | 
12 | @interface SGPacket ()
13 | 
14 | /**
15 |  *
16 |  */
17 | + (instancetype)packet;
18 | 
19 | /**
20 |  *
21 |  */
22 | @property (nonatomic, readonly) AVPacket *core;
23 | 
24 | /**
25 |  *
26 |  */
27 | @property (nonatomic, strong) SGCodecDescriptor *codecDescriptor;
28 | 
29 | /**
30 |  *
31 |  */
32 | - (void)fill;
33 | 
34 | @end
35 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGPacket.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPacket.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/22.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGTrack.h"
11 | #import "SGData.h"
12 | 
13 | @interface SGPacket : NSObject <SGData>
14 | 
15 | /**
16 |  *
17 |  */
18 | @property (nonatomic, readonly) void *coreptr;
19 | 
20 | /**
21 |  *
22 |  */
23 | @property (nonatomic, strong, readonly) SGTrack *track;
24 | 
25 | /**
26 |  *
27 |  */
28 | @property (nonatomic, strong, readonly) NSDictionary *metadata;
29 | 
30 | /**
31 |  *
32 |  */
33 | @property (nonatomic, readonly) CMTime duration;
34 | 
35 | /**
36 |  *
37 |  */
38 | @property (nonatomic, readonly) CMTime timeStamp;
39 | 
40 | /**
41 |  *
42 |  */
43 | @property (nonatomic, readonly) CMTime decodeTimeStamp;
44 | 
45 | /**
46 |  *
47 |  */
48 | @property (nonatomic, readonly) int size;
49 | 
50 | @end
51 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGTimeLayout.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGTimeLayout.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/15.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGTime.h"
11 | 
12 | @interface SGTimeLayout : NSObject <NSCopying>
13 | 
14 | /**
15 |  *
16 |  */
17 | - (instancetype)initWithScale:(CMTime)scale;
18 | 
19 | /**
20 |  *
21 |  */
22 | - (instancetype)initWithOffset:(CMTime)offset;
23 | 
24 | /**
25 |  *
26 |  */
27 | @property (nonatomic, readonly) CMTime scale;
28 | 
29 | /**
30 |  *
31 |  */
32 | @property (nonatomic, readonly) CMTime offset;
33 | 
34 | /**
35 |  *
36 |  */
37 | - (CMTime)convertDuration:(CMTime)duration;
38 | 
39 | /**
40 |  *
41 |  */
42 | - (CMTime)convertTimeStamp:(CMTime)timeStamp;
43 | 
44 | /**
45 |  *
46 |  */
47 | - (CMTime)reconvertTimeStamp:(CMTime)timeStamp;
48 | 
49 | /**
50 |  *
51 |  */
52 | - (BOOL)isEqualToTimeLayout:(SGTimeLayout *)timeLayout;
53 | 
54 | @end
55 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGTimeLayout.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGTimeLayout.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/15.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGTimeLayout.h"
10 | 
11 | @implementation SGTimeLayout
12 | 
13 | - (id)copyWithZone:(NSZone *)zone
14 | {
15 |     SGTimeLayout *obj = [[SGTimeLayout alloc] init];
16 |     obj->_scale = self->_scale;
17 |     obj->_offset = self->_offset;
18 |     return obj;
19 | }
20 | 
21 | - (instancetype)initWithScale:(CMTime)scale
22 | {
23 |     if (self = [super init]) {
24 |         self->_scale = SGCMTimeValidate(scale, CMTimeMake(1, 1), NO);
25 |         self->_offset = kCMTimeInvalid;
26 |     }
27 |     return self;
28 | }
29 | 
30 | - (instancetype)initWithOffset:(CMTime)offset
31 | {
32 |     if (self = [super init]) {
33 |         self->_scale = kCMTimeInvalid;
34 |         self->_offset = SGCMTimeValidate(offset, kCMTimeZero, NO);
35 |     }
36 |     return self;
37 | }
38 | 
39 | - (CMTime)convertDuration:(CMTime)duration
40 | {
41 |     if (CMTIME_IS_NUMERIC(self->_scale)) {
42 |         duration = SGCMTimeMultiply(duration, self->_scale);
43 |     }
44 |     return duration;
45 | }
46 | 
47 | - (CMTime)convertTimeStamp:(CMTime)timeStamp
48 | {
49 |     if (CMTIME_IS_NUMERIC(self->_scale)) {
50 |         timeStamp = SGCMTimeMultiply(timeStamp, self->_scale);
51 |     }
52 |     if (CMTIME_IS_NUMERIC(self->_offset)) {
53 |         timeStamp = CMTimeAdd(timeStamp, self->_offset);
54 |     }
55 |     return timeStamp;
56 | }
57 | 
58 | - (CMTime)reconvertTimeStamp:(CMTime)timeStamp
59 | {
60 |     if (CMTIME_IS_NUMERIC(self->_scale)) {
61 |         timeStamp = SGCMTimeDivide(timeStamp, self->_scale);
62 |     }
63 |     if (CMTIME_IS_NUMERIC(self->_offset)) {
64 |         timeStamp = CMTimeSubtract(timeStamp, self->_offset);
65 |     }
66 |     return timeStamp;
67 | }
68 | 
69 | - (BOOL)isEqualToTimeLayout:(SGTimeLayout *)timeLayout
70 | {
71 |     if (!timeLayout) {
72 |         return NO;
73 |     }
74 |     if (CMTimeCompare(timeLayout->_scale, self->_scale) != 0) {
75 |         return NO;
76 |     }
77 |     if (CMTimeCompare(timeLayout->_offset, self->_offset) != 0) {
78 |         return NO;
79 |     }
80 |     return YES;
81 | }
82 | 
83 | @end
84 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGData/SGVideoFrame.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGVideoFrame.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/22.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGFrame.h"
10 | #import "SGPLFImage.h"
11 | #import "SGVideoDescriptor.h"
12 | 
13 | @interface SGVideoFrame : SGFrame
14 | 
15 | /**
16 |  *
17 |  */
18 | @property (nonatomic, strong, readonly) SGVideoDescriptor *descriptor;
19 | 
20 | /**
21 |  *
22 |  */
23 | - (int *)linesize;
24 | 
25 | /**
26 |  *
27 |  */
28 | - (uint8_t **)data;
29 | 
30 | /**
31 |  *
32 |  */
33 | - (CVPixelBufferRef)pixelBuffer;
34 | 
35 | /**
36 |  *
37 |  */
38 | - (SGPLFImage *)image;
39 | 
40 | @end
41 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDecoder/SGAudioDecoder.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioDecoder.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/16.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGDecodable.h"
10 | 
11 | @interface SGAudioDecoder : NSObject <SGDecodable>
12 | 
13 | @end
14 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDecoder/SGCodecContext.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGCodecContext.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/16.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGCodecDescriptor.h"
11 | #import "SGDecoderOptions.h"
12 | #import "SGPacket.h"
13 | #import "SGFrame.h"
14 | 
15 | @interface SGCodecContext : NSObject
16 | 
17 | + (instancetype)new NS_UNAVAILABLE;
18 | - (instancetype)init NS_UNAVAILABLE;
19 | 
20 | /**
21 |  *
22 |  */
23 | - (instancetype)initWithTimebase:(AVRational)timebase
24 |                         codecpar:(AVCodecParameters *)codecpar
25 |                   frameGenerator:(__kindof SGFrame *(^)(void))frameGenerator;
26 | 
27 | /**
28 |  *
29 |  */
30 | @property (nonatomic, strong) SGDecoderOptions *options;
31 | 
32 | /**
33 |  *
34 |  */
35 | - (BOOL)open;
36 | 
37 | /**
38 |  *
39 |  */
40 | - (void)close;
41 | 
42 | /**
43 |  *
44 |  */
45 | - (void)flush;
46 | 
47 | /**
48 |  *
49 |  */
50 | - (NSArray<__kindof SGFrame *> *)decode:(SGPacket *)packet;
51 | 
52 | @end
53 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDecoder/SGDecodable.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGDecodable.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/10/22.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGDecoderOptions.h"
11 | #import "SGPacket.h"
12 | #import "SGFrame.h"
13 | 
14 | @protocol SGDecodable <NSObject>
15 | 
16 | /**
17 |  *
18 |  */
19 | @property (nonatomic, strong) SGDecoderOptions *options;
20 | 
21 | /**
22 |  *
23 |  */
24 | - (NSArray<__kindof SGFrame *> *)decode:(SGPacket *)packet;
25 | 
26 | /**
27 |  *
28 |  */
29 | - (NSArray<__kindof SGFrame *> *)finish;
30 | 
31 | /**
32 |  *
33 |  */
34 | - (void)flush;
35 | 
36 | @end
37 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDecoder/SGDecodeContext.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGDecodeContext.h
 3 | //  KTVMediaKitDemo
 4 | //
 5 | //  Created by Single on 2019/11/18.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGDecoderOptions.h"
11 | #import "SGCapacity.h"
12 | #import "SGPacket.h"
13 | #import "SGFrame.h"
14 | 
15 | @interface SGDecodeContext : NSObject
16 | 
17 | + (instancetype)new NS_UNAVAILABLE;
18 | - (instancetype)init NS_UNAVAILABLE;
19 | 
20 | /**
21 |  *
22 |  */
23 | - (instancetype)initWithDecoderClass:(Class)decoderClass;
24 | 
25 | /**
26 |  *
27 |  */
28 | @property (nonatomic, copy) SGDecoderOptions *options;
29 | 
30 | /**
31 |  *
32 |  */
33 | @property (nonatomic, readonly) CMTime decodeTimeStamp;
34 | 
35 | /**
36 |  *
37 |  */
38 | - (SGCapacity)capacity;
39 | 
40 | /**
41 |  *
42 |  */
43 | - (void)putPacket:(SGPacket *)packet;
44 | 
45 | /**
46 |  *
47 |  */
48 | - (BOOL)needsPredecode;
49 | 
50 | /**
51 |  *
52 |  */
53 | - (void)predecode:(SGBlock)lock unlock:(SGBlock)unlock;
54 | 
55 | /**
56 |  *
57 |  */
58 | - (NSArray<__kindof SGFrame *> *)decode:(SGBlock)lock unlock:(SGBlock)unlock;
59 | 
60 | /**
61 |  *
62 |  */
63 | - (void)setNeedsFlush;
64 | 
65 | /**
66 |  *
67 |  */
68 | - (void)markAsFinished;
69 | 
70 | /**
71 |  *
72 |  */
73 | - (void)destory;
74 | 
75 | @end
76 | 
77 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDecoder/SGDecodeLoop.h:
--------------------------------------------------------------------------------
  1 | //
  2 | //  SGDecodeLoop.h
  3 | //  SGPlayer
  4 | //
  5 | //  Created by Single on 2018/1/19.
  6 | //  Copyright © 2018年 single. All rights reserved.
  7 | //
  8 | 
  9 | #import <Foundation/Foundation.h>
 10 | #import "SGDecodable.h"
 11 | #import "SGCapacity.h"
 12 | 
 13 | @protocol SGDecodeLoopDelegate;
 14 | 
 15 | /**
 16 |  *
 17 |  */
 18 | typedef NS_ENUM(NSUInteger, SGDecodeLoopState) {
 19 |     SGDecodeLoopStateNone     = 0,
 20 |     SGDecodeLoopStateDecoding = 1,
 21 |     SGDecodeLoopStateStalled  = 2,
 22 |     SGDecodeLoopStatePaused   = 3,
 23 |     SGDecodeLoopStateClosed   = 4,
 24 | };
 25 | 
 26 | @interface SGDecodeLoop : NSObject
 27 | 
 28 | + (instancetype)new NS_UNAVAILABLE;
 29 | - (instancetype)init NS_UNAVAILABLE;
 30 | 
 31 | /**
 32 |  *
 33 |  */
 34 | - (instancetype)initWithDecoderClass:(Class)decoderClass;
 35 | 
 36 | /**
 37 |  *
 38 |  */
 39 | @property (nonatomic, weak) id<SGDecodeLoopDelegate> delegate;
 40 | 
 41 | /**
 42 |  *
 43 |  */
 44 | @property (nonatomic, copy) SGDecoderOptions *options;
 45 | 
 46 | /**
 47 |  *
 48 |  */
 49 | - (SGDecodeLoopState)state;
 50 | 
 51 | /**
 52 |  *
 53 |  */
 54 | - (BOOL)open;
 55 | 
 56 | /**
 57 |  *
 58 |  */
 59 | - (BOOL)close;
 60 | 
 61 | /**
 62 |  *
 63 |  */
 64 | - (BOOL)pause;
 65 | 
 66 | /**
 67 |  *
 68 |  */
 69 | - (BOOL)resume;
 70 | 
 71 | /**
 72 |  *
 73 |  */
 74 | - (BOOL)flush;
 75 | 
 76 | /**
 77 |  *
 78 |  */
 79 | - (BOOL)finish:(NSArray<SGTrack *> *)tracks;
 80 | 
 81 | /**
 82 |  *
 83 |  */
 84 | - (BOOL)putPacket:(SGPacket *)packet;
 85 | 
 86 | @end
 87 | 
 88 | @protocol SGDecodeLoopDelegate <NSObject>
 89 | 
 90 | /**
 91 |  *
 92 |  */
 93 | - (void)decodeLoop:(SGDecodeLoop *)decodeLoop didChangeState:(SGDecodeLoopState)state;
 94 | 
 95 | /**
 96 |  *
 97 |  */
 98 | - (void)decodeLoop:(SGDecodeLoop *)decodeLoop didChangeCapacity:(SGCapacity)capacity;
 99 | 
100 | /**
101 |  *
102 |  */
103 | - (void)decodeLoop:(SGDecodeLoop *)decodeLoop didOutputFrames:(NSArray<__kindof SGFrame *> *)frames needsDrop:(BOOL(^)(void))needsDrop;
104 | 
105 | @end
106 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDecoder/SGVideoDecoder.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGVideoDecoder.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/16.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGDecodable.h"
10 | 
11 | @interface SGVideoDecoder : NSObject <SGDecodable>
12 | 
13 | /**
14 |  *
15 |  */
16 | @property (nonatomic) BOOL outputFromKeyFrame;
17 | 
18 | @end
19 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDefine/SGMacro.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMacro.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 16/6/29.
 6 | //  Copyright © 2016年 single. All rights reserved.
 7 | //
 8 | 
 9 | #ifndef SGMacro_h
10 | #define SGMacro_h
11 | 
12 | #import <Foundation/Foundation.h>
13 | 
14 | #define SGWeakify(obj) __weak typeof(obj) weak_obj = obj;
15 | #define SGStrongify(obj) __strong typeof(weak_obj) obj = weak_obj;
16 | 
17 | #ifdef DEBUG
18 | #define SGPlayerLog(...) NSLog(__VA_ARGS__)
19 | #else
20 | #define SGPlayerLog(...)
21 | #endif
22 | 
23 | #define SGGet0Map(ret, name0, obj) - (ret)name0 {return obj.name0;}
24 | #define SGGet1Map(ret, name0, t0, obj) - (ret)name0:(t0)n0 {return [obj name0:n0];}
25 | #define SGGet00Map(ret, name0, name00, obj) - (ret)name0 {return obj.name00;}
26 | #define SGGet11Map(ret, name0, name00, t0, obj) - (ret)name0:(t0)n0 {return [obj name00:n0];}
27 | 
28 | #define SGSet1Map(ret, name0, t0, obj) - (ret)name0:(t0)n0 {[obj name0:n0];}
29 | #define SGSet2Map(ret, name0, t0, name1, t1, obj) - (ret)name0:(t0)n0 name1:(t1)n1 {[obj name0:n0 name1:n1];}
30 | #define SGSet11Map(ret, name0, name00, t0, obj) - (ret)name0:(t0)n0 {[obj name00:n0];}
31 | #define SGSet22Map(ret, name0, name00, t0, name1, name11, t1, obj) - (ret)name0:(t0)n0 name1:(t1)n1 {[obj name00:n0 name11:n1];}
32 | 
33 | #endif
34 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDefine/SGMapping.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMapping.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/26.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGVideoRenderer.h"
11 | #import "SGMetalViewport.h"
12 | #import "SGFFmpeg.h"
13 | 
14 | // SG <-> SGMetal
15 | SGMetalViewportMode SGScaling2Viewport(SGScalingMode mode);
16 | SGScalingMode SGViewport2Scaling(SGMetalViewportMode mode);
17 | 
18 | // FF <-> SG
19 | SGMediaType SGMediaTypeFF2SG(enum AVMediaType mediaType);
20 | enum AVMediaType SGMediaTypeSG2FF(SGMediaType mediaType);
21 | 
22 | // FF <-> AV
23 | OSType SGPixelFormatFF2AV(enum AVPixelFormat format);
24 | enum AVPixelFormat SGPixelFormatAV2FF(OSType format);
25 | 
26 | // FF <-> NS
27 | AVDictionary * SGDictionaryNS2FF(NSDictionary *dictionary);
28 | NSDictionary * SGDictionaryFF2NS(AVDictionary *dictionary);
29 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDemuxer/SGDemuxable.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGDemuxable.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/9/25.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGDemuxerOptions.h"
11 | #import "SGPacket.h"
12 | 
13 | @protocol SGDemuxableDelegate;
14 | 
15 | @protocol SGDemuxable <NSObject>
16 | 
17 | /**
18 |  *
19 |  */
20 | @property (nonatomic, copy) SGDemuxerOptions *options;
21 | 
22 | /**
23 |  *
24 |  */
25 | @property (nonatomic, weak) id<SGDemuxableDelegate> delegate;
26 | 
27 | /**
28 |  *
29 |  */
30 | @property (nonatomic, copy, readonly) NSArray<SGTrack *> *tracks;
31 | 
32 | /**
33 |  *
34 |  */
35 | @property (nonatomic, copy, readonly) NSArray<SGTrack *> *finishedTracks;
36 | 
37 | /**
38 |  *
39 |  */
40 | @property (nonatomic, copy, readonly) NSDictionary *metadata;
41 | 
42 | /**
43 |  *
44 |  */
45 | @property (nonatomic, readonly) CMTime duration;
46 | 
47 | /**
48 |  *
49 |  */
50 | - (id<SGDemuxable>)sharedDemuxer;
51 | 
52 | /**
53 |  *
54 |  */
55 | - (NSError *)open;
56 | 
57 | /**
58 |  *
59 |  */
60 | - (NSError *)close;
61 | 
62 | /**
63 |  *
64 |  */
65 | - (NSError *)seekable;
66 | 
67 | /**
68 |  *
69 |  */
70 | - (NSError *)seekToTime:(CMTime)time;
71 | 
72 | /**
73 |  *
74 |  */
75 | - (NSError *)seekToTime:(CMTime)time toleranceBefor:(CMTime)toleranceBefor toleranceAfter:(CMTime)toleranceAfter;
76 | 
77 | /**
78 |  *
79 |  */
80 | - (NSError *)nextPacket:(SGPacket **)packet;
81 | 
82 | @end
83 | 
84 | @protocol SGDemuxableDelegate <NSObject>
85 | 
86 | /**
87 |  *
88 |  */
89 | - (BOOL)demuxableShouldAbortBlockingFunctions:(id<SGDemuxable>)demuxable;
90 | 
91 | @end
92 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDemuxer/SGExtractingDemuxer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGExtractingDemuxer.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/14.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGDemuxable.h"
10 | 
11 | @interface SGExtractingDemuxer : NSObject <SGDemuxable>
12 | 
13 | /**
14 |  *
15 |  */
16 | + (instancetype)new NS_UNAVAILABLE;
17 | - (instancetype)init NS_UNAVAILABLE;
18 | 
19 | /**
20 |  *
21 |  */
22 | - (instancetype)initWithDemuxable:(id<SGDemuxable>)demuxable index:(NSInteger)index timeRange:(CMTimeRange)timeRange scale:(CMTime)scale;
23 | 
24 | /**
25 |  *
26 |  */
27 | @property (nonatomic, strong, readonly) id<SGDemuxable> demuxable;
28 | 
29 | /**
30 |  *
31 |  */
32 | @property (nonatomic, readonly) NSInteger index;
33 | 
34 | /**
35 |  *
36 |  */
37 | @property (nonatomic, readonly) CMTimeRange timeRange;
38 | 
39 | /**
40 |  *
41 |  */
42 | @property (nonatomic, readonly) CMTime scale;
43 | 
44 | /**
45 |  *
46 |  */
47 | @property (nonatomic) BOOL overgop;
48 | 
49 | @end
50 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDemuxer/SGMutilDemuxer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMutilDemuxer.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/16.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGDemuxable.h"
10 | 
11 | @interface SGMutilDemuxer : NSObject <SGDemuxable>
12 | 
13 | /**
14 |  *
15 |  */
16 | + (instancetype)new NS_UNAVAILABLE;
17 | - (instancetype)init NS_UNAVAILABLE;
18 | 
19 | /**
20 |  *
21 |  */
22 | - (instancetype)initWithDemuxables:(NSArray<id<SGDemuxable>> *)demuxables;
23 | 
24 | @end
25 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDemuxer/SGPaddingDemuxer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPaddingDemuxer.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/4.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGDemuxable.h"
10 | 
11 | @interface SGPaddingDemuxer : NSObject <SGDemuxable>
12 | 
13 | /**
14 |  *
15 |  */
16 | + (instancetype)new NS_UNAVAILABLE;
17 | - (instancetype)init NS_UNAVAILABLE;
18 | 
19 | /**
20 |  *
21 |  */
22 | - (instancetype)initWithDuration:(CMTime)duration;
23 | 
24 | @end
25 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDemuxer/SGPaddingDemuxer.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPaddingDemuxer.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/4.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPaddingDemuxer.h"
10 | #import "SGPacket+Internal.h"
11 | #import "SGError.h"
12 | 
13 | @interface SGPaddingDemuxer ()
14 | 
15 | @property (nonatomic, readonly) CMTime lasttime;
16 | 
17 | @end
18 | 
19 | @implementation SGPaddingDemuxer
20 | 
21 | @synthesize tracks = _tracks;
22 | @synthesize options = _options;
23 | @synthesize delegate = _delegate;
24 | @synthesize metadata = _metadata;
25 | @synthesize duration = _duration;
26 | @synthesize finishedTracks = _finishedTracks;
27 | 
28 | - (instancetype)initWithDuration:(CMTime)duration
29 | {
30 |     if (self = [super init]) {
31 |         self->_duration = duration;
32 |         [self seekToTime:kCMTimeZero];
33 |     }
34 |     return self;
35 | }
36 | 
37 | #pragma mark - Control
38 | 
39 | - (id<SGDemuxable>)sharedDemuxer
40 | {
41 |     return nil;
42 | }
43 | 
44 | - (NSError *)open
45 | {
46 |     return nil;
47 | }
48 | 
49 | - (NSError *)close
50 | {
51 |     return nil;
52 | }
53 | 
54 | - (NSError *)seekable
55 | {
56 |     return nil;
57 | }
58 | 
59 | - (NSError *)seekToTime:(CMTime)time
60 | {
61 |     return [self seekToTime:time toleranceBefor:kCMTimeInvalid toleranceAfter:kCMTimeInvalid];
62 | }
63 | 
64 | - (NSError *)seekToTime:(CMTime)time toleranceBefor:(CMTime)toleranceBefor toleranceAfter:(CMTime)toleranceAfter
65 | {
66 |     if (!CMTIME_IS_NUMERIC(time)) {
67 |         return SGCreateError(SGErrorCodeInvlidTime, SGActionCodeFormatSeekFrame);
68 |     }
69 |     time = CMTimeMaximum(time, kCMTimeZero);
70 |     time = CMTimeMinimum(time, self->_duration);
71 |     self->_lasttime = time;
72 |     return nil;
73 | }
74 | 
75 | - (NSError *)nextPacket:(SGPacket **)packet
76 | {
77 |     if (CMTimeCompare(self->_lasttime, self->_duration) >= 0) {
78 |         return SGCreateError(SGErrorCodeDemuxerEndOfFile, SGActionCodeFormatReadFrame);
79 |     }
80 |     CMTime timeStamp = self->_lasttime;
81 |     CMTime duration = CMTimeSubtract(self->_duration, self->_lasttime);
82 |     SGPacket *pkt = [SGPacket packet];
83 |     pkt.flags |= SGDataFlagPadding;
84 |     pkt.core->size = 1;
85 |     pkt.core->pts = av_rescale(AV_TIME_BASE, timeStamp.value, timeStamp.timescale);
86 |     pkt.core->dts = av_rescale(AV_TIME_BASE, timeStamp.value, timeStamp.timescale);
87 |     pkt.core->duration = av_rescale(AV_TIME_BASE, duration.value, duration.timescale);
88 |     SGCodecDescriptor *cd = [[SGCodecDescriptor alloc] init];
89 |     cd.timebase = AV_TIME_BASE_Q;
90 |     [pkt setCodecDescriptor:cd];
91 |     [pkt fill];
92 |     *packet = pkt;
93 |     self->_lasttime = self->_duration;
94 |     return nil;
95 | }
96 | 
97 | @end
98 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDemuxer/SGTrackDemuxer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGTrackDemuxer.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/14.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGDemuxable.h"
10 | #import "SGMutableTrack.h"
11 | 
12 | @interface SGTrackDemuxer : NSObject <SGDemuxable>
13 | 
14 | /**
15 |  *
16 |  */
17 | + (instancetype)new NS_UNAVAILABLE;
18 | - (instancetype)init NS_UNAVAILABLE;
19 | 
20 | /**
21 |  *
22 |  */
23 | - (instancetype)initWithTrack:(SGMutableTrack *)track;
24 | 
25 | @end
26 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDemuxer/SGURLDemuxer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGURLDemuxer.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/13.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGDemuxable.h"
10 | 
11 | @interface SGURLDemuxer : NSObject <SGDemuxable>
12 | 
13 | + (instancetype)new NS_UNAVAILABLE;
14 | - (instancetype)init NS_UNAVAILABLE;
15 | 
16 | /*!
17 |  @method initWithURL:
18 |  @abstract
19 |     Initializes an SGURLDemuxer with an NSURL.
20 |  */
21 | - (instancetype)initWithURL:(NSURL *)URL;
22 | 
23 | /*!
24 |  @property URL
25 |  @abstract
26 |     Indicates the URL of the demuxer.
27 |  */
28 | @property (nonatomic, copy, readonly) NSURL *URL;
29 | 
30 | @end
31 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDescription/SGAudioDescriptor.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioDescriptor.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/28.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | 
11 | @interface SGAudioDescriptor : NSObject <NSCopying>
12 | 
13 | /*!
14 |  @property format
15 |  @abstract
16 |     Indicates the audio format.
17 |  
18 |  @discussion
19 |     The value corresponds to AVSampleFormat.
20 |  */
21 | @property (nonatomic) int format;
22 | 
23 | /*!
24 |  @property sampleRate
25 |  @abstract
26 |     Indicates the sample rate.
27 |  */
28 | @property (nonatomic) int sampleRate;
29 | 
30 | /*!
31 |  @property numberOfChannels
32 |  @abstract
33 |     Indicates the channel count.
34 |  */
35 | @property (nonatomic) int numberOfChannels;
36 | 
37 | /*!
38 |  @method isPlanar
39 |  @abstract
40 |     Get whether the sample format is planar.
41 |  */
42 | - (BOOL)isPlanar;
43 | 
44 | /*!
45 |  @method bytesPerSample
46 |  @abstract
47 |     Get the bytes per sample.
48 |  */
49 | - (int)bytesPerSample;
50 | 
51 | /*!
52 |  @method numberOfPlanes
53 |  @abstract
54 |     Get the number of planes.
55 |  */
56 | - (int)numberOfPlanes;
57 | 
58 | /*!
59 |  @method linesize:
60 |  @abstract
61 |     Get the linesize of the number of samples.
62 |  */
63 | - (int)linesize:(int)numberOfSamples;
64 | 
65 | /*!
66 |  @method isEqualToDescriptor:
67 |  @abstract
68 |     Check if the descriptor is equal to another.
69 |  */
70 | - (BOOL)isEqualToDescriptor:(SGAudioDescriptor *)descriptor;
71 | 
72 | @end
73 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDescription/SGAudioDescriptor.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioDescriptor.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/28.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGAudioDescriptor.h"
10 | #import "SGDescriptor+Internal.h"
11 | #import "SGFFmpeg.h"
12 | 
13 | @implementation SGAudioDescriptor
14 | 
15 | - (id)copyWithZone:(NSZone *)zone
16 | {
17 |     SGAudioDescriptor *obj = [[SGAudioDescriptor alloc] init];
18 |     obj->_format = self->_format;
19 |     obj->_sampleRate = self->_sampleRate;
20 |     obj->_numberOfChannels = self->_numberOfChannels;
21 |     obj->_channelLayout = self->_channelLayout;
22 |     return obj;
23 | }
24 | 
25 | - (instancetype)init
26 | {
27 |     if (self = [super init]) {
28 |         self->_format = AV_SAMPLE_FMT_FLTP;
29 |         self->_sampleRate = 44100;
30 |         self->_numberOfChannels = 2;
31 |         av_channel_layout_default(&self->_channelLayout, 2);
32 |     }
33 |     return self;
34 | }
35 | 
36 | - (instancetype)initWithFrame:(AVFrame *)frame
37 | {
38 |     if (self = [super init]) {
39 |         self->_format = frame->format;
40 |         self->_sampleRate = frame->sample_rate;
41 |         self->_numberOfChannels = frame->ch_layout.nb_channels;
42 |         self->_channelLayout = frame->ch_layout;
43 |     }
44 |     return self;
45 | }
46 | 
47 | - (BOOL)isPlanar
48 | {
49 |     return av_sample_fmt_is_planar(self->_format);
50 | }
51 | 
52 | - (int)bytesPerSample
53 | {
54 |     return av_get_bytes_per_sample(self->_format);
55 | }
56 | 
57 | - (int)numberOfPlanes
58 | {
59 |     return av_sample_fmt_is_planar(self->_format) ? self->_numberOfChannels : 1;
60 | }
61 | 
62 | - (int)linesize:(int)numberOfSamples
63 | {
64 |     int linesize = av_get_bytes_per_sample(self->_format) * numberOfSamples;
65 |     linesize *= av_sample_fmt_is_planar(self->_format) ? 1 : self->_numberOfChannels;
66 |     return linesize;
67 | }
68 | 
69 | - (BOOL)isEqualToDescriptor:(SGAudioDescriptor *)descriptor
70 | {
71 |     if (!descriptor) {
72 |         return NO;
73 |     }
74 |     return
75 |     self->_format == descriptor->_format &&
76 |     self->_sampleRate == descriptor->_sampleRate &&
77 |     self->_numberOfChannels == descriptor->_numberOfChannels &&
78 |     (av_channel_layout_compare(&self->_channelLayout, &descriptor->_channelLayout) == 0);
79 | }
80 | 
81 | @end
82 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDescription/SGCodecDescriptor.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGCodecDescriptor.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/15.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGTimeLayout.h"
11 | #import "SGFFmpeg.h"
12 | #import "SGTrack.h"
13 | 
14 | @interface SGCodecDescriptor : NSObject <NSCopying>
15 | 
16 | /**
17 |  *
18 |  */
19 | @property (nonatomic) AVRational timebase;
20 | 
21 | /**
22 |  *
23 |  */
24 | @property (nonatomic) AVCodecParameters *codecpar;
25 | 
26 | /**
27 |  *
28 |  */
29 | @property (nonatomic, strong) SGTrack *track;
30 | 
31 | /**
32 |  *
33 |  */
34 | @property (nonatomic, strong) NSDictionary *metadata;
35 | 
36 | /**
37 |  *
38 |  */
39 | @property (nonatomic, readonly) CMTimeRange timeRange;
40 | 
41 | /**
42 |  *
43 |  */
44 | @property (nonatomic, readonly) CMTime scale;
45 | 
46 | /**
47 |  *
48 |  */
49 | - (CMTime)convertTimeStamp:(CMTime)timeStamp;
50 | 
51 | /**
52 |  *
53 |  */
54 | - (CMTime)convertDuration:(CMTime)duration;
55 | 
56 | /**
57 |  *
58 |  */
59 | - (void)appendTimeRange:(CMTimeRange)timeRange;
60 | 
61 | /**
62 |  *
63 |  */
64 | - (void)appendTimeLayout:(SGTimeLayout *)timeLayout;
65 | 
66 | /**
67 |  *
68 |  */
69 | - (void)fillToDescriptor:(SGCodecDescriptor *)descriptor;
70 | 
71 | /**
72 |  *
73 |  */
74 | - (BOOL)isEqualToDescriptor:(SGCodecDescriptor *)descriptor;
75 | 
76 | /**
77 |  *
78 |  */
79 | - (BOOL)isEqualCodecContextToDescriptor:(SGCodecDescriptor *)descriptor;
80 | 
81 | @end
82 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDescription/SGDescriptor+Internal.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPacket+Internal.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/23.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPacket.h"
10 | #import "SGFFmpeg.h"
11 | #import "SGAudioDescriptor.h"
12 | #import "SGVideoDescriptor.h"
13 | 
14 | @interface SGAudioDescriptor ()
15 | 
16 | - (instancetype)initWithFrame:(AVFrame *)frame;
17 | 
18 | /*!
19 |  @property channelLayout
20 |  @abstract
21 |     Indicates the channel layout.
22 |  */
23 | @property (nonatomic) AVChannelLayout channelLayout;
24 | 
25 | @end
26 | 
27 | @interface SGVideoDescriptor ()
28 | 
29 | - (instancetype)initWithFrame:(AVFrame *)frame;
30 | 
31 | @end
32 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGDescription/SGVideoDescriptor.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGVideoDescriptor.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/12/11.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGDefines.h"
11 | 
12 | @interface SGVideoDescriptor : NSObject <NSCopying>
13 | 
14 | /*!
15 |  @property format
16 |  @abstract
17 |     Indicates the vdieo format.
18 |  
19 |  @discussion
20 |     The value corresponds to AVPixelFormat.
21 |  */
22 | @property (nonatomic) int format;
23 | 
24 | /*!
25 |  @property cv_format
26 |  @abstract
27 |     Indicates the vdieo format.
28 |  
29 |  @discussion
30 |     The value corresponds to kCVPixelFormatType_XXX.
31 |  */
32 | @property (nonatomic) OSType cv_format;
33 | 
34 | /*!
35 |  @property width
36 |  @abstract
37 |     Indicates the width.
38 |  */
39 | @property (nonatomic) int width;
40 | 
41 | /*!
42 |  @property height
43 |  @abstract
44 |     Indicates the height.
45 |  */
46 | @property (nonatomic) int height;
47 | 
48 | /*!
49 |  @property sampleAspectRatio
50 |  @abstract
51 |     Indicates the sample aspect ratio, 0/1 if unknown/unspecified.
52 | */
53 | @property (nonatomic) SGRational sampleAspectRatio;
54 | 
55 | /*!
56 |  @property frameSize
57 |  @abstract
58 |     Indicates the pixel buffer frame size.
59 | */
60 | @property (nonatomic, readonly) SGRational frameSize;
61 | 
62 | /*!
63 |  @property presentationSize
64 |  @abstract
65 |     Indicates the best presentation size.
66 | */
67 | @property (nonatomic, readonly) SGRational presentationSize;
68 | 
69 | /*!
70 |  @method numberOfPlanes
71 |  @abstract
72 |     Get the number of planes.
73 |  */
74 | - (int)numberOfPlanes;
75 | 
76 | /*!
77 |  @method isEqualToDescriptor:
78 |  @abstract
79 |     Check if the descriptor is equal to another.
80 |  */
81 | - (BOOL)isEqualToDescriptor:(SGVideoDescriptor *)descriptor;
82 | 
83 | @end
84 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGFFmpeg/SGFFmpeg.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGFFmpeg.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/8/2.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #pragma clang diagnostic push
11 | #pragma clang diagnostic ignored "-Wdocumentation"
12 | #import "avformat.h"
13 | #import "imgutils.h"
14 | #import "swresample.h"
15 | #import "swscale.h"
16 | #import "avcodec.h"
17 | #pragma clang diagnostic pop
18 | 
19 | void SGFFmpegSetupIfNeeded(void);
20 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGFFmpeg/SGFFmpeg.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGFFmpeg.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/8/2.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGFFmpeg.h"
10 | 
11 | static void SGFFmpegLogCallback(void * context, int level, const char * format, va_list args)
12 | {
13 | //    NSString * message = [[NSString alloc] initWithFormat:[NSString stringWithUTF8String:format] arguments:args];
14 | //    NSLog(@"SGFFLog : %@", message);
15 | }
16 | 
17 | void SGFFmpegSetupIfNeeded(void)
18 | {
19 |     static dispatch_once_t onceToken;
20 |     dispatch_once(&onceToken, ^{
21 |         av_log_set_callback(SGFFmpegLogCallback);
22 |         avformat_network_init();
23 |     });
24 | }
25 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetal.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetal.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #ifndef SGMetal_h
10 | #define SGMetal_h
11 | 
12 | #import <Metal/Metal.h>
13 | #import <MetalKit/MetalKit.h>
14 | 
15 | #import "SGMetalTypes.h"
16 | #import "SGMetalRenderer.h"
17 | #import "SGMetalViewport.h"
18 | #import "SGMetalProjection.h"
19 | #import "SGMetalTextureLoader.h"
20 | 
21 | #import "SGMetalModel.h"
22 | #import "SGMetalPlaneModel.h"
23 | #import "SGMetalSphereModel.h"
24 | 
25 | #import "SGMetalRenderPipeline.h"
26 | #import "SGMetalYUVRenderPipeline.h"
27 | #import "SGMetalNV12RenderPipeline.h"
28 | #import "SGMetalBGRARenderPipeline.h"
29 | #import "SGMetalRenderPipelinePool.h"
30 | 
31 | #endif /* SGMetal_h */
32 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalBGRARenderPipeline.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalBGRARenderPipeline.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalRenderPipeline.h"
10 | 
11 | @interface SGMetalBGRARenderPipeline : SGMetalRenderPipeline
12 | 
13 | @end
14 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalBGRARenderPipeline.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalBGRARenderPipeline.m
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalBGRARenderPipeline.h"
10 | 
11 | @implementation SGMetalBGRARenderPipeline
12 | 
13 | - (instancetype)initWithDevice:(id<MTLDevice>)device library:(id<MTLLibrary>)library
14 | {
15 |     if (self = [super initWithDevice:device library:library]) {
16 |         self.descriptor = [[MTLRenderPipelineDescriptor alloc] init];
17 |         self.descriptor.vertexFunction = [self.library newFunctionWithName:@"vertexShader"];
18 |         self.descriptor.fragmentFunction = [self.library newFunctionWithName:@"fragmentShaderBGRA"];
19 |         self.descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
20 |         self.state = [self.device newRenderPipelineStateWithDescriptor:self.descriptor error:nil];
21 |     }
22 |     return self;
23 | }
24 | 
25 | @end
26 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalModel.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalModel.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/24.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Metal/Metal.h>
10 | 
11 | @interface SGMetalModel : NSObject
12 | 
13 | - (instancetype)initWithDevice:(id<MTLDevice>)device;
14 | 
15 | @property (nonatomic) NSUInteger indexCount;
16 | @property (nonatomic) MTLIndexType indexType;
17 | @property (nonatomic) MTLPrimitiveType primitiveType;
18 | @property (nonatomic, strong) id<MTLDevice> device;
19 | @property (nonatomic, strong) id<MTLBuffer> indexBuffer;
20 | @property (nonatomic, strong) id<MTLBuffer> vertexBuffer;
21 | 
22 | @end
23 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalModel.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalModel.m
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/24.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalModel.h"
10 | 
11 | @implementation SGMetalModel
12 | 
13 | - (instancetype)initWithDevice:(id<MTLDevice>)device
14 | {
15 |     if (self = [super init]) {
16 |         self.device = device;
17 |     }
18 |     return self;
19 | }
20 | 
21 | @end
22 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalNV12RenderPipeline.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalNV12RenderPipeline.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalRenderPipeline.h"
10 | 
11 | @interface SGMetalNV12RenderPipeline : SGMetalRenderPipeline
12 | 
13 | @end
14 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalNV12RenderPipeline.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalNV12RenderPipeline.m
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalNV12RenderPipeline.h"
10 | 
11 | @implementation SGMetalNV12RenderPipeline
12 | 
13 | - (instancetype)initWithDevice:(id<MTLDevice>)device library:(id<MTLLibrary>)library
14 | {
15 |     if (self = [super initWithDevice:device library:library]) {
16 |         self.descriptor = [[MTLRenderPipelineDescriptor alloc] init];
17 |         self.descriptor.vertexFunction = [self.library newFunctionWithName:@"vertexShader"];
18 |         self.descriptor.fragmentFunction = [self.library newFunctionWithName:@"fragmentShaderNV12"];
19 |         self.descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
20 |         self.state = [self.device newRenderPipelineStateWithDescriptor:self.descriptor error:nil];
21 |     }
22 |     return self;
23 | }
24 | 
25 | @end
26 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalPlaneModel.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalPlaneModel.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/25.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalModel.h"
10 | 
11 | @interface SGMetalPlaneModel : SGMetalModel
12 | 
13 | @end
14 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalPlaneModel.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalPlaneModel.m
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/25.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalPlaneModel.h"
10 | #import "SGMetalTypes.h"
11 | 
12 | @implementation SGMetalPlaneModel
13 | 
14 | static const UInt32 indices[] = {
15 |     0, 1, 3, 0, 3, 2,
16 | };
17 | 
18 | static const SGMetalVertex vertices[] = {
19 |     { { -1.0,  -1.0,  0.0,  1.0 }, { 0.0, 1.0 } },
20 |     { { -1.0,   1.0,  0.0,  1.0 }, { 0.0, 0.0 } },
21 |     { {  1.0,  -1.0,  0.0,  1.0 }, { 1.0, 1.0 } },
22 |     { {  1.0,   1.0,  0.0,  1.0 }, { 1.0, 0.0 } },
23 | };
24 | 
25 | - (instancetype)initWithDevice:(id<MTLDevice>)device
26 | {
27 |     if (self = [super initWithDevice:device]) {
28 |         self.indexCount = 6;
29 |         self.indexType = MTLIndexTypeUInt32;
30 |         self.primitiveType = MTLPrimitiveTypeTriangle;
31 |         self.indexBuffer = [self.device newBufferWithBytes:indices length:sizeof(indices) options:MTLResourceStorageModeShared];
32 |         self.vertexBuffer = [self.device newBufferWithBytes:vertices length:sizeof(vertices) options:MTLResourceStorageModeShared];
33 |     }
34 |     return self;
35 | }
36 | 
37 | @end
38 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalProjection.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalProjection.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/28.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Metal/Metal.h>
10 | #import <GLKit/GLKit.h>
11 | 
12 | @interface SGMetalProjection : NSObject
13 | 
14 | - (instancetype)initWithDevice:(id<MTLDevice>)device;
15 | 
16 | @property (nonatomic) GLKMatrix4 matrix;
17 | @property (nonatomic, strong) id<MTLDevice> device;
18 | @property (nonatomic, strong) id<MTLBuffer> matrixBuffer;
19 | 
20 | @end
21 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalProjection.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalProjection.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/28.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalProjection.h"
10 | #import "SGMetalTypes.h"
11 | 
12 | @implementation SGMetalProjection
13 | 
14 | - (instancetype)initWithDevice:(id<MTLDevice>)device
15 | {
16 |     if (self = [super init]) {
17 |         self.device = device;
18 |         self.matrixBuffer = [device newBufferWithLength:sizeof(SGMetalMatrix) options:MTLResourceStorageModeShared];
19 |     }
20 |     return self;
21 | }
22 | 
23 | - (void)setMatrix:(GLKMatrix4)matrix
24 | {
25 |     self->_matrix = matrix;
26 |     ((SGMetalMatrix *)self.matrixBuffer.contents)->mvp = SGMatrixFloat4x4FromGLKMatrix4(matrix);
27 | }
28 | 
29 | static matrix_float4x4 SGMatrixFloat4x4FromGLKMatrix4(GLKMatrix4 matrix)
30 | {
31 |     return (matrix_float4x4){{
32 |         {matrix.m00, matrix.m01, matrix.m02, matrix.m03},
33 |         {matrix.m10, matrix.m11, matrix.m12, matrix.m13},
34 |         {matrix.m20, matrix.m21, matrix.m22, matrix.m23},
35 |         {matrix.m30, matrix.m31, matrix.m32, matrix.m33}}};
36 | }
37 | 
38 | @end
39 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalRenderPipeline.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalRenderPipeline.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Metal/Metal.h>
10 | 
11 | @interface SGMetalRenderPipeline : NSObject
12 | 
13 | - (instancetype)initWithDevice:(id<MTLDevice>)device library:(id<MTLLibrary>)library;
14 | 
15 | @property (nonatomic, strong) id<MTLDevice> device;
16 | @property (nonatomic, strong) id<MTLLibrary> library;
17 | @property (nonatomic, strong) id<MTLRenderPipelineState> state;
18 | @property (nonatomic, strong) MTLRenderPipelineDescriptor *descriptor;
19 | 
20 | @end
21 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalRenderPipeline.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalRenderPipeline.m
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalRenderPipeline.h"
10 | 
11 | @implementation SGMetalRenderPipeline
12 | 
13 | - (instancetype)initWithDevice:(id<MTLDevice>)device library:(id<MTLLibrary>)library
14 | {
15 |     if (self = [super init]) {
16 |         self.device = device;
17 |         self.library = library;
18 |     }
19 |     return self;
20 | }
21 | 
22 | @end
23 | 
24 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalRenderPipelinePool.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalRenderPipelinePool.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGMetalRenderPipeline.h"
11 | #import <CoreVideo/CoreVideo.h>
12 | 
13 | @interface SGMetalRenderPipelinePool : NSObject
14 | 
15 | - (instancetype)initWithDevice:(id<MTLDevice>)device;
16 | 
17 | - (SGMetalRenderPipeline *)pipelineWithCVPixelFormat:(OSType)pixpelFormat;
18 | - (SGMetalRenderPipeline *)pipelineWithCVPixelBuffer:(CVPixelBufferRef)pixelBuffer;
19 | 
20 | @end
21 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalRenderPipelinePool.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalRenderPipelinePool.m
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalRenderPipelinePool.h"
10 | #import "SGMetalYUVRenderPipeline.h"
11 | #import "SGMetalNV12RenderPipeline.h"
12 | #import "SGMetalBGRARenderPipeline.h"
13 | 
14 | #import "SGPLFTargets.h"
15 | #if SGPLATFORM_TARGET_OS_IPHONE
16 | #import "SGMetalShader_iOS.h"
17 | #elif SGPLATFORM_TARGET_OS_TV
18 | #import "SGMetalShader_tvOS.h"
19 | #elif SGPLATFORM_TARGET_OS_MAC
20 | #import "SGMetalShader_macOS.h"
21 | #endif
22 | 
23 | @interface SGMetalRenderPipelinePool ()
24 | 
25 | @property (nonatomic, strong) id<MTLDevice> device;
26 | @property (nonatomic, strong) id<MTLLibrary> library;
27 | @property (nonatomic, strong) SGMetalRenderPipeline *yuv;
28 | @property (nonatomic, strong) SGMetalRenderPipeline *nv12;
29 | @property (nonatomic, strong) SGMetalRenderPipeline *bgra;
30 | 
31 | @end
32 | 
33 | @implementation SGMetalRenderPipelinePool
34 | 
35 | - (instancetype)initWithDevice:(id<MTLDevice>)device
36 | {
37 |     if (self = [super init]) {
38 |         self.device = device;
39 |         self.library = [device newLibraryWithData:dispatch_data_create(metallib, sizeof(metallib), dispatch_get_global_queue(0, 0), ^{}) error:NULL];
40 |     }
41 |     return self;
42 | }
43 | 
44 | - (SGMetalRenderPipeline *)pipelineWithCVPixelFormat:(OSType)pixpelFormat
45 | {
46 |     if (pixpelFormat == kCVPixelFormatType_420YpCbCr8Planar) {
47 |         return self.yuv;
48 |     } else if (pixpelFormat == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) {
49 |         return self.nv12;
50 |     } else if (pixpelFormat == kCVPixelFormatType_32BGRA) {
51 |         return self.bgra;
52 |     }
53 |     return nil;
54 | }
55 | 
56 | - (SGMetalRenderPipeline *)pipelineWithCVPixelBuffer:(CVPixelBufferRef)pixelBuffer
57 | {
58 |     return [self pipelineWithCVPixelFormat:CVPixelBufferGetPixelFormatType(pixelBuffer)];
59 | }
60 | 
61 | - (SGMetalRenderPipeline *)yuv
62 | {
63 |     if (_yuv == nil) {
64 |         _yuv = [[SGMetalYUVRenderPipeline alloc] initWithDevice:self.device library:self.library];
65 |     }
66 |     return _yuv;
67 | }
68 | 
69 | - (SGMetalRenderPipeline *)nv12
70 | {
71 |     if (_nv12 == nil) {
72 |         _nv12 = [[SGMetalNV12RenderPipeline alloc] initWithDevice:self.device library:self.library];
73 |     }
74 |     return _nv12;
75 | }
76 | 
77 | - (SGMetalRenderPipeline *)bgra
78 | {
79 |     if (_bgra == nil) {
80 |         _bgra = [[SGMetalBGRARenderPipeline alloc] initWithDevice:self.device library:self.library];
81 |     }
82 |     return _bgra;
83 | }
84 | 
85 | @end
86 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalRenderer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalRenderer.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/24.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import <simd/simd.h>
10 | #import <Metal/Metal.h>
11 | #import "SGMetalModel.h"
12 | #import "SGMetalProjection.h"
13 | #import "SGMetalRenderPipeline.h"
14 | 
15 | @interface SGMetalRenderer : NSObject
16 | 
17 | - (instancetype)initWithDevice:(id<MTLDevice>)device;
18 | 
19 | - (id<MTLCommandBuffer>)drawModel:(SGMetalModel *)model
20 |                         viewports:(MTLViewport[])viewports
21 |                          pipeline:(SGMetalRenderPipeline *)pipeline
22 |                       projections:(NSArray<SGMetalProjection *> *)projections
23 |                     inputTextures:(NSArray<id<MTLTexture>> *)inputTextures
24 |                     outputTexture:(id<MTLTexture>)outputTexture;
25 | 
26 | @end
27 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalRenderer.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalRenderer.m
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/24.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalRenderer.h"
10 | #import "SGMetalTypes.h"
11 | 
12 | @interface SGMetalRenderer ()
13 | 
14 | @property (nonatomic, strong) id<MTLDevice> device;
15 | @property (nonatomic, strong) id<MTLCommandQueue> commandQueue;
16 | @property (nonatomic, strong) MTLRenderPassDescriptor *renderPassDescriptor;
17 | 
18 | @end
19 | 
20 | @implementation SGMetalRenderer
21 | 
22 | - (instancetype)initWithDevice:(id<MTLDevice>)device
23 | {
24 |     if (self = [super init]) {
25 |         self.device = device;
26 |         self.commandQueue = [self.device newCommandQueue];
27 |         self.renderPassDescriptor = [[MTLRenderPassDescriptor alloc] init];
28 |         self.renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 1);
29 |         self.renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear;
30 |         self.renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore;
31 |     }
32 |     return self;
33 | }
34 | 
35 | - (id<MTLCommandBuffer>)drawModel:(SGMetalModel *)model
36 |                         viewports:(MTLViewport[])viewports
37 |                          pipeline:(SGMetalRenderPipeline *)pipeline
38 |                       projections:(NSArray<SGMetalProjection *> *)projections
39 |                     inputTextures:(NSArray<id<MTLTexture>> *)inputTextures
40 |                     outputTexture:(id<MTLTexture>)outputTexture
41 | {
42 |     self.renderPassDescriptor.colorAttachments[0].texture = outputTexture;
43 |     id<MTLCommandBuffer> commandBuffer = [self.commandQueue commandBuffer];
44 |     id<MTLRenderCommandEncoder> encoder = [commandBuffer renderCommandEncoderWithDescriptor:self.renderPassDescriptor];
45 |     [encoder setCullMode:MTLCullModeNone];
46 |     [encoder setRenderPipelineState:pipeline.state];
47 |     [encoder setVertexBuffer:model.vertexBuffer offset:0 atIndex:0];
48 |     for (NSUInteger i = 0; i < inputTextures.count; i++) {
49 |         [encoder setFragmentTexture:inputTextures[i] atIndex:i];
50 |     }
51 |     for (NSUInteger i = 0; i < projections.count; i++) {
52 |         [encoder setViewport:viewports[i]];
53 |         [encoder setVertexBuffer:projections[i].matrixBuffer offset:0 atIndex:1];
54 |         [encoder drawIndexedPrimitives:model.primitiveType
55 |                             indexCount:model.indexCount
56 |                              indexType:model.indexType
57 |                            indexBuffer:model.indexBuffer
58 |                      indexBufferOffset:0];
59 |     }
60 |     [encoder endEncoding];
61 |     return commandBuffer;
62 | }
63 | 
64 | @end
65 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalSphereModel.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalSphereModel.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/25.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalModel.h"
10 | 
11 | @interface SGMetalSphereModel : SGMetalModel
12 | 
13 | @end
14 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalSphereModel.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalSphereModel.m
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/25.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalSphereModel.h"
10 | #import "SGMetalTypes.h"
11 | 
12 | @implementation SGMetalSphereModel
13 | 
14 | static int const slicesCount    = 200;
15 | static int const parallelsCount = slicesCount / 2;
16 | static int const indicesCount   = slicesCount * parallelsCount * 6;
17 | static int const verticesCount  = (slicesCount + 1) * (parallelsCount + 1);
18 | 
19 | static UInt32        indices [indicesCount];
20 | static SGMetalVertex vertices[verticesCount];
21 | 
22 | - (instancetype)initWithDevice:(id<MTLDevice>)device
23 | {
24 |     if (self = [super initWithDevice:device]) {
25 |         static dispatch_once_t onceToken;
26 |         dispatch_once(&onceToken, ^{
27 |             int runCount = 0;
28 |             float const radius = 1.0f;
29 |             float const step = (2.0f * M_PI) / (float)slicesCount;
30 |             for (int i = 0; i < parallelsCount + 1; i++) {
31 |                 for (int j = 0; j < slicesCount + 1; j++) {
32 |                     SGMetalVertex vertex;
33 |                     vertex.position[0] = radius * sinf(step * (float)i) * cosf(step * (float)j);
34 |                     vertex.position[1] = radius * cosf(step * (float)i);
35 |                     vertex.position[2] = radius * sinf(step * (float)i) * sinf(step * (float)j);
36 |                     vertex.position[3] = 1.0;
37 |                     vertex.texCoord[0] = (float)j / (float)slicesCount;
38 |                     vertex.texCoord[1] = (float)i / (float)parallelsCount;
39 |                     vertices[i * (slicesCount + 1) + j] = vertex;
40 |                     if (i < parallelsCount && j < slicesCount) {
41 |                         indices[runCount++] = i * (slicesCount + 1) + j;
42 |                         indices[runCount++] = (i + 1) * (slicesCount + 1) + j;
43 |                         indices[runCount++] = (i + 1) * (slicesCount + 1) + (j + 1);
44 |                         indices[runCount++] = i * (slicesCount + 1) + j;
45 |                         indices[runCount++] = (i + 1) * (slicesCount + 1) + (j + 1);
46 |                         indices[runCount++] = i * (slicesCount + 1) + (j + 1);
47 |                     }
48 |                 }
49 |             }
50 |         });
51 |         self.indexCount = indicesCount;
52 |         self.indexType = MTLIndexTypeUInt32;
53 |         self.primitiveType = MTLPrimitiveTypeTriangle;
54 |         self.indexBuffer = [self.device newBufferWithBytes:indices length:sizeof(indices) options:MTLResourceStorageModeShared];
55 |         self.vertexBuffer = [self.device newBufferWithBytes:vertices length:sizeof(vertices) options:MTLResourceStorageModeShared];
56 |     }
57 |     return self;
58 | }
59 | 
60 | @end
61 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalTextureLoader.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalTextureLoader.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Metal/Metal.h>
10 | #import <CoreVideo/CoreVideo.h>
11 | 
12 | @interface SGMetalTextureLoader : NSObject
13 | 
14 | - (instancetype)initWithDevice:(id<MTLDevice>)device;
15 | 
16 | - (NSArray<id<MTLTexture>> *)texturesWithCVPixelBuffer:(CVPixelBufferRef)pixelBuffer;
17 | 
18 | - (NSArray<id<MTLTexture>> *)texturesWithCVPixelFormat:(OSType)pixelFormat
19 |                                                  width:(NSUInteger)width
20 |                                                 height:(NSUInteger)height
21 |                                                  bytes:(void **)bytes
22 |                                            bytesPerRow:(int *)bytesPerRow;
23 | 
24 | - (id<MTLTexture>)textureWithPixelFormat:(MTLPixelFormat)pixelFormat
25 |                                    width:(NSUInteger)width
26 |                                   height:(NSUInteger)height
27 |                                    bytes:(void *)bytes
28 |                              bytesPerRow:(NSUInteger)bytesPerRow;
29 | 
30 | @end
31 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalTypes.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalTypes.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/21.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #ifndef SGMetalTypes_h
10 | #define SGMetalTypes_h
11 | 
12 | #include <simd/simd.h>
13 | 
14 | typedef struct {
15 |     vector_float4 position;
16 |     vector_float2 texCoord;
17 | } SGMetalVertex;
18 | 
19 | typedef struct {
20 |     matrix_float4x4 mvp;
21 | } SGMetalMatrix;
22 | 
23 | #endif /* SGMetalTypes_h */
24 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalViewport.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalViewport.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/27.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Metal/Metal.h>
10 | 
11 | typedef NS_ENUM(NSUInteger, SGMetalViewportMode) {
12 |     SGMetalViewportModeResize           = 0,
13 |     SGMetalViewportModeResizeAspect     = 1,
14 |     SGMetalViewportModeResizeAspectFill = 2,
15 | };
16 | 
17 | @interface SGMetalViewport : NSObject
18 | 
19 | + (MTLViewport)viewportWithLayerSize:(MTLSize)layerSize;
20 | + (MTLViewport)viewportWithLayerSizeForLeft:(MTLSize)layerSize;
21 | + (MTLViewport)viewportWithLayerSizeForRight:(MTLSize)layerSize;
22 | + (MTLViewport)viewportWithLayerSize:(MTLSize)layerSize textureSize:(MTLSize)textureSize mode:(SGMetalViewportMode)mode;
23 | 
24 | 
25 | @end
26 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalYUVRenderPipeline.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalYUVRenderPipeline.h
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalRenderPipeline.h"
10 | 
11 | @interface SGMetalYUVRenderPipeline : SGMetalRenderPipeline
12 | 
13 | @end
14 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGMetal/SGMetalYUVRenderPipeline.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMetalYUVRenderPipeline.m
 3 | //  MetalTest
 4 | //
 5 | //  Created by Single on 2019/6/26.
 6 | //  Copyright © 2019 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGMetalYUVRenderPipeline.h"
10 | 
11 | @implementation SGMetalYUVRenderPipeline
12 | 
13 | - (instancetype)initWithDevice:(id<MTLDevice>)device library:(id<MTLLibrary>)library
14 | {
15 |     if (self = [super initWithDevice:device library:library]) {
16 |         self.descriptor = [[MTLRenderPipelineDescriptor alloc] init];
17 |         self.descriptor.vertexFunction = [self.library newFunctionWithName:@"vertexShader"];
18 |         self.descriptor.fragmentFunction = [self.library newFunctionWithName:@"fragmentShaderYUV"];
19 |         self.descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
20 |         self.state = [self.device newRenderPipelineStateWithDescriptor:self.descriptor error:nil];
21 |     }
22 |     return self;
23 | }
24 | 
25 | @end
26 | 
27 | 
28 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGDecoderOptions.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/14.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGAudioDescriptor.h"
11 | #import "SGTime.h"
12 | 
13 | @interface SGDecoderOptions : NSObject <NSCopying>
14 | 
15 | /*!
16 |  @property options
17 |  @abstract
18 |     The options for avformat_open_input.
19 |     Default is nil.
20 |  */
21 | @property (nonatomic, copy) NSDictionary *options;
22 | 
23 | /*!
24 |  @property threadsAuto
25 |  @abstract
26 |     The option for avformat_open_input.
27 |     Default is YES.
28 |  */
29 | @property (nonatomic) BOOL threadsAuto;
30 | 
31 | /*!
32 |  @property refcountedFrames
33 |  @abstract
34 |     The option for avformat_open_input.
35 |     Default is YES.
36 |  */
37 | @property (nonatomic) BOOL refcountedFrames;
38 | 
39 | /*!
40 |  @property hardwareDecodeH264
41 |  @abstract
42 |     Indicates whether hardware decoding is enabled for H264.
43 |     Default is YES.
44 |  */
45 | @property (nonatomic) BOOL hardwareDecodeH264;
46 | 
47 | /*!
48 |  @property hardwareDecodeH265
49 |  @abstract
50 |     Indicates whether hardware decoding is enabled for H265.
51 |     Default is YES.
52 |  */
53 | @property (nonatomic) BOOL hardwareDecodeH265;
54 | 
55 | /*!
56 |  @property preferredPixelFormat
57 |  @abstract
58 |     Indicates the default hardware decoding output format.
59 |     Default is kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange.
60 |  */
61 | @property (nonatomic) OSType preferredCVPixelFormat;
62 | 
63 | /*!
64 |  @property supportedPixelFormats
65 |  @abstract
66 |     Indicates the supported pixel formats.
67 |  */
68 | @property (nonatomic, copy) NSArray<NSNumber *> *supportedPixelFormats;
69 | 
70 | /*!
71 |  @property supportedAudioDescriptors
72 |  @abstract
73 |     Indicates the supported audio descriptors.
74 |  */
75 | @property (nonatomic, copy) NSArray<SGAudioDescriptor *> *supportedAudioDescriptors;
76 | 
77 | /*!
78 |  @property resetFrameRate
79 |  @abstract
80 |     Indicates whether video decoder needs reset frame rate.
81 |     Default is NO.
82 |  */
83 | @property (nonatomic) BOOL resetFrameRate;
84 | 
85 | /*!
86 |  @property preferredFrameRate
87 |  @abstract
88 |     Indicates the preferred video track frame rate.
89 |     Default is (1, 25).
90 |  */
91 | @property (nonatomic) CMTime preferredFrameRate;
92 | 
93 | @end
94 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGOption/SGDecoderOptions.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGDecoderOptions.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/14.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGDecoderOptions.h"
10 | #import "SGAudioRenderer.h"
11 | #import "SGVideoRenderer.h"
12 | #import "SGMapping.h"
13 | 
14 | @implementation SGDecoderOptions
15 | 
16 | - (id)copyWithZone:(NSZone *)zone
17 | {
18 |     SGDecoderOptions *obj = [[SGDecoderOptions alloc] init];
19 |     obj->_options = self->_options.copy;
20 |     obj->_threadsAuto = self->_threadsAuto;
21 |     obj->_refcountedFrames = self->_refcountedFrames;
22 |     obj->_hardwareDecodeH264 = self->_hardwareDecodeH264;
23 |     obj->_hardwareDecodeH265 = self->_hardwareDecodeH265;
24 |     obj->_preferredCVPixelFormat = self->_preferredCVPixelFormat;
25 |     obj->_supportedPixelFormats = self->_supportedPixelFormats.copy;
26 |     obj->_supportedAudioDescriptors = self->_supportedAudioDescriptors.copy;
27 |     obj->_resetFrameRate = self->_resetFrameRate;
28 |     obj->_preferredFrameRate = self->_preferredFrameRate;
29 |     return obj;
30 | }
31 | 
32 | - (instancetype)init
33 | {
34 |     if (self = [super init]) {
35 |         self->_options = nil;
36 |         self->_threadsAuto = YES;
37 |         self->_refcountedFrames = YES;
38 |         self->_hardwareDecodeH264 = YES;
39 |         self->_hardwareDecodeH265 = YES;
40 |         self->_preferredCVPixelFormat = SGPixelFormatFF2AV(AV_PIX_FMT_NV12);
41 |         self->_supportedPixelFormats = [SGVideoRenderer supportedPixelFormats];
42 |         self->_supportedAudioDescriptors = @[[SGAudioRenderer supportedAudioDescriptor]];
43 |         self->_resetFrameRate = NO;
44 |         self->_preferredFrameRate = CMTimeMake(1, 25);
45 |     }
46 |     return self;
47 | }
48 | 
49 | @end
50 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGOption/SGDemuxerOptions.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGDemuxerOptions.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/14.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | 
11 | @interface SGDemuxerOptions : NSObject <NSCopying>
12 | 
13 | /*!
14 |  @property options
15 |  @abstract
16 |     The options for avformat_open_input.
17 |     Default:
18 |         @{@"reconnect" : @(1),
19 |           @"user-agent" : @"SGPlayer",
20 |           @"timeout" : @(20 * 1000 * 1000)}
21 |  */
22 | @property (nonatomic, copy) NSDictionary *options;
23 | 
24 | @end
25 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGOption/SGDemuxerOptions.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGDemuxerOptions.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/14.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGDemuxerOptions.h"
10 | 
11 | @implementation SGDemuxerOptions
12 | 
13 | - (id)copyWithZone:(NSZone *)zone
14 | {
15 |     SGDemuxerOptions *obj = [[SGDemuxerOptions alloc] init];
16 |     obj->_options = self->_options.copy;
17 |     return obj;
18 | }
19 | 
20 | - (instancetype)init
21 | {
22 |     if (self = [super init]) {
23 |         self->_options = @{@"reconnect" : @(1),
24 |                            @"user-agent" : @"SGPlayer",
25 |                            @"timeout" : @(20 * 1000 * 1000)};
26 |     }
27 |     return self;
28 | }
29 | 
30 | @end
31 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGOption/SGOptions.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGOptions.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/29.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGProcessorOptions.h"
11 | #import "SGDecoderOptions.h"
12 | #import "SGDemuxerOptions.h"
13 | 
14 | @interface SGOptions : NSObject <NSCopying>
15 | 
16 | /*!
17 |  @method sharedOptions
18 |  @abstract
19 |     Globally shared configuration options.
20 |  */
21 | + (instancetype)sharedOptions;
22 | 
23 | /*!
24 |  @property demuxer
25 |  @abstract
26 |     The options for demuxer.
27 |  */
28 | @property (nonatomic, strong) SGDemuxerOptions *demuxer;
29 | 
30 | /*!
31 |  @property decoder
32 |  @abstract
33 |     The options for decoder.
34 |  */
35 | @property (nonatomic, strong) SGDecoderOptions *decoder;
36 | 
37 | /*!
38 |  @property processor
39 |  @abstract
40 |     The options for processor.
41 |  */
42 | @property (nonatomic, strong) SGProcessorOptions *processor;
43 | 
44 | @end
45 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGOption/SGOptions.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGOptions.m
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/29.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGOptions.h"
10 | 
11 | @implementation SGOptions
12 | 
13 | + (instancetype)sharedOptions
14 | {
15 |     static SGOptions *obj = nil;
16 |     static dispatch_once_t onceToken;
17 |     dispatch_once(&onceToken, ^{
18 |         obj = [[SGOptions alloc] init];
19 |     });
20 |     return obj;
21 | }
22 | 
23 | - (id)copyWithZone:(NSZone *)zone
24 | {
25 |     SGOptions *obj = [[SGOptions alloc] init];
26 |     obj->_demuxer = self->_demuxer.copy;
27 |     obj->_decoder = self->_decoder.copy;
28 |     obj->_processor = self->_processor.copy;
29 |     return obj;
30 | }
31 | 
32 | - (instancetype)init
33 | {
34 |     if (self = [super init]) {
35 |         self->_demuxer = [[SGDemuxerOptions alloc] init];
36 |         self->_decoder = [[SGDecoderOptions alloc] init];
37 |         self->_processor = [[SGProcessorOptions alloc] init];
38 |     }
39 |     return self;
40 | }
41 | 
42 | @end
43 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGProcessorOptions.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/8/13.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | 
11 | @interface SGProcessorOptions : NSObject <NSCopying>
12 | 
13 | /*!
14 |  @property audioClass
15 |  @abstract
16 |     The audio frame processor class.
17 |     Default is SGAudioProcessor.
18 |  */
19 | @property (nonatomic, copy) Class audioClass;
20 | 
21 | /*!
22 |  @property videoClass
23 |  @abstract
24 |     The video frame processor class.
25 |     Default is SGVideoProcessor.
26 |  */
27 | @property (nonatomic, copy) Class videoClass;
28 | 
29 | @end
30 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGOption/SGProcessorOptions.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGProcessorOptions.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/8/13.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGProcessorOptions.h"
10 | #import "SGAudioProcessor.h"
11 | #import "SGVideoProcessor.h"
12 | 
13 | @implementation SGProcessorOptions
14 | 
15 | - (id)copyWithZone:(NSZone *)zone
16 | {
17 |     SGProcessorOptions *obj = [[SGProcessorOptions alloc] init];
18 |     obj->_audioClass = self->_audioClass.copy;
19 |     obj->_videoClass = self->_videoClass.copy;
20 |     return obj;
21 | }
22 | 
23 | - (instancetype)init
24 | {
25 |     if (self = [super init]) {
26 |         self->_audioClass = [SGAudioProcessor class];
27 |         self->_videoClass = [SGVideoProcessor class];
28 |     }
29 |     return self;
30 | }
31 | 
32 | @end
33 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGPlatform/SGPLFColor.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPLFColor.h
 3 | //  SGPlatform
 4 | //
 5 | //  Created by Single on 2017/2/24.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPLFObject.h"
10 | 
11 | #if SGPLATFORM_TARGET_OS_MAC
12 | 
13 | typedef NSColor SGPLFColor;
14 | 
15 | #elif SGPLATFORM_TARGET_OS_IPHONE_OR_TV
16 | 
17 | typedef UIColor SGPLFColor;
18 | 
19 | #endif
20 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGPlatform/SGPLFColor.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPLFColor.m
 3 | //  SGPlatform
 4 | //
 5 | //  Created by Single on 2017/2/24.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPLFColor.h"
10 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGPlatform/SGPLFImage.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPLFImage.h
 3 | //  SGPlatform
 4 | //
 5 | //  Created by Single on 2017/2/24.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPLFObject.h"
10 | #import <CoreVideo/CoreVideo.h>
11 | #import <CoreImage/CoreImage.h>
12 | 
13 | #if SGPLATFORM_TARGET_OS_MAC
14 | 
15 | typedef NSImage SGPLFImage;
16 | 
17 | #elif SGPLATFORM_TARGET_OS_IPHONE_OR_TV
18 | 
19 | typedef UIImage SGPLFImage;
20 | 
21 | #endif
22 | 
23 | SGPLFImage * SGPLFImageWithCGImage(CGImageRef image);
24 | 
25 | // CVPixelBufferRef
26 | SGPLFImage * SGPLFImageWithCVPixelBuffer(CVPixelBufferRef pixelBuffer);
27 | CIImage * SGPLFImageCIImageWithCVPexelBuffer(CVPixelBufferRef pixelBuffer);
28 | CGImageRef SGPLFImageCGImageWithCVPexelBuffer(CVPixelBufferRef pixelBuffer);
29 | 
30 | // RGB data buffer
31 | SGPLFImage * SGPLFImageWithRGBData(uint8_t *rgb_data, int linesize, int width, int height);
32 | CGImageRef SGPLFImageCGImageWithRGBData(uint8_t *rgb_data, int linesize, int width, int height);
33 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGPlatform/SGPLFObject.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPLFObject.h
 3 | //  SGPlatform
 4 | //
 5 | //  Created by Single on 2017/2/24.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #ifndef SGPLFObject_h
10 | #define SGPLFObject_h
11 | 
12 | #import "SGPLFTargets.h"
13 | 
14 | #if SGPLATFORM_TARGET_OS_MAC
15 | 
16 | #import <Cocoa/Cocoa.h>
17 | 
18 | #elif SGPLATFORM_TARGET_OS_IPHONE_OR_TV
19 | 
20 | #import <UIKit/UIKit.h>
21 | 
22 | #endif
23 | 
24 | #endif /* SGPLFObject_h */
25 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGPlatform/SGPLFScreen.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPLFScreen.h
 3 | //  SGPlatform
 4 | //
 5 | //  Created by Single on 2017/2/24.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPLFObject.h"
10 | 
11 | #if SGPLATFORM_TARGET_OS_MAC
12 | 
13 | typedef NSScreen SGPLFScreen;
14 | 
15 | #elif SGPLATFORM_TARGET_OS_IPHONE_OR_TV
16 | 
17 | typedef UIScreen SGPLFScreen;
18 | 
19 | #endif
20 | 
21 | CGFloat SGPLFScreenGetScale(void);
22 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGPlatform/SGPLFScreen.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPLFScreen.m
 3 | //  SGPlatform
 4 | //
 5 | //  Created by Single on 2017/2/24.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPLFScreen.h"
10 | 
11 | #if SGPLATFORM_TARGET_OS_MAC
12 | 
13 | CGFloat SGPLFScreenGetScale(void)
14 | {
15 |     return [NSScreen mainScreen].backingScaleFactor;
16 | }
17 | 
18 | #elif SGPLATFORM_TARGET_OS_IPHONE_OR_TV
19 | 
20 | CGFloat SGPLFScreenGetScale(void)
21 | {
22 |     return [UIScreen mainScreen].scale;
23 | }
24 | 
25 | #endif
26 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGPlatform/SGPLFTargets.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPLFTargets.h
 3 | //  SGPlatform
 4 | //
 5 | //  Created by Single on 2017/2/23.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #ifndef SGPLFTargets_h
10 | #define SGPLFTargets_h
11 | 
12 | #import <TargetConditionals.h>
13 | 
14 | #define SGPLATFORM_TARGET_OS_MAC    TARGET_OS_OSX
15 | #define SGPLATFORM_TARGET_OS_IPHONE TARGET_OS_IOS
16 | #define SGPLATFORM_TARGET_OS_TV     TARGET_OS_TV
17 | 
18 | #define SGPLATFORM_TARGET_OS_MAC_OR_IPHONE (SGPLATFORM_TARGET_OS_MAC || SGPLATFORM_TARGET_OS_IPHONE)
19 | #define SGPLATFORM_TARGET_OS_MAC_OR_TV     (SGPLATFORM_TARGET_OS_MAC || SGPLATFORM_TARGET_OS_TV)
20 | #define SGPLATFORM_TARGET_OS_IPHONE_OR_TV  (SGPLATFORM_TARGET_OS_IPHONE || SGPLATFORM_TARGET_OS_TV)
21 | 
22 | #endif /* SGPLFTargets_h */
23 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGPlatform/SGPLFView.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPLFView.h
 3 | //  SGPlatform
 4 | //
 5 | //  Created by Single on 2017/2/24.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGPLFObject.h"
10 | #import "SGPLFImage.h"
11 | #import "SGPLFColor.h"
12 | 
13 | #if SGPLATFORM_TARGET_OS_MAC
14 | 
15 | typedef NSView SGPLFView;
16 | 
17 | #elif SGPLATFORM_TARGET_OS_IPHONE_OR_TV
18 | 
19 | typedef UIView SGPLFView;
20 | 
21 | #endif
22 | 
23 | void SGPLFViewSetBackgroundColor(SGPLFView *view, SGPLFColor *color);
24 | void SGPLFViewInsertSubview(SGPLFView *superView, SGPLFView *subView, NSInteger index);
25 | 
26 | SGPLFImage * SGPLFViewGetCurrentSnapshot(SGPLFView *view);
27 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGAudioFormatter.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioFormatter.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/30.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGAudioDescriptor.h"
11 | #import "SGAudioFrame.h"
12 | 
13 | @interface SGAudioFormatter : NSObject
14 | 
15 | /**
16 |  *
17 |  */
18 | @property (nonatomic, copy) SGAudioDescriptor *descriptor;
19 | 
20 | /**
21 |  *
22 |  */
23 | - (SGAudioFrame *)format:(SGAudioFrame *)frame;
24 | 
25 | /**
26 |  *
27 |  */
28 | - (SGAudioFrame *)finish;
29 | 
30 | /**
31 |  *
32 |  */
33 | - (void)flush;
34 | 
35 | @end
36 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGAudioMixer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioMixer.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/29.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGAudioDescriptor.h"
11 | #import "SGAudioFrame.h"
12 | #import "SGCapacity.h"
13 | 
14 | @interface SGAudioMixer : NSObject
15 | 
16 | + (instancetype)new NS_UNAVAILABLE;
17 | - (instancetype)init NS_UNAVAILABLE;
18 | 
19 | /**
20 |  *
21 |  */
22 | - (instancetype)initWithTracks:(NSArray<SGTrack *> *)tracks weights:(NSArray<NSNumber *> *)weights;
23 | 
24 | /**
25 |  *
26 |  */
27 | @property (nonatomic, copy, readonly) NSArray<SGTrack *> *tracks;
28 | 
29 | /**
30 |  *
31 |  */
32 | @property (nonatomic, copy) NSArray<NSNumber *> *weights;
33 | 
34 | /**
35 |  *
36 |  */
37 | - (SGAudioFrame *)putFrame:(SGAudioFrame *)frame;
38 | 
39 | /**
40 |  *
41 |  */
42 | - (SGAudioFrame *)finish;
43 | 
44 | /**
45 |  *
46 |  */
47 | - (SGCapacity)capacity;
48 | 
49 | /**
50 |  *
51 |  */
52 | - (void)flush;
53 | 
54 | @end
55 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGAudioMixerUnit.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioMixerUnit.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/29.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGAudioFrame.h"
11 | #import "SGCapacity.h"
12 | 
13 | @interface SGAudioMixerUnit : NSObject
14 | 
15 | /**
16 |  *
17 |  */
18 | @property (nonatomic, readonly) CMTimeRange timeRange;
19 | 
20 | /**
21 |  *
22 |  */
23 | - (BOOL)putFrame:(SGAudioFrame *)frame;
24 | 
25 | /**
26 |  *
27 |  */
28 | - (NSArray<SGAudioFrame *> *)framesToEndTime:(CMTime)endTime;
29 | 
30 | /**
31 |  *
32 |  */
33 | - (SGCapacity)capacity;
34 | 
35 | /**
36 |  *
37 |  */
38 | - (void)flush;
39 | 
40 | @end
41 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGAudioMixerUnit.m:
--------------------------------------------------------------------------------
  1 | //
  2 | //  SGAudioMixerUnit.m
  3 | //  SGPlayer
  4 | //
  5 | //  Created by Single on 2018/11/29.
  6 | //  Copyright © 2018 single. All rights reserved.
  7 | //
  8 | 
  9 | #import "SGAudioMixerUnit.h"
 10 | 
 11 | @interface SGAudioMixerUnit ()
 12 | 
 13 | {
 14 |     SGCapacity _capacity;
 15 | }
 16 | 
 17 | @property (nonatomic, strong, readonly) NSMutableArray<SGAudioFrame *> *frames;
 18 | 
 19 | @end
 20 | 
 21 | @implementation SGAudioMixerUnit
 22 | 
 23 | - (instancetype)init
 24 | {
 25 |     if (self = [super init]) {
 26 |         [self flush];
 27 |     }
 28 |     return self;
 29 | }
 30 | 
 31 | - (void)dealloc
 32 | {
 33 |     for (SGAudioFrame *obj in self->_frames) {
 34 |         [obj unlock];
 35 |     }
 36 | }
 37 | 
 38 | #pragma mark - Control
 39 | 
 40 | - (BOOL)putFrame:(SGAudioFrame *)frame
 41 | {
 42 |     if (CMTIMERANGE_IS_VALID(self->_timeRange) &&
 43 |         CMTimeCompare(CMTimeAdd(frame.timeStamp, frame.duration), CMTimeRangeGetEnd(self->_timeRange)) <= 0) {
 44 |         return NO;
 45 |     }
 46 |     [frame lock];
 47 |     [self->_frames addObject:frame];
 48 |     [self updateTimeRange];
 49 |     return YES;
 50 | }
 51 | 
 52 | - (NSArray<SGAudioFrame *> *)framesToEndTime:(CMTime)endTime
 53 | {
 54 |     NSMutableArray<SGAudioFrame *> *ret = [NSMutableArray array];
 55 |     NSMutableArray<SGAudioFrame *> *remove = [NSMutableArray array];
 56 |     for (SGAudioFrame *obj in self->_frames) {
 57 |         if (CMTimeCompare(obj.timeStamp, endTime) < 0) {
 58 |             [obj lock];
 59 |             [ret addObject:obj];
 60 |         }
 61 |         if (CMTimeCompare(CMTimeAdd(obj.timeStamp, obj.duration), endTime) <= 0) {
 62 |             [obj unlock];
 63 |             [remove addObject:obj];
 64 |         }
 65 |     }
 66 |     [self->_frames removeObjectsInArray:remove];
 67 |     [self updateTimeRange];
 68 |     return [ret copy];
 69 | }
 70 | 
 71 | - (SGCapacity)capacity
 72 | {
 73 |     return self->_capacity;
 74 | }
 75 | 
 76 | - (void)flush
 77 | {
 78 |     for (SGAudioFrame *obj in self->_frames) {
 79 |         [obj unlock];
 80 |     }
 81 |     self->_capacity = SGCapacityCreate();
 82 |     self->_frames = [NSMutableArray array];
 83 |     self->_timeRange = kCMTimeRangeInvalid;
 84 | }
 85 | 
 86 | #pragma mark - Internal
 87 | 
 88 | - (void)updateTimeRange
 89 | {
 90 |     self->_capacity.count = (int)self->_frames.count;
 91 |     if (self->_frames.count == 0) {
 92 |         self->_timeRange = kCMTimeRangeInvalid;
 93 |     } else {
 94 |         CMTime start = self->_frames.firstObject.timeStamp;
 95 |         CMTime end = CMTimeAdd(self->_frames.lastObject.timeStamp, self->_frames.lastObject.duration);
 96 |         self->_timeRange = CMTimeRangeFromTimeToTime(start, end);
 97 |     }
 98 | }
 99 | 
100 | @end
101 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioProcessor.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/28.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGProcessor.h"
10 | #import "SGAudioDescriptor.h"
11 | 
12 | @interface SGAudioProcessor : NSObject <SGProcessor>
13 | 
14 | @end
15 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGAudioProcessor.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioProcessor.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/11/28.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGAudioProcessor.h"
10 | #import "SGAudioMixer.h"
11 | 
12 | @interface SGAudioProcessor ()
13 | 
14 | @property (nonatomic, strong, readonly) SGAudioMixer *mixer;
15 | @property (nonatomic, strong, readonly) SGTrackSelection *selection;
16 | 
17 | @end
18 | 
19 | @implementation SGAudioProcessor
20 | 
21 | - (void)setSelection:(SGTrackSelection *)selection action:(SGTrackSelectionAction)action
22 | {
23 |     self->_selection = [selection copy];
24 |     if (action & SGTrackSelectionActionTracks) {
25 |         self->_mixer = [[SGAudioMixer alloc] initWithTracks:selection.tracks weights:selection.weights];
26 |     } else if (action & SGTrackSelectionActionWeights) {
27 |         self->_mixer.weights = selection.weights;
28 |     }
29 | }
30 | 
31 | - (__kindof SGFrame *)putFrame:(__kindof SGFrame *)frame
32 | {
33 |     if (![frame isKindOfClass:[SGAudioFrame class]] ||
34 |         ![self->_selection.tracks containsObject:frame.track]) {
35 |         [frame unlock];
36 |         return nil;
37 |     }
38 |     return [self->_mixer putFrame:frame];
39 | }
40 | 
41 | - (SGAudioFrame *)finish
42 | {
43 |     return [self->_mixer finish];
44 | }
45 | 
46 | - (SGCapacity)capacity
47 | {
48 |     return [self->_mixer capacity];
49 | }
50 | 
51 | - (void)flush
52 | {
53 |     [self->_mixer flush];
54 | }
55 | 
56 | - (void)close
57 | {
58 |     self->_mixer = nil;
59 | }
60 | 
61 | @end
62 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGProcessor.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGProcessor.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/8/13.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGTrackSelection.h"
11 | #import "SGCapacity.h"
12 | #import "SGFrame.h"
13 | 
14 | @protocol SGProcessor <NSObject>
15 | 
16 | /**
17 |  *
18 |  */
19 | - (void)setSelection:(SGTrackSelection *)selection action:(SGTrackSelectionAction)action;
20 | 
21 | /**
22 |  *
23 |  */
24 | - (__kindof SGFrame *)putFrame:(__kindof SGFrame *)frame;
25 | 
26 | /**
27 |  *
28 |  */
29 | - (__kindof SGFrame *)finish;
30 | 
31 | /**
32 |  *
33 |  */
34 | - (SGCapacity)capacity;
35 | 
36 | /**
37 |  *
38 |  */
39 | - (void)flush;
40 | 
41 | /**
42 |  *
43 |  */
44 | - (void)close;
45 | 
46 | @end
47 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGSWResample.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGSWResample.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/10/30.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGAudioDescriptor.h"
11 | 
12 | @interface SGSWResample : NSObject
13 | 
14 | /**
15 |  *
16 |  */
17 | @property (nonatomic, copy) SGAudioDescriptor *inputDescriptor;
18 | @property (nonatomic, copy) SGAudioDescriptor *outputDescriptor;
19 | 
20 | /**
21 |  *
22 |  */
23 | - (BOOL)open;
24 | 
25 | /**
26 |  *
27 |  */
28 | - (int)write:(uint8_t **)data nb_samples:(int)nb_samples;
29 | 
30 | /**
31 |  *
32 |  */
33 | - (int)read:(uint8_t **)data nb_samples:(int)nb_samples;
34 | 
35 | /**
36 |  *
37 |  */
38 | - (int)delay;
39 | 
40 | @end
41 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGSWScale.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGSWScale.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/28.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGVideoDescriptor.h"
11 | 
12 | @interface SGSWScale : NSObject
13 | 
14 | /**
15 |  *
16 |  */
17 | + (BOOL)isSupportedInputFormat:(int)format;
18 | 
19 | /**
20 |  *
21 |  */
22 | + (BOOL)isSupportedOutputFormat:(int)format;
23 | 
24 | /**
25 |  *
26 |  */
27 | @property (nonatomic, copy) SGVideoDescriptor *inputDescriptor;
28 | 
29 | /**
30 |  *
31 |  */
32 | @property (nonatomic, copy) SGVideoDescriptor *outputDescriptor;
33 | 
34 | /**
35 |  *
36 |  */
37 | @property (nonatomic) int flags;          // SWS_FAST_BILINEAR
38 | 
39 | /**
40 |  *
41 |  */
42 | - (BOOL)open;
43 | 
44 | /**
45 |  *
46 |  */
47 | - (int)convert:(const uint8_t * const [])inputData inputLinesize:(const int[])inputLinesize outputData:(uint8_t * const [])outputData outputLinesize:(const int[])outputLinesize;
48 | 
49 | @end
50 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGSWScale.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGSWScale.m
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/28.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGSWScale.h"
10 | #import "SGFFmpeg.h"
11 | 
12 | @interface SGSWScale ()
13 | 
14 | @property (nonatomic, readonly) struct SwsContext *context;
15 | 
16 | @end
17 | 
18 | @implementation SGSWScale
19 | 
20 | + (BOOL)isSupportedInputFormat:(int)format
21 | {
22 |     return sws_isSupportedInput(format) > 0;
23 | }
24 | 
25 | + (BOOL)isSupportedOutputFormat:(int)format
26 | {
27 |     return sws_isSupportedOutput(format) > 0;
28 | }
29 | 
30 | - (instancetype)init
31 | {
32 |     if (self = [super init]) {
33 |         self->_flags = SWS_FAST_BILINEAR;
34 |     }
35 |     return self;
36 | }
37 | 
38 | - (void)dealloc
39 | {
40 |     if (self->_context) {
41 |         sws_freeContext(self->_context);
42 |         self->_context = nil;
43 |     }
44 | }
45 | 
46 | - (BOOL)open
47 | {
48 |     if (!self->_inputDescriptor ||
49 |         !self->_outputDescriptor) {
50 |         return NO;
51 |     }
52 |     self->_context = sws_getCachedContext(self->_context,
53 |                                           self->_inputDescriptor.width,
54 |                                           self->_inputDescriptor.height,
55 |                                           self->_inputDescriptor.format,
56 |                                           self->_outputDescriptor.width,
57 |                                           self->_outputDescriptor.height,
58 |                                           self->_outputDescriptor.format,
59 |                                           self->_flags,
60 |                                           NULL, NULL, NULL);
61 |     return self->_context ? YES : NO;
62 | }
63 | 
64 | - (int)convert:(const uint8_t *const [])inputData inputLinesize:(const int [])inputLinesize outputData:(uint8_t *const [])outputData outputLinesize:(const int [])outputLinesize
65 | {
66 |     return sws_scale(self->_context,
67 |                      inputData,
68 |                      inputLinesize,
69 |                      0,
70 |                      self->_inputDescriptor.height,
71 |                      outputData,
72 |                      outputLinesize);
73 | }
74 | 
75 | @end
76 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGSonic.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGSonic.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/12/20.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGAudioDescriptor.h"
11 | 
12 | @interface SGSonic : NSObject
13 | 
14 | /**
15 |  *
16 |  */
17 | + (instancetype)new NS_UNAVAILABLE;
18 | - (instancetype)init NS_UNAVAILABLE;
19 | 
20 | /**
21 |  *
22 |  */
23 | - (instancetype)initWithDescriptor:(SGAudioDescriptor *)descriptor;
24 | 
25 | /**
26 |  *
27 |  */
28 | @property (nonatomic, copy, readonly) SGAudioDescriptor *descriptor;
29 | 
30 | /**
31 |  *
32 |  */
33 | @property (nonatomic) float speed;
34 | 
35 | /**
36 |  *
37 |  */
38 | @property (nonatomic) float pitch;
39 | 
40 | /**
41 |  *
42 |  */
43 | @property (nonatomic) float rate;
44 | 
45 | /**
46 |  *
47 |  */
48 | @property (nonatomic) float volume;
49 | 
50 | /**
51 |  *
52 |  */
53 | - (BOOL)open;
54 | 
55 | /**
56 |  *
57 |  */
58 | - (int)flush;
59 | 
60 | /**
61 |  *
62 |  */
63 | - (int)samplesInput;
64 | 
65 | /**
66 |  *
67 |  */
68 | - (int)samplesAvailable;
69 | 
70 | /**
71 |  *
72 |  */
73 | - (int)write:(uint8_t **)data nb_samples:(int)nb_samples;
74 | 
75 | /**
76 |  *
77 |  */
78 | - (int)read:(uint8_t **)data nb_samples:(int)nb_samples;
79 | 
80 | @end
81 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGVideoProcessor.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/8/13.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGProcessor.h"
10 | 
11 | @interface SGVideoProcessor : NSObject <SGProcessor>
12 | 
13 | @end
14 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGProcessor/SGVideoProcessor.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGVideoProcessor.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/8/13.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGVideoProcessor.h"
10 | #import "SGVideoFrame.h"
11 | 
12 | @interface SGVideoProcessor ()
13 | 
14 | @property (nonatomic, strong, readonly) SGTrackSelection *selection;
15 | 
16 | @end
17 | 
18 | @implementation SGVideoProcessor
19 | 
20 | - (void)setSelection:(SGTrackSelection *)selection action:(SGTrackSelectionAction)action
21 | {
22 |     self->_selection = [selection copy];
23 | }
24 | 
25 | - (__kindof SGFrame *)putFrame:(__kindof SGFrame *)frame
26 | {
27 |     if (![frame isKindOfClass:[SGVideoFrame class]] ||
28 |         ![self->_selection.tracks containsObject:frame.track]) {
29 |         [frame unlock];
30 |         return nil;
31 |     }
32 |     return frame;
33 | }
34 | 
35 | - (__kindof SGFrame *)finish
36 | {
37 |     return nil;
38 | }
39 | 
40 | - (SGCapacity)capacity
41 | {
42 |     return SGCapacityCreate();
43 | }
44 | 
45 | - (void)flush
46 | {
47 | 
48 | }
49 | 
50 | - (void)close
51 | {
52 | 
53 | }
54 | 
55 | @end
56 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGRenderer/SGAudioRenderer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGAudioRenderer.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/19.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGAudioDescriptor.h"
11 | 
12 | @interface SGAudioRenderer : NSObject
13 | 
14 | /*!
15 |  @method supportedAudioDescriptor
16 |  @abstract
17 |     Indicates all supported audio descriptor.
18 | */
19 | + (SGAudioDescriptor *)supportedAudioDescriptor;
20 | 
21 | /*!
22 |  @property pitch
23 |  @abstract
24 |     Indicates the current pitch.
25 |  */
26 | @property (nonatomic) Float64 pitch;
27 | 
28 | /*!
29 |  @property volume
30 |  @abstract
31 |     Indicates the current volume.
32 |  */
33 | @property (nonatomic) Float64 volume;
34 | 
35 | @end
36 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGRenderer/SGClock+Internal.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGRenderer+Internal.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/11/1.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGClock.h"
10 | #import "SGDefines.h"
11 | 
12 | @protocol SGClockDelegate;
13 | 
14 | @interface SGClock ()
15 | 
16 | /**
17 |  *
18 |  */
19 | @property (nonatomic, weak) id<SGClockDelegate> delegate;
20 | 
21 | /**
22 |  *
23 |  */
24 | @property (nonatomic) Float64 rate;
25 | 
26 | /**
27 |  *
28 |  */
29 | @property (nonatomic, readonly) CMTime currentTime;
30 | 
31 | /**
32 |  *
33 |  */
34 | - (void)setAudioTime:(CMTime)time running:(BOOL)running;
35 | 
36 | /**
37 |  *
38 |  */
39 | - (void)setVideoTime:(CMTime)time;
40 | 
41 | /**
42 |  *
43 |  */
44 | - (BOOL)open;
45 | 
46 | /**
47 |  *
48 |  */
49 | - (BOOL)close;
50 | 
51 | /**
52 |  *
53 |  */
54 | - (BOOL)pause;
55 | 
56 | /**
57 |  *
58 |  */
59 | - (BOOL)resume;
60 | 
61 | /**
62 |  *
63 |  */
64 | - (BOOL)flush;
65 | 
66 | @end
67 | 
68 | @protocol SGClockDelegate <NSObject>
69 | 
70 | /**
71 |  *
72 |  */
73 | - (void)clock:(SGClock *)clock didChcnageCurrentTime:(CMTime)currentTime;
74 | 
75 | @end
76 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGRenderer/SGClock.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGClock.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/6/14.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | 
11 | @interface SGClock : NSObject
12 | 
13 | @end
14 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGRenderer/SGRenderTimer.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGRenderTimer.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/28.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | 
11 | @interface SGRenderTimer : NSObject
12 | 
13 | - (instancetype)initWithHandler:(dispatch_block_t)handler;
14 | 
15 | @property (nonatomic) NSTimeInterval timeInterval;
16 | @property (nonatomic) BOOL paused;
17 | 
18 | - (void)start;
19 | - (void)stop;
20 | 
21 | @end
22 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGRenderer/SGRenderTimer.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGRenderTimer.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2019/6/28.
 6 | //  Copyright © 2019 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGRenderTimer.h"
10 | 
11 | @interface SGRenderTimer ()
12 | 
13 | @property (nonatomic, copy) dispatch_block_t handler;
14 | @property (nonatomic, strong) NSTimer *timer;
15 | 
16 | @end
17 | 
18 | @implementation SGRenderTimer
19 | 
20 | - (instancetype)initWithHandler:(dispatch_block_t)handler
21 | {
22 |     if (self = [super init]) {
23 |         self.handler = handler;
24 |     }
25 |     return self;
26 | }
27 | 
28 | - (void)dealloc
29 | {
30 |     [self stop];
31 | }
32 | 
33 | - (void)timerHandler
34 | {
35 |     if (self.handler) {
36 |         self.handler();
37 |     }
38 | }
39 | 
40 | - (void)setTimeInterval:(NSTimeInterval)timeInterval
41 | {
42 |     if (self->_timeInterval != timeInterval) {
43 |         self->_timeInterval = timeInterval;
44 |         [self start];
45 |     }
46 | }
47 | 
48 | - (void)setPaused:(BOOL)paused
49 | {
50 |     if (self->_paused != paused) {
51 |         self->_paused = paused;
52 |         [self fire];
53 |     }
54 | }
55 | 
56 | - (void)start
57 | {
58 |     [self stop];
59 |     self->_timer = [NSTimer timerWithTimeInterval:self->_timeInterval
60 |                                            target:self
61 |                                          selector:@selector(timerHandler)
62 |                                          userInfo:nil
63 |                                           repeats:YES];
64 |     [[NSRunLoop mainRunLoop] addTimer:self->_timer
65 |                               forMode:NSRunLoopCommonModes];
66 |     [self fire];
67 | }
68 | 
69 | - (void)stop
70 | {
71 |     [self->_timer invalidate];
72 |     self->_timer = nil;
73 | }
74 | 
75 | - (void)fire
76 | {
77 |     self->_timer.fireDate =
78 |     self->_paused ?
79 |     [NSDate distantFuture] :
80 |     [NSDate distantPast];
81 | }
82 | 
83 | @end
84 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGRenderer/SGRenderable.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGRenderable.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/19.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGCapacity.h"
11 | #import "SGFrame.h"
12 | 
13 | @protocol SGRenderableDelegate;
14 | 
15 | /**
16 |  *
17 |  */
18 | typedef NS_ENUM(NSUInteger, SGRenderableState) {
19 |     SGRenderableStateNone      = 0,
20 |     SGRenderableStateRendering = 1,
21 |     SGRenderableStatePaused    = 2,
22 |     SGRenderableStateFinished  = 3,
23 |     SGRenderableStateFailed    = 4,
24 | };
25 | 
26 | @protocol SGRenderable <NSObject>
27 | 
28 | /**
29 |  *
30 |  */
31 | @property (nonatomic, weak) id<SGRenderableDelegate> delegate;
32 | 
33 | /**
34 |  *
35 |  */
36 | @property (nonatomic, readonly) SGRenderableState state;
37 | 
38 | /**
39 |  *
40 |  */
41 | - (SGCapacity)capacity;
42 | 
43 | /**
44 |  *
45 |  */
46 | - (BOOL)open;
47 | 
48 | /**
49 |  *
50 |  */
51 | - (BOOL)close;
52 | 
53 | /**
54 |  *
55 |  */
56 | - (BOOL)pause;
57 | 
58 | /**
59 |  *
60 |  */
61 | - (BOOL)resume;
62 | 
63 | /**
64 |  *
65 |  */
66 | - (BOOL)flush;
67 | 
68 | /**
69 |  *
70 |  */
71 | - (BOOL)finish;
72 | 
73 | @end
74 | 
75 | @protocol SGRenderableDelegate <NSObject>
76 | 
77 | /**
78 |  *
79 |  */
80 | - (void)renderable:(id<SGRenderable>)renderable didChangeState:(SGRenderableState)state;
81 | 
82 | /**
83 |  *
84 |  */
85 | - (void)renderable:(id<SGRenderable>)renderable didChangeCapacity:(SGCapacity)capacity;
86 | 
87 | /**
88 |  *
89 |  */
90 | - (__kindof SGFrame *)renderable:(id<SGRenderable>)renderable fetchFrame:(SGTimeReader)timeReader;
91 | 
92 | @end
93 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGRenderer/SGRenderer+Internal.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGRenderer+Internal.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/11/1.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGRenderable.h"
10 | #import "SGAudioDescriptor.h"
11 | #import "SGAudioRenderer.h"
12 | #import "SGVideoRenderer.h"
13 | #import "SGClock+Internal.h"
14 | 
15 | @class SGAudioFormatter;
16 | 
17 | @interface SGAudioRenderer () <SGRenderable>
18 | 
19 | + (instancetype)new NS_UNAVAILABLE;
20 | - (instancetype)init NS_UNAVAILABLE;
21 | 
22 | /**
23 |  *
24 |  */
25 | - (instancetype)initWithClock:(SGClock *)clock;
26 | 
27 | /**
28 |  *
29 |  */
30 | @property (nonatomic) Float64 rate;
31 | 
32 | /**
33 |  *
34 |  */
35 | @property (nonatomic, copy, readonly) SGAudioDescriptor *descriptor;
36 | 
37 | @end
38 | 
39 | @interface SGVideoRenderer () <SGRenderable>
40 | 
41 | + (instancetype)new NS_UNAVAILABLE;
42 | - (instancetype)init NS_UNAVAILABLE;
43 | 
44 | /**
45 |  *
46 |  */
47 | - (instancetype)initWithClock:(SGClock *)clock;
48 | 
49 | /**
50 |  *
51 |  */
52 | @property (nonatomic) Float64 rate;
53 | 
54 | @end
55 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGRenderer/SGVideoRenderer.h:
--------------------------------------------------------------------------------
  1 | //
  2 | //  SGVideoRenderer.h
  3 | //  SGPlayer
  4 | //
  5 | //  Created by Single on 2018/1/22.
  6 | //  Copyright © 2018年 single. All rights reserved.
  7 | //
  8 | 
  9 | #import <Foundation/Foundation.h>
 10 | #import "SGVideoFrame.h"
 11 | #import "SGVRViewport.h"
 12 | #import "SGPLFImage.h"
 13 | #import "SGPLFView.h"
 14 | 
 15 | typedef NS_ENUM(NSUInteger, SGDisplayMode) {
 16 |     SGDisplayModePlane = 0,
 17 |     SGDisplayModeVR    = 1,
 18 |     SGDisplayModeVRBox = 2,
 19 | };
 20 | 
 21 | typedef NS_ENUM(NSUInteger, SGScalingMode) {
 22 |     SGScalingModeResize           = 0,
 23 |     SGScalingModeResizeAspect     = 1,
 24 |     SGScalingModeResizeAspectFill = 2,
 25 | };
 26 | 
 27 | @interface SGVideoRenderer : NSObject
 28 | 
 29 | /*!
 30 |  @method supportedPixelFormats
 31 |  @abstract
 32 |     Indicates all supported pixel formats.
 33 | */
 34 | + (NSArray<NSNumber *> *)supportedPixelFormats;
 35 | 
 36 | /*!
 37 |  @method isSupportedInputFormat:
 38 |  @abstract
 39 |     Indicates whether the input format is supported.
 40 | */
 41 | + (BOOL)isSupportedPixelFormat:(int)format;
 42 | 
 43 | /*!
 44 |  @property view
 45 |  @abstract
 46 |     Indicates the view that displays content.
 47 |  
 48 |  @discussion
 49 |     Main thread only.
 50 |  */
 51 | @property (nonatomic, strong) SGPLFView *view;
 52 | 
 53 | /*!
 54 |  @property viewport
 55 |  @abstract
 56 |     Indicates the current vr viewport.
 57 |  
 58 |  @discussion
 59 |     Main thread only.
 60 |  */
 61 | @property (nonatomic, strong, readonly) SGVRViewport *viewport;
 62 | 
 63 | /*!
 64 |  @property frameOutput
 65 |  @abstract
 66 |     Capture the video frame that will be rendered.
 67 |  
 68 |  @discussion
 69 |     Main thread only.
 70 |  */
 71 | @property (nonatomic, copy) void (^frameOutput)(SGVideoFrame *frame);
 72 | 
 73 | /*!
 74 |  @property preferredFramesPerSecond
 75 |  @abstract
 76 |     Indicates how many frames are rendered in one second.
 77 |     Default is 30.
 78 |  
 79 |  @discussion
 80 |     Main thread only.
 81 |  */
 82 | @property (nonatomic) NSInteger preferredFramesPerSecond;
 83 | 
 84 | /*!
 85 |  @property scalingMode
 86 |  @abstract
 87 |     Indicates current scaling mode.
 88 |  
 89 |  @discussion
 90 |     Main thread only.
 91 |  */
 92 | @property (nonatomic) SGScalingMode scalingMode;
 93 | 
 94 | /*!
 95 |  @property displayMode
 96 |  @abstract
 97 |     Indicates current display mode.
 98 |  
 99 |  @discussion
100 |     Main thread only.
101 |  */
102 | @property (nonatomic) SGDisplayMode displayMode;
103 | 
104 | /*!
105 |  @method currentImage
106 |  @abstract
107 |     Generate a screenshot of the current view.
108 |  
109 |  @discussion
110 |     Main thread only.
111 |  */
112 | - (SGPLFImage *)currentImage;
113 | 
114 | @end
115 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGSession/SGFrameReader.h:
--------------------------------------------------------------------------------
  1 | //
  2 | //  SGFrameReader.h
  3 | //  SGPlayer
  4 | //
  5 | //  Created by Single on 2019/11/12.
  6 | //  Copyright © 2019 single. All rights reserved.
  7 | //
  8 | 
  9 | #import <Foundation/Foundation.h>
 10 | #import "SGDemuxerOptions.h"
 11 | #import "SGDecoderOptions.h"
 12 | #import "SGAsset.h"
 13 | #import "SGFrame.h"
 14 | 
 15 | @protocol SGFrameReaderDelegate;
 16 | 
 17 | @interface SGFrameReader : NSObject
 18 | 
 19 | + (instancetype)new NS_UNAVAILABLE;
 20 | - (instancetype)init NS_UNAVAILABLE;
 21 | 
 22 | /**
 23 |  *
 24 |  */
 25 | - (instancetype)initWithAsset:(SGAsset *)asset;
 26 | 
 27 | /**
 28 |  *
 29 |  */
 30 | @property (nonatomic, copy) SGDemuxerOptions *demuxerOptions;
 31 | 
 32 | /**
 33 |  *
 34 |  */
 35 | @property (nonatomic, copy) SGDecoderOptions *decoderOptions;
 36 | 
 37 | /**
 38 |  *
 39 |  */
 40 | @property (nonatomic, weak) id<SGFrameReaderDelegate> delegate;
 41 | 
 42 | /**
 43 |  *
 44 |  */
 45 | @property (nonatomic, copy, readonly) NSArray<SGTrack *> *tracks;
 46 | 
 47 | /**
 48 |  *
 49 |  */
 50 | @property (nonatomic, copy, readonly) NSArray<SGTrack *> *selectedTracks;
 51 | 
 52 | /**
 53 |  *
 54 |  */
 55 | @property (nonatomic, copy, readonly) NSDictionary *metadata;
 56 | 
 57 | /**
 58 |  *
 59 |  */
 60 | @property (nonatomic, readonly) CMTime duration;
 61 | 
 62 | /**
 63 |  *
 64 |  */
 65 | - (NSError *)open;
 66 | 
 67 | /**
 68 |  *
 69 |  */
 70 | - (NSError *)close;
 71 | 
 72 | /**
 73 |  *
 74 |  */
 75 | - (NSError *)seekable;
 76 | 
 77 | /**
 78 |  *
 79 |  */
 80 | - (NSError *)seekToTime:(CMTime)time;
 81 | 
 82 | /**
 83 |  *
 84 |  */
 85 | - (NSError *)seekToTime:(CMTime)time toleranceBefor:(CMTime)toleranceBefor toleranceAfter:(CMTime)toleranceAfter;
 86 | 
 87 | /**
 88 |  *
 89 |  */
 90 | - (NSError *)selectTracks:(NSArray<SGTrack *> *)tracks;
 91 | 
 92 | /**
 93 |  *
 94 |  */
 95 | - (NSError *)nextFrame:(__kindof SGFrame **)frame;
 96 | 
 97 | @end
 98 | 
 99 | @protocol SGFrameReaderDelegate <NSObject>
100 | 
101 | /**
102 |  *
103 |  */
104 | - (BOOL)frameReaderShouldAbortBlockingFunctions:(SGFrameReader *)frameReader;
105 | 
106 | @end
107 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGSession/SGPlayerItem+Internal.h:
--------------------------------------------------------------------------------
  1 | //
  2 | //  SGPlayerItem+Internal.h
  3 | //  SGPlayer iOS
  4 | //
  5 | //  Created by Single on 2018/10/25.
  6 | //  Copyright © 2018 single. All rights reserved.
  7 | //
  8 | 
  9 | #import "SGPlayerItem.h"
 10 | #import "SGProcessorOptions.h"
 11 | #import "SGAudioDescriptor.h"
 12 | #import "SGDemuxerOptions.h"
 13 | #import "SGDecoderOptions.h"
 14 | #import "SGCapacity.h"
 15 | #import "SGFrame.h"
 16 | 
 17 | @protocol SGPlayerItemDelegate;
 18 | 
 19 | /**
 20 |  *
 21 |  */
 22 | typedef NS_ENUM(NSUInteger, SGPlayerItemState) {
 23 |     SGPlayerItemStateNone     = 0,
 24 |     SGPlayerItemStateOpening  = 1,
 25 |     SGPlayerItemStateOpened   = 2,
 26 |     SGPlayerItemStateReading  = 3,
 27 |     SGPlayerItemStateSeeking  = 4,
 28 |     SGPlayerItemStateFinished = 5,
 29 |     SGPlayerItemStateClosed   = 6,
 30 |     SGPlayerItemStateFailed   = 7,
 31 | };
 32 | 
 33 | @interface SGPlayerItem ()
 34 | 
 35 | /**
 36 |  *
 37 |  */
 38 | @property (nonatomic, copy) SGDemuxerOptions *demuxerOptions;
 39 | 
 40 | /**
 41 |  *
 42 |  */
 43 | @property (nonatomic, copy) SGDecoderOptions *decoderOptions;
 44 | 
 45 | /**
 46 |  *
 47 |  */
 48 | @property (nonatomic, copy) SGProcessorOptions *processorOptions;
 49 | 
 50 | /**
 51 |  *
 52 |  */
 53 | @property (nonatomic, weak) id<SGPlayerItemDelegate> delegate;
 54 | 
 55 | /**
 56 |  *
 57 |  */
 58 | @property (nonatomic, readonly) SGPlayerItemState state;
 59 | 
 60 | /**
 61 |  *
 62 |  */
 63 | - (BOOL)open;
 64 | 
 65 | /**
 66 |  *
 67 |  */
 68 | - (BOOL)start;
 69 | 
 70 | /**
 71 |  *
 72 |  */
 73 | - (BOOL)close;
 74 | 
 75 | /**
 76 |  *
 77 |  */
 78 | - (BOOL)seekable;
 79 | 
 80 | /**
 81 |  *
 82 |  */
 83 | - (BOOL)seekToTime:(CMTime)time;
 84 | 
 85 | /**
 86 |  *
 87 |  */
 88 | - (BOOL)seekToTime:(CMTime)time result:(SGSeekResult)result;
 89 | 
 90 | /**
 91 |  *
 92 |  */
 93 | - (BOOL)seekToTime:(CMTime)time toleranceBefor:(CMTime)toleranceBefor toleranceAfter:(CMTime)toleranceAfter result:(SGSeekResult)result;
 94 | 
 95 | /**
 96 |  *
 97 |  */
 98 | - (SGCapacity)capacityWithType:(SGMediaType)type;
 99 | 
100 | /**
101 |  *
102 |  */
103 | - (BOOL)isAvailable:(SGMediaType)type;
104 | 
105 | /**
106 |  *
107 |  */
108 | - (BOOL)isFinished:(SGMediaType)type;
109 | 
110 | /**
111 |  *
112 |  */
113 | - (__kindof SGFrame *)copyAudioFrame:(SGTimeReader)timeReader;
114 | - (__kindof SGFrame *)copyVideoFrame:(SGTimeReader)timeReader;
115 | 
116 | @end
117 | 
118 | @protocol SGPlayerItemDelegate <NSObject>
119 | 
120 | /**
121 |  *
122 |  */
123 | - (void)playerItem:(SGPlayerItem *)playerItem didChangeState:(SGPlayerItemState)state;
124 | 
125 | /**
126 |  *
127 |  */
128 | - (void)playerItem:(SGPlayerItem *)playerItem didChangeCapacity:(SGCapacity)capacity type:(SGMediaType)type;
129 | 
130 | @end
131 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGSession/SGPlayerItem.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPlayerItem.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/1/16.
 6 | //  Copyright © 2018年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import "SGTrackSelection.h"
11 | #import "SGAsset.h"
12 | #import "SGTrack.h"
13 | 
14 | @interface SGPlayerItem : NSObject
15 | 
16 | + (instancetype)new NS_UNAVAILABLE;
17 | - (instancetype)init NS_UNAVAILABLE;
18 | 
19 | /*!
20 |  @method initWithAsset:
21 |  @abstract
22 |     Initializes an SGPlayerItem with asset.
23 |  */
24 | - (instancetype)initWithAsset:(SGAsset *)asset;
25 | 
26 | /*!
27 |  @property error
28 |  @abstract
29 |     If the loading item failed, this describes the error that caused the failure.
30 |  */
31 | @property (nonatomic, copy, readonly) NSError *error;
32 | 
33 | /*!
34 |  @property tracks
35 |  @abstract
36 |     Provides array of SGPlayerItem tracks.
37 |  */
38 | @property (nonatomic, copy, readonly) NSArray<SGTrack *> *tracks;
39 | 
40 | /*!
41 |  @property duration
42 |  @abstract
43 |     Indicates the metadata of the item.
44 |  */
45 | @property (nonatomic, copy, readonly) NSDictionary *metadata;
46 | 
47 | /*!
48 |  @property duration
49 |  @abstract
50 |     Indicates the duration of the item.
51 |  */
52 | @property (nonatomic, readonly) CMTime duration;
53 | 
54 | /*!
55 |  @property duration
56 |  @abstract
57 |     Indicates the audioSelection of the item.
58 |  */
59 | @property (nonatomic, copy, readonly) SGTrackSelection *audioSelection;
60 | 
61 | /*!
62 |  @method setAudioSelection:action:
63 |  @abstract
64 |     Select specific audio tracks.
65 |  */
66 | - (void)setAudioSelection:(SGTrackSelection *)audioSelection action:(SGTrackSelectionAction)action;
67 | 
68 | /*!
69 |  @property duration
70 |  @abstract
71 |     Indicates the videoSelection of the item.
72 |  */
73 | @property (nonatomic, copy, readonly) SGTrackSelection *videoSelection;
74 | 
75 | /*!
76 |  @method setVideoSelection:action:
77 |  @abstract
78 |     Select specific video tracks.
79 |  */
80 | - (void)setVideoSelection:(SGTrackSelection *)videoSelection action:(SGTrackSelectionAction)action;
81 | 
82 | @end
83 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGVR/SGMotionSensor.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGMotionSensor.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/23.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import <GLKit/GLKit.h>
11 | 
12 | @interface SGMotionSensor : NSObject
13 | 
14 | @property (nonatomic, readonly) BOOL ready;
15 | @property (nonatomic, readonly) GLKMatrix4 matrix;
16 | 
17 | - (void)start;
18 | - (void)stop;
19 | 
20 | @end
21 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGVR/SGVRProjection.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGVRProjection.h
 3 | //  SGPlayer iOS
 4 | //
 5 | //  Created by Single on 2018/8/23.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | #import <GLKit/GLKit.h>
11 | #import "SGVRViewport.h"
12 | 
13 | @interface SGVRProjection : NSObject
14 | 
15 | @property (nonatomic, strong) SGVRViewport * viewport;
16 | 
17 | - (BOOL)ready;
18 | - (BOOL)matrixWithAspect:(Float64)aspect matrix1:(GLKMatrix4 *)matrix1;
19 | - (BOOL)matrixWithAspect:(Float64)aspect matrix1:(GLKMatrix4 *)matrix1 matrix2:(GLKMatrix4 *)matrix2;
20 | 
21 | @end
22 | 
23 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGVR/SGVRViewport.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGVRViewport.h
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/8/27.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Foundation/Foundation.h>
10 | 
11 | @interface SGVRViewport : NSObject
12 | 
13 | @property (nonatomic) Float64 degress;       // Default value is 60.
14 | @property (nonatomic) Float64 x;             // Default value is 0, range is (-360, 360).
15 | @property (nonatomic) Float64 y;             // Default value is 0, range is (-360, 360).
16 | @property (nonatomic) BOOL flipX;            // Default value is NO.
17 | @property (nonatomic) BOOL flipY;            // Default value is NO.
18 | @property (nonatomic) BOOL sensorEnable;     // Default value is YES.
19 | 
20 | @end
21 | 


--------------------------------------------------------------------------------
/SGPlayer/Classes/Core/SGVR/SGVRViewport.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGVRViewport.m
 3 | //  SGPlayer
 4 | //
 5 | //  Created by Single on 2018/8/27.
 6 | //  Copyright © 2018 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGVRViewport.h"
10 | 
11 | @implementation SGVRViewport
12 | 
13 | - (instancetype)init
14 | {
15 |     if (self = [super init]) {
16 |         self.degress = 60;
17 |         self.x = 0;
18 |         self.y = 0;
19 |         self.flipX = NO;
20 |         self.flipY = NO;
21 |         self.sensorEnable = YES;
22 |     }
23 |     return self;
24 | }
25 | 
26 | @end
27 | 


--------------------------------------------------------------------------------
/SGPlayer/Info.plist:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 | <dict>
 5 | 	<key>CFBundleDevelopmentRegion</key>
 6 | 	<string>en</string>
 7 | 	<key>CFBundleDisplayName</key>
 8 | 	<string>SGPlayer</string>
 9 | 	<key>CFBundleExecutable</key>
10 | 	<string>$(EXECUTABLE_NAME)</string>
11 | 	<key>CFBundleIdentifier</key>
12 | 	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13 | 	<key>CFBundleInfoDictionaryVersion</key>
14 | 	<string>6.0</string>
15 | 	<key>CFBundleName</key>
16 | 	<string>$(PRODUCT_NAME)</string>
17 | 	<key>CFBundlePackageType</key>
18 | 	<string>FMWK</string>
19 | 	<key>CFBundleShortVersionString</key>
20 | 	<string>2.0.0</string>
21 | 	<key>CFBundleVersion</key>
22 | 	<string>$(CURRENT_PROJECT_VERSION)</string>
23 | 	<key>NSHumanReadableCopyright</key>
24 | 	<string>Copyright © 2017年 single. All rights reserved.</string>
25 | 	<key>NSPrincipalClass</key>
26 | 	<string></string>
27 | </dict>
28 | </plist>
29 | 


--------------------------------------------------------------------------------
/SGPlayer/module.modulemap:
--------------------------------------------------------------------------------
1 | framework module SGPlayer {
2 |     umbrella header "SGPlayer.h"
3 |     export *
4 |     module * { export * }
5 | }
6 | 


--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/sh
 2 | 
 3 | set -e
 4 | 
 5 | PLATFORM=$1
 6 | ACTION=$2
 7 | 
 8 | FFMPEG_VERSION=7.0.1
 9 | OPENSSL_VERSION=OpenSSL_1_1_1w
10 | 
11 | if [ "$ACTION" = "build" ]; then
12 |     sh scripts/init-openssl.sh $PLATFORM $OPENSSL_VERSION
13 |     sh scripts/init-ffmpeg.sh  $PLATFORM $FFMPEG_VERSION
14 |     sh scripts/compile-openssl.sh $PLATFORM "build"
15 |     sh scripts/compile-ffmpeg.sh $PLATFORM "build"
16 | elif [ "$ACTION" = "clean" ]; then
17 |     sh scripts/compile-openssl.sh $PLATFORM "clean"
18 |     sh scripts/compile-ffmpeg.sh $PLATFORM "clean"
19 | else
20 |     echo "Usage:"
21 |     echo "  sh build.sh iOS build"
22 |     echo "  sh build.sh iOS clean"
23 |     echo " ---"
24 |     echo "  sh build.sh tvOS build"
25 |     echo "  sh build.sh tvOS clean"
26 |     echo " ---"
27 |     echo "  sh build.sh macOS build"
28 |     echo "  sh build.sh macOS clean"
29 |     exit 1
30 | fi
31 | 


--------------------------------------------------------------------------------
/demo/demo-assset/google-help-vr.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-assset/google-help-vr.mp4


--------------------------------------------------------------------------------
/demo/demo-assset/i-see-fire.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-assset/i-see-fire.mp4


--------------------------------------------------------------------------------
/demo/demo-common/SGVideoItem.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGVideoItem.h
 3 | //  demo-common
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <SGPlayer/SGPlayer.h>
10 | 
11 | @interface SGVideoItem : NSObject
12 | 
13 | @property (nonatomic, copy) NSString *name;
14 | @property (nonatomic, copy) SGAsset *asset;
15 | @property (nonatomic) SGDisplayMode displayMode;
16 | 
17 | + (NSArray<SGVideoItem *> *)videoItems;
18 | 
19 | @end
20 | 
21 | 


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <Workspace
3 |    version = "1.0">
4 |    <FileRef
5 |       location = "self:demo-ios.xcodeproj">
6 |    </FileRef>
7 | </Workspace>
8 | 


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/AppDelegate.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  AppDelegate.h
 3 | //  demo-ios
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <UIKit/UIKit.h>
10 | 
11 | @interface AppDelegate : UIResponder <UIApplicationDelegate>
12 | 
13 | @property (strong, nonatomic) UIWindow *window;
14 | 
15 | @end
16 | 
17 | 


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/AppDelegate.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  AppDelegate.m
 3 | //  demo-ios
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "AppDelegate.h"
10 | #import <AVFoundation/AVFoundation.h>
11 | 
12 | @interface AppDelegate ()
13 | 
14 | @end
15 | 
16 | @implementation AppDelegate
17 | 
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
19 | {
20 |     [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
21 |     return YES;
22 | }
23 | 
24 | @end
25 | 


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "size" : "20x20",
 5 |       "idiom" : "iphone",
 6 |       "filename" : "Icon-Notification@2x.png",
 7 |       "scale" : "2x"
 8 |     },
 9 |     {
10 |       "size" : "20x20",
11 |       "idiom" : "iphone",
12 |       "filename" : "Icon-Notification@3x.png",
13 |       "scale" : "3x"
14 |     },
15 |     {
16 |       "size" : "29x29",
17 |       "idiom" : "iphone",
18 |       "filename" : "Icon-Small@2x.png",
19 |       "scale" : "2x"
20 |     },
21 |     {
22 |       "size" : "29x29",
23 |       "idiom" : "iphone",
24 |       "filename" : "Icon-Small@3x.png",
25 |       "scale" : "3x"
26 |     },
27 |     {
28 |       "size" : "40x40",
29 |       "idiom" : "iphone",
30 |       "filename" : "Icon-Small-40@2x.png",
31 |       "scale" : "2x"
32 |     },
33 |     {
34 |       "size" : "40x40",
35 |       "idiom" : "iphone",
36 |       "filename" : "Icon-Small-40@3x.png",
37 |       "scale" : "3x"
38 |     },
39 |     {
40 |       "size" : "60x60",
41 |       "idiom" : "iphone",
42 |       "filename" : "Icon-60@2x.png",
43 |       "scale" : "2x"
44 |     },
45 |     {
46 |       "size" : "60x60",
47 |       "idiom" : "iphone",
48 |       "filename" : "Icon-60@3x.png",
49 |       "scale" : "3x"
50 |     },
51 |     {
52 |       "size" : "1024x1024",
53 |       "idiom" : "ios-marketing",
54 |       "filename" : "logo.png",
55 |       "scale" : "1x"
56 |     }
57 |   ],
58 |   "info" : {
59 |     "version" : 1,
60 |     "author" : "xcode"
61 |   }
62 | }


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Notification@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Notification@2x.png


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Notification@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Notification@3x.png


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@2x.png


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/Icon-Small@3x.png


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-ios/demo-ios/Assets.xcassets/AppIcon.appiconset/logo.png


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 2 | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
 3 |     <dependencies>
 4 |         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
 5 |         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
 6 |     </dependencies>
 7 |     <scenes>
 8 |         <!--View Controller-->
 9 |         <scene sceneID="EHf-IW-A2E">
10 |             <objects>
11 |                 <viewController id="01J-lp-oVM" sceneMemberID="viewController">
12 |                     <layoutGuides>
13 |                         <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
14 |                         <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
15 |                     </layoutGuides>
16 |                     <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
17 |                         <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
18 |                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19 |                         <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
20 |                     </view>
21 |                 </viewController>
22 |                 <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
23 |             </objects>
24 |             <point key="canvasLocation" x="53" y="375"/>
25 |         </scene>
26 |     </scenes>
27 | </document>
28 | 


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/Info.plist:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 | <dict>
 5 | 	<key>CFBundleDevelopmentRegion</key>
 6 | 	<string>en</string>
 7 | 	<key>CFBundleDisplayName</key>
 8 | 	<string>SGPlayer</string>
 9 | 	<key>CFBundleExecutable</key>
10 | 	<string>$(EXECUTABLE_NAME)</string>
11 | 	<key>CFBundleIdentifier</key>
12 | 	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13 | 	<key>CFBundleInfoDictionaryVersion</key>
14 | 	<string>6.0</string>
15 | 	<key>CFBundleName</key>
16 | 	<string>$(PRODUCT_NAME)</string>
17 | 	<key>CFBundlePackageType</key>
18 | 	<string>APPL</string>
19 | 	<key>CFBundleShortVersionString</key>
20 | 	<string>1.0.0</string>
21 | 	<key>CFBundleVersion</key>
22 | 	<string>1</string>
23 | 	<key>LSRequiresIPhoneOS</key>
24 | 	<true/>
25 | 	<key>NSAppTransportSecurity</key>
26 | 	<dict>
27 | 		<key>NSAllowsArbitraryLoads</key>
28 | 		<true/>
29 | 	</dict>
30 | 	<key>UIBackgroundModes</key>
31 | 	<array>
32 | 		<string>audio</string>
33 | 	</array>
34 | 	<key>UILaunchStoryboardName</key>
35 | 	<string>LaunchScreen</string>
36 | 	<key>UIMainStoryboardFile</key>
37 | 	<string>Main</string>
38 | 	<key>UIRequiredDeviceCapabilities</key>
39 | 	<array>
40 | 		<string>armv7</string>
41 | 	</array>
42 | 	<key>UISupportedInterfaceOrientations</key>
43 | 	<array>
44 | 		<string>UIInterfaceOrientationPortrait</string>
45 | 		<string>UIInterfaceOrientationLandscapeLeft</string>
46 | 		<string>UIInterfaceOrientationLandscapeRight</string>
47 | 	</array>
48 | </dict>
49 | </plist>
50 | 


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/SGListViewController.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGListViewController.h
 3 | //  demo-ios
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <UIKit/UIKit.h>
10 | 
11 | @interface SGListViewController : UITableViewController
12 | 
13 | @end
14 | 
15 | 


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/SGListViewController.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGListViewController.m
 3 | //  demo-ios
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGListViewController.h"
10 | #import "SGPlayViewController.h"
11 | #import "SGVideoItem.h"
12 | 
13 | @interface SGListViewController ()
14 | 
15 | @property (nonatomic, strong) NSArray<SGVideoItem *> *videoItems;
16 | 
17 | @end
18 | 
19 | @implementation SGListViewController
20 | 
21 | - (void)viewDidLoad
22 | {
23 |     [super viewDidLoad];
24 |     self.videoItems = [SGVideoItem videoItems];
25 | }
26 | 
27 | - (void)viewWillDisappear:(BOOL)animated
28 | {
29 |     [super viewWillDisappear:animated];
30 |     [self.navigationController setNavigationBarHidden:YES animated:YES];
31 | }
32 | 
33 | - (void)viewWillAppear:(BOOL)animated
34 | {
35 |     [super viewWillAppear:animated];
36 |     [self.navigationController setNavigationBarHidden:NO animated:YES];
37 | }
38 | 
39 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
40 | {
41 |     return 1;
42 | }
43 | 
44 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
45 | {
46 |     return self.videoItems.count;
47 | }
48 | 
49 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
50 | {
51 |     UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
52 |     cell.textLabel.text = self.videoItems[indexPath.row].name;
53 |     return cell;
54 | }
55 | 
56 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
57 | {
58 |     SGPlayViewController *vc = [[SGPlayViewController alloc] init];
59 |     vc.videoItem = self.videoItems[indexPath.row];
60 |     [self.navigationController pushViewController:vc animated:YES];
61 | }
62 | 
63 | @end
64 | 


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/SGPlayViewController.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPlayViewController.h
 3 | //  demo-ios
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <UIKit/UIKit.h>
10 | #import "SGVideoItem.h"
11 | 
12 | @interface SGPlayViewController : UIViewController
13 | 
14 | @property (nonatomic, strong) SGVideoItem *videoItem;
15 | 
16 | @end
17 | 


--------------------------------------------------------------------------------
/demo/demo-ios/demo-ios/main.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  main.m
 3 | //  demo-ios
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <UIKit/UIKit.h>
10 | #import "AppDelegate.h"
11 | 
12 | int main(int argc, char * argv[]) {
13 |     @autoreleasepool {
14 |         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 |     }
16 | }
17 | 


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <Workspace
3 |    version = "1.0">
4 |    <FileRef
5 |       location = "self:demo-macos.xcodeproj">
6 |    </FileRef>
7 | </Workspace>
8 | 


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/AppDelegate.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  AppDelegate.h
 3 | //  demo-macos
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Cocoa/Cocoa.h>
10 | 
11 | @interface AppDelegate : NSObject <NSApplicationDelegate>
12 | 
13 | 
14 | @end
15 | 
16 | 


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/AppDelegate.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  AppDelegate.m
 3 | //  demo-macos
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "AppDelegate.h"
10 | 
11 | @interface AppDelegate ()
12 | 
13 | @end
14 | 
15 | @implementation AppDelegate
16 | 
17 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
18 |     // Insert code here to initialize your application
19 | }
20 | 
21 | 
22 | - (void)applicationWillTerminate:(NSNotification *)aNotification {
23 |     // Insert code here to tear down your application
24 | }
25 | 
26 | 
27 | @end
28 | 


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "size" : "16x16",
 5 |       "idiom" : "mac",
 6 |       "filename" : "icon_16x16.png",
 7 |       "scale" : "1x"
 8 |     },
 9 |     {
10 |       "size" : "16x16",
11 |       "idiom" : "mac",
12 |       "filename" : "icon_16x16@2x.png",
13 |       "scale" : "2x"
14 |     },
15 |     {
16 |       "size" : "32x32",
17 |       "idiom" : "mac",
18 |       "filename" : "icon_32x32.png",
19 |       "scale" : "1x"
20 |     },
21 |     {
22 |       "size" : "32x32",
23 |       "idiom" : "mac",
24 |       "filename" : "icon_32x32@2x.png",
25 |       "scale" : "2x"
26 |     },
27 |     {
28 |       "size" : "128x128",
29 |       "idiom" : "mac",
30 |       "filename" : "icon_128x128.png",
31 |       "scale" : "1x"
32 |     },
33 |     {
34 |       "size" : "128x128",
35 |       "idiom" : "mac",
36 |       "filename" : "icon_128x128@2x.png",
37 |       "scale" : "2x"
38 |     },
39 |     {
40 |       "size" : "256x256",
41 |       "idiom" : "mac",
42 |       "filename" : "icon_256x256.png",
43 |       "scale" : "1x"
44 |     },
45 |     {
46 |       "size" : "256x256",
47 |       "idiom" : "mac",
48 |       "filename" : "icon_256x256@2x.png",
49 |       "scale" : "2x"
50 |     },
51 |     {
52 |       "size" : "512x512",
53 |       "idiom" : "mac",
54 |       "filename" : "icon_512x512.png",
55 |       "scale" : "1x"
56 |     },
57 |     {
58 |       "size" : "512x512",
59 |       "idiom" : "mac",
60 |       "filename" : "icon_512x512@2x.png",
61 |       "scale" : "2x"
62 |     }
63 |   ],
64 |   "info" : {
65 |     "version" : 1,
66 |     "author" : "xcode"
67 |   }
68 | }


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_128x128.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_16x16.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_256x256.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_32x32.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_512x512.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/demo/demo-macos/demo-macos/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/Info.plist:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 | <dict>
 5 | 	<key>CFBundleDevelopmentRegion</key>
 6 | 	<string>en</string>
 7 | 	<key>CFBundleExecutable</key>
 8 | 	<string>$(EXECUTABLE_NAME)</string>
 9 | 	<key>CFBundleIconFile</key>
10 | 	<string></string>
11 | 	<key>CFBundleIdentifier</key>
12 | 	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13 | 	<key>CFBundleInfoDictionaryVersion</key>
14 | 	<string>6.0</string>
15 | 	<key>CFBundleName</key>
16 | 	<string>$(PRODUCT_NAME)</string>
17 | 	<key>CFBundlePackageType</key>
18 | 	<string>APPL</string>
19 | 	<key>CFBundleShortVersionString</key>
20 | 	<string>1.0.0</string>
21 | 	<key>CFBundleVersion</key>
22 | 	<string>1</string>
23 | 	<key>LSApplicationCategoryType</key>
24 | 	<string>public.app-category.video</string>
25 | 	<key>LSMinimumSystemVersion</key>
26 | 	<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
27 | 	<key>NSAppTransportSecurity</key>
28 | 	<dict>
29 | 		<key>NSAllowsArbitraryLoads</key>
30 | 		<true/>
31 | 	</dict>
32 | 	<key>NSHumanReadableCopyright</key>
33 | 	<string>Copyright © 2017年 single. All rights reserved.</string>
34 | 	<key>NSMainStoryboardFile</key>
35 | 	<string>Main</string>
36 | 	<key>NSPrincipalClass</key>
37 | 	<string>NSApplication</string>
38 | </dict>
39 | </plist>
40 | 


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/SGListViewController.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGListViewController.h
 3 | //  demo-macos
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Cocoa/Cocoa.h>
10 | 
11 | @interface SGListViewController : NSViewController
12 | 
13 | 
14 | @end
15 | 
16 | 


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/SGListViewController.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGListViewController.m
 3 | //  demo-macos
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import "SGListViewController.h"
10 | #import "SGPlayViewController.h"
11 | #import "SGVideoItem.h"
12 | 
13 | @interface SGListViewController ()
14 | 
15 | @property (weak) IBOutlet NSPopUpButton *popUpButton;
16 | @property (nonatomic, strong) NSArray<SGVideoItem *> *videoItems;
17 | 
18 | @end
19 | 
20 | @implementation SGListViewController
21 | 
22 | - (void)viewDidLoad
23 | {
24 |     [super viewDidLoad];
25 |     [self.popUpButton removeAllItems];
26 |     self.videoItems = [SGVideoItem videoItems];
27 |     for (NSUInteger i = 0; i < self.videoItems.count; i++) {
28 |         [self.popUpButton addItemWithTitle:self.videoItems[i].name];
29 |     }
30 | }
31 | 
32 | - (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(id)sender
33 | {
34 |     SGPlayViewController *vc = (id)[segue.destinationController contentViewController];
35 |     vc.videoItem = self.videoItems[self.popUpButton.indexOfSelectedItem];
36 |     [vc run];
37 | }
38 | 
39 | @end
40 | 


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/SGPlayViewController.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  SGPlayViewController.h
 3 | //  demo-macos
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Cocoa/Cocoa.h>
10 | #import "SGVideoItem.h"
11 | 
12 | @interface SGPlayViewController : NSViewController
13 | 
14 | @property (nonatomic, strong) SGVideoItem *videoItem;
15 | 
16 | - (void)run;
17 | 
18 | @end
19 | 


--------------------------------------------------------------------------------
/demo/demo-macos/demo-macos/main.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  main.m
 3 | //  demo-macos
 4 | //
 5 | //  Created by Single on 2017/3/15.
 6 | //  Copyright © 2017年 single. All rights reserved.
 7 | //
 8 | 
 9 | #import <Cocoa/Cocoa.h>
10 | 
11 | int main(int argc, const char * argv[]) {
12 |     return NSApplicationMain(argc, argv);
13 | }
14 | 


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <Workspace
3 |    version = "1.0">
4 |    <FileRef
5 |       location = "self:demo-tvos.xcodeproj">
6 |    </FileRef>
7 | </Workspace>
8 | 


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>IDEDidComputeMac32BitWarning</key>
6 | 	<true/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/AppDelegate.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  AppDelegate.h
 3 | //  demo-tvos
 4 | //
 5 | //  Created by Single on 2018/11/5.
 6 | //  Copyright © 2018 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import <UIKit/UIKit.h>
10 | 
11 | @interface AppDelegate : UIResponder <UIApplicationDelegate>
12 | 
13 | @property (strong, nonatomic) UIWindow * window;
14 | 
15 | @end
16 | 
17 | 


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/AppDelegate.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  AppDelegate.m
 3 | //  demo-tvos
 4 | //
 5 | //  Created by Single on 2018/11/5.
 6 | //  Copyright © 2018 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "AppDelegate.h"
10 | 
11 | @interface AppDelegate ()
12 | 
13 | @end
14 | 
15 | @implementation AppDelegate
16 | 
17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
18 | {
19 |     return YES;
20 | }
21 | 
22 | @end
23 | 


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "idiom" : "tv"
 5 |     }
 6 |   ],
 7 |   "info" : {
 8 |     "version" : 1,
 9 |     "author" : "xcode"
10 |   }
11 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 |   "info" : {
3 |     "version" : 1,
4 |     "author" : "xcode"
5 |   }
6 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "layers" : [
 3 |     {
 4 |       "filename" : "Front.imagestacklayer"
 5 |     },
 6 |     {
 7 |       "filename" : "Middle.imagestacklayer"
 8 |     },
 9 |     {
10 |       "filename" : "Back.imagestacklayer"
11 |     }
12 |   ],
13 |   "info" : {
14 |     "version" : 1,
15 |     "author" : "xcode"
16 |   }
17 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "idiom" : "tv"
 5 |     }
 6 |   ],
 7 |   "info" : {
 8 |     "version" : 1,
 9 |     "author" : "xcode"
10 |   }
11 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 |   "info" : {
3 |     "version" : 1,
4 |     "author" : "xcode"
5 |   }
6 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "idiom" : "tv"
 5 |     }
 6 |   ],
 7 |   "info" : {
 8 |     "version" : 1,
 9 |     "author" : "xcode"
10 |   }
11 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 |   "info" : {
3 |     "version" : 1,
4 |     "author" : "xcode"
5 |   }
6 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "idiom" : "tv",
 5 |       "scale" : "1x"
 6 |     },
 7 |     {
 8 |       "idiom" : "tv",
 9 |       "scale" : "2x"
10 |     }
11 |   ],
12 |   "info" : {
13 |     "version" : 1,
14 |     "author" : "xcode"
15 |   }
16 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 |   "info" : {
3 |     "version" : 1,
4 |     "author" : "xcode"
5 |   }
6 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "layers" : [
 3 |     {
 4 |       "filename" : "Front.imagestacklayer"
 5 |     },
 6 |     {
 7 |       "filename" : "Middle.imagestacklayer"
 8 |     },
 9 |     {
10 |       "filename" : "Back.imagestacklayer"
11 |     }
12 |   ],
13 |   "info" : {
14 |     "version" : 1,
15 |     "author" : "xcode"
16 |   }
17 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "idiom" : "tv",
 5 |       "scale" : "1x"
 6 |     },
 7 |     {
 8 |       "idiom" : "tv",
 9 |       "scale" : "2x"
10 |     }
11 |   ],
12 |   "info" : {
13 |     "version" : 1,
14 |     "author" : "xcode"
15 |   }
16 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 |   "info" : {
3 |     "version" : 1,
4 |     "author" : "xcode"
5 |   }
6 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "idiom" : "tv",
 5 |       "scale" : "1x"
 6 |     },
 7 |     {
 8 |       "idiom" : "tv",
 9 |       "scale" : "2x"
10 |     }
11 |   ],
12 |   "info" : {
13 |     "version" : 1,
14 |     "author" : "xcode"
15 |   }
16 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 |   "info" : {
3 |     "version" : 1,
4 |     "author" : "xcode"
5 |   }
6 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "assets" : [
 3 |     {
 4 |       "size" : "1280x768",
 5 |       "idiom" : "tv",
 6 |       "filename" : "App Icon - App Store.imagestack",
 7 |       "role" : "primary-app-icon"
 8 |     },
 9 |     {
10 |       "size" : "400x240",
11 |       "idiom" : "tv",
12 |       "filename" : "App Icon.imagestack",
13 |       "role" : "primary-app-icon"
14 |     },
15 |     {
16 |       "size" : "2320x720",
17 |       "idiom" : "tv",
18 |       "filename" : "Top Shelf Image Wide.imageset",
19 |       "role" : "top-shelf-image-wide"
20 |     },
21 |     {
22 |       "size" : "1920x720",
23 |       "idiom" : "tv",
24 |       "filename" : "Top Shelf Image.imageset",
25 |       "role" : "top-shelf-image"
26 |     }
27 |   ],
28 |   "info" : {
29 |     "version" : 1,
30 |     "author" : "xcode"
31 |   }
32 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "idiom" : "tv",
 5 |       "scale" : "1x"
 6 |     },
 7 |     {
 8 |       "idiom" : "tv",
 9 |       "scale" : "2x"
10 |     },
11 |     {
12 |       "idiom" : "tv-marketing",
13 |       "scale" : "1x"
14 |     },
15 |     {
16 |       "idiom" : "tv-marketing",
17 |       "scale" : "2x"
18 |     }
19 |   ],
20 |   "info" : {
21 |     "version" : 1,
22 |     "author" : "xcode"
23 |   }
24 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "images" : [
 3 |     {
 4 |       "idiom" : "tv",
 5 |       "scale" : "1x"
 6 |     },
 7 |     {
 8 |       "idiom" : "tv",
 9 |       "scale" : "2x"
10 |     },
11 |     {
12 |       "idiom" : "tv-marketing",
13 |       "scale" : "1x"
14 |     },
15 |     {
16 |       "idiom" : "tv-marketing",
17 |       "scale" : "2x"
18 |     }
19 |   ],
20 |   "info" : {
21 |     "version" : 1,
22 |     "author" : "xcode"
23 |   }
24 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 |   "info" : {
3 |     "version" : 1,
4 |     "author" : "xcode"
5 |   }
6 | }


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="13122.16" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
 3 |     <dependencies>
 4 |         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
 5 |         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
 6 |         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
 7 |     </dependencies>
 8 |     <scenes>
 9 |         <!--View Controller-->
10 |         <scene sceneID="tne-QT-ifu">
11 |             <objects>
12 |                 <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
13 |                     <layoutGuides>
14 |                         <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
15 |                         <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
16 |                     </layoutGuides>
17 |                     <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
18 |                         <rect key="frame" x="0.0" y="0.0" width="1920" height="1080"/>
19 |                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
20 |                         <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
21 |                         <viewLayoutGuide key="safeArea" id="wu6-TO-1qx"/>
22 |                     </view>
23 |                 </viewController>
24 |                 <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
25 |             </objects>
26 |         </scene>
27 |     </scenes>
28 | </document>
29 | 


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/Info.plist:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 | <dict>
 5 | 	<key>CFBundleDevelopmentRegion</key>
 6 | 	<string>$(DEVELOPMENT_LANGUAGE)</string>
 7 | 	<key>CFBundleDisplayName</key>
 8 | 	<string>SGPlayer</string>
 9 | 	<key>CFBundleExecutable</key>
10 | 	<string>$(EXECUTABLE_NAME)</string>
11 | 	<key>CFBundleIdentifier</key>
12 | 	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13 | 	<key>CFBundleInfoDictionaryVersion</key>
14 | 	<string>6.0</string>
15 | 	<key>CFBundleName</key>
16 | 	<string>$(PRODUCT_NAME)</string>
17 | 	<key>CFBundlePackageType</key>
18 | 	<string>APPL</string>
19 | 	<key>CFBundleShortVersionString</key>
20 | 	<string>1.0.0</string>
21 | 	<key>CFBundleVersion</key>
22 | 	<string>1</string>
23 | 	<key>LSRequiresIPhoneOS</key>
24 | 	<true/>
25 | 	<key>UIMainStoryboardFile</key>
26 | 	<string>Main</string>
27 | 	<key>UIRequiredDeviceCapabilities</key>
28 | 	<array>
29 | 		<string>arm64</string>
30 | 	</array>
31 | 	<key>UIUserInterfaceStyle</key>
32 | 	<string>Automatic</string>
33 | </dict>
34 | </plist>
35 | 


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/ViewController.h:
--------------------------------------------------------------------------------
 1 | //
 2 | //  ViewController.h
 3 | //  demo-tvos
 4 | //
 5 | //  Created by Single on 2018/11/5.
 6 | //  Copyright © 2018 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import <UIKit/UIKit.h>
10 | 
11 | @interface ViewController : UIViewController
12 | 
13 | @end
14 | 
15 | 


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/ViewController.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  ViewController.m
 3 | //  demo-tvos
 4 | //
 5 | //  Created by Single on 2018/11/5.
 6 | //  Copyright © 2018 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import "ViewController.h"
10 | #import <SGPlayer/SGPlayer.h>
11 | 
12 | @interface ViewController ()
13 | 
14 | @property (nonatomic, assign) BOOL seeking;
15 | @property (nonatomic, strong) SGPlayer *player;
16 | 
17 | @end
18 | 
19 | @implementation ViewController
20 | 
21 | - (instancetype)init
22 | {
23 |     if (self = [super init]) {
24 |         self.player = [[SGPlayer alloc] init];
25 |         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(infoChanged:) name:SGPlayerDidChangeInfosNotification object:self.player];
26 |     }
27 |     return self;
28 | }
29 | 
30 | - (void)dealloc
31 | {
32 |     [[NSNotificationCenter defaultCenter] removeObserver:self];
33 | }
34 | 
35 | - (void)viewDidLoad
36 | {
37 |     [super viewDidLoad];
38 |     
39 |     NSURL *URL = [[NSBundle mainBundle] URLForResource:@"i-see-fire" withExtension:@"mp4"];
40 |     SGAsset *asset = [[SGURLAsset alloc] initWithURL:URL];
41 |     
42 |     self.player.videoRenderer.view = self.view;
43 |     [self.player replaceWithAsset:asset];
44 |     [self.player play];
45 | }
46 | 
47 | #pragma mark - SGPlayer Notifications
48 | 
49 | - (void)infoChanged:(NSNotification *)notification
50 | {
51 |     SGTimeInfo time = [SGPlayer timeInfoFromUserInfo:notification.userInfo];
52 |     SGStateInfo state = [SGPlayer stateInfoFromUserInfo:notification.userInfo];
53 |     SGInfoAction action = [SGPlayer infoActionFromUserInfo:notification.userInfo];
54 |     if (action & SGInfoActionTime) {
55 |         NSLog(@"playback: %f, duration: %f, cached: %f",
56 |               CMTimeGetSeconds(time.playback),
57 |               CMTimeGetSeconds(time.duration),
58 |               CMTimeGetSeconds(time.cached));
59 |     }
60 |     if (action & SGInfoActionState) {
61 |         NSLog(@"player: %d, loading: %d, playback: %d, playing: %d, seeking: %d, finished: %d",
62 |               (int)state.player, (int)state.loading, (int)state.playback,
63 |               (int)(state.playback & SGPlaybackStatePlaying),
64 |               (int)(state.playback & SGPlaybackStateSeeking),
65 |               (int)(state.playback & SGPlaybackStateFinished));
66 |     }
67 | }
68 | 
69 | @end
70 | 


--------------------------------------------------------------------------------
/demo/demo-tvos/demo-tvos/main.m:
--------------------------------------------------------------------------------
 1 | //
 2 | //  main.m
 3 | //  demo-tvos
 4 | //
 5 | //  Created by Single on 2018/11/5.
 6 | //  Copyright © 2018 Single. All rights reserved.
 7 | //
 8 | 
 9 | #import <UIKit/UIKit.h>
10 | #import "AppDelegate.h"
11 | 
12 | int main(int argc, char * argv[]) {
13 |     @autoreleasepool {
14 |         return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 |     }
16 | }
17 | 


--------------------------------------------------------------------------------
/demo/demo.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <Workspace
 3 |    version = "1.0">
 4 |    <FileRef
 5 |       location = "group:demo-ios/demo-ios.xcodeproj">
 6 |    </FileRef>
 7 |    <FileRef
 8 |       location = "group:demo-macos/demo-macos.xcodeproj">
 9 |    </FileRef>
10 |    <FileRef
11 |       location = "group:demo-tvos/demo-tvos.xcodeproj">
12 |    </FileRef>
13 |    <FileRef
14 |       location = "group:../SGPlayer.xcodeproj">
15 |    </FileRef>
16 | </Workspace>
17 | 


--------------------------------------------------------------------------------
/demo/demo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | 	<key>IDEDidComputeMac32BitWarning</key>
6 | 	<true/>
7 | </dict>
8 | </plist>
9 | 


--------------------------------------------------------------------------------
/demo/demo.xcworkspace/xcshareddata/demo.xcscmblueprint:
--------------------------------------------------------------------------------
 1 | {
 2 |   "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "F23AFB690725856BF6A8F7C02C736922AA443A58",
 3 |   "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
 4 | 
 5 |   },
 6 |   "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
 7 |     "F23AFB690725856BF6A8F7C02C736922AA443A58" : 9223372036854775807,
 8 |     "CF9A9AD861EDA5D4368DC40F74298A8979BAE8C8" : 9223372036854775807
 9 |   },
10 |   "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "C8E1264A-1979-46B0-A87B-28155F88CEC8",
11 |   "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12 |     "F23AFB690725856BF6A8F7C02C736922AA443A58" : "SGPlayer\/",
13 |     "CF9A9AD861EDA5D4368DC40F74298A8979BAE8C8" : "SGPlayer\/Vendors\/SGPlatform\/"
14 |   },
15 |   "DVTSourceControlWorkspaceBlueprintNameKey" : "demo",
16 |   "DVTSourceControlWorkspaceBlueprintVersion" : 204,
17 |   "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "demo\/demo.xcworkspace",
18 |   "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19 |     {
20 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:0x010101\/SGPlatform.git",
21 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "CF9A9AD861EDA5D4368DC40F74298A8979BAE8C8"
23 |     },
24 |     {
25 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:0x010101\/SGPlayer.git",
26 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27 |       "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "F23AFB690725856BF6A8F7C02C736922AA443A58"
28 |     }
29 |   ]
30 | }


--------------------------------------------------------------------------------
/documents/banner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/documents/banner.jpg


--------------------------------------------------------------------------------
/documents/flow-chart.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/libobjc/SGPlayer/1d0b304c2f980c73b2c09d8ef417f6734f257f4b/documents/flow-chart.jpg


--------------------------------------------------------------------------------
/scripts/avconfig.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * avconfig.h
 3 |  *
 4 |  * Copyright (c) 2013 Bilibili
 5 |  * Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
 6 |  *
 7 |  * This file is part of ijkPlayer.
 8 |  *
 9 |  * ijkPlayer is free software; you can redistribute it and/or
10 |  * modify it under the terms of the GNU Lesser General Public
11 |  * License as published by the Free Software Foundation; either
12 |  * version 2.1 of the License, or (at your option) any later version.
13 |  *
14 |  * ijkPlayer is distributed in the hope that it will be useful,
15 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 |  * Lesser General Public License for more details.
18 |  *
19 |  * You should have received a copy of the GNU Lesser General Public
20 |  * License along with ijkPlayer; if not, write to the Free Software
21 |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 |  */
23 | 
24 | #if   defined(__aarch64__)
25 | #   include "arm64/avconfig.h"
26 | #elif defined(__x86_64__)
27 | #   include "x86_64/avconfig.h"
28 | #else
29 | #   error Unsupport architecture
30 | #endif
31 | 


--------------------------------------------------------------------------------
/scripts/config.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * config.h
 3 |  *
 4 |  * Copyright (c) 2013 Bilibili
 5 |  * Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
 6 |  *
 7 |  * This file is part of ijkPlayer.
 8 |  *
 9 |  * ijkPlayer is free software; you can redistribute it and/or
10 |  * modify it under the terms of the GNU Lesser General Public
11 |  * License as published by the Free Software Foundation; either
12 |  * version 2.1 of the License, or (at your option) any later version.
13 |  *
14 |  * ijkPlayer is distributed in the hope that it will be useful,
15 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 |  * Lesser General Public License for more details.
18 |  *
19 |  * You should have received a copy of the GNU Lesser General Public
20 |  * License along with ijkPlayer; if not, write to the Free Software
21 |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 |  */
23 | 
24 | #if   defined(__aarch64__)
25 | #   include "arm64/config.h"
26 | #elif defined(__x86_64__)
27 | #   include "x86_64/config.h"
28 | #else
29 | #   error Unsupport architecture
30 | #endif
31 | 


--------------------------------------------------------------------------------
/scripts/ffversion.h:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * ffversion.h
 3 |  *
 4 |  * Copyright (c) 2013 Bilibili
 5 |  * Copyright (c) 2013 Zhang Rui <bbcallen@gmail.com>
 6 |  *
 7 |  * This file is part of ijkPlayer.
 8 |  *
 9 |  * ijkPlayer is free software; you can redistribute it and/or
10 |  * modify it under the terms of the GNU Lesser General Public
11 |  * License as published by the Free Software Foundation; either
12 |  * version 2.1 of the License, or (at your option) any later version.
13 |  *
14 |  * ijkPlayer is distributed in the hope that it will be useful,
15 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 |  * Lesser General Public License for more details.
18 |  *
19 |  * You should have received a copy of the GNU Lesser General Public
20 |  * License along with ijkPlayer; if not, write to the Free Software
21 |  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 |  */
23 | 
24 | #if   defined(__aarch64__)
25 | #   include "arm64/ffversion.h"
26 | #elif defined(__x86_64__)
27 | #   include "x86_64/ffversion.h"
28 | #else
29 | #   error Unsupport architecture
30 | #endif
31 | 


--------------------------------------------------------------------------------
/scripts/init-ffmpeg.sh:
--------------------------------------------------------------------------------
 1 | #! /usr/bin/env bash
 2 | #
 3 | # Copyright (C) 2013-2015 Bilibili
 4 | # Copyright (C) 2013-2015 Zhang Rui <bbcallen@gmail.com>
 5 | #
 6 | # Licensed under the Apache License, Version 2.0 (the "License");
 7 | # you may not use this file except in compliance with the License.
 8 | # You may obtain a copy of the License at
 9 | #
10 | #      http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | 
19 | IJK_FFMPEG_UPSTREAM=https://github.com/libobjc/FFmpeg.git
20 | IJK_FFMPEG_FORK=https://github.com/libobjc/FFmpeg.git
21 | IJK_FFMPEG_COMMIT=$2
22 | IJK_FFMPEG_LOCAL_REPO=build/extra/ffmpeg
23 | 
24 | IJK_GASP_UPSTREAM=https://github.com/libav/gas-preprocessor.git
25 | IJK_GASP_LOCAL_REPO=build/extra/gas-preprocessor
26 | 
27 | set -e
28 | 
29 | FF_ALL_ARCHS=
30 | FF_ALL_ARCHS_IOS="arm64"
31 | FF_ALL_ARCHS_TVOS="arm64"
32 | FF_ALL_ARCHS_MACOS="arm64 x86_64"
33 | 
34 | #FF_ALL_ARCHS_IOS="x86_64 arm64-simulator"
35 | #FF_ALL_ARCHS_TVOS="x86_64 arm64-simulator"
36 | 
37 | FF_PLATFORM=$1
38 | 
39 | function pull_common() {
40 |     echo "== pull gas-preprocessor base =="
41 |     sh scripts/pull-repo-base.sh $IJK_GASP_UPSTREAM $IJK_GASP_LOCAL_REPO
42 | 
43 |     echo "== pull ffmpeg base =="
44 |     sh scripts/pull-repo-base.sh $IJK_FFMPEG_UPSTREAM $IJK_FFMPEG_LOCAL_REPO
45 | }
46 | 
47 | function pull_fork() {
48 |     echo "== pull ffmpeg fork $1 =="
49 |     sh scripts/pull-repo-ref.sh $IJK_FFMPEG_FORK build/source/$FF_PLATFORM/ffmpeg-$1 ${IJK_FFMPEG_LOCAL_REPO}
50 |     cd build/source/$FF_PLATFORM/ffmpeg-$1
51 |     git checkout ${IJK_FFMPEG_COMMIT} -B SGPlayer
52 |     cd -
53 | }
54 | 
55 | function pull_fork_all() {
56 |     for ARCH in $FF_ALL_ARCHS
57 |     do
58 |         pull_fork $ARCH
59 |     done
60 | }
61 | 
62 | #----------
63 | if [ "$FF_PLATFORM" = "iOS" ]; then
64 |     FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS
65 | elif [ "$FF_PLATFORM" = "tvOS" ]; then
66 |     FF_ALL_ARCHS=$FF_ALL_ARCHS_TVOS
67 | elif [ "$FF_PLATFORM" = "macOS" ]; then
68 |     FF_ALL_ARCHS=$FF_ALL_ARCHS_MACOS
69 | else
70 |     echo "You must specific an platform 'iOS, tvOS, macOS'.\n"
71 |     exit 1
72 | fi
73 | 
74 | pull_common
75 | pull_fork_all
76 | 
77 | 


--------------------------------------------------------------------------------
/scripts/init-openssl.sh:
--------------------------------------------------------------------------------
 1 | #! /usr/bin/env bash
 2 | #
 3 | # Copyright (C) 2013-2015 Bilibili
 4 | # Copyright (C) 2013-2015 Zhang Rui <bbcallen@gmail.com>
 5 | #
 6 | # Licensed under the Apache License, Version 2.0 (the "License");
 7 | # you may not use this file except in compliance with the License.
 8 | # You may obtain a copy of the License at
 9 | #
10 | #      http://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | 
19 | IJK_OPENSSL_UPSTREAM=https://github.com/openssl/openssl.git
20 | IJK_OPENSSL_FORK=https://github.com/openssl/openssl.git
21 | IJK_OPENSSL_COMMIT=$2
22 | IJK_OPENSSL_LOCAL_REPO=build/extra/openssl
23 | 
24 | set -e
25 | 
26 | FF_ALL_ARCHS=
27 | FF_ALL_ARCHS_IOS="arm64"
28 | FF_ALL_ARCHS_TVOS="arm64"
29 | FF_ALL_ARCHS_MACOS="arm64 x86_64"
30 | 
31 | #FF_ALL_ARCHS_IOS="x86_64 arm64-simulator"
32 | #FF_ALL_ARCHS_TVOS="x86_64 arm64-simulator"
33 | 
34 | FF_PLATFORM=$1
35 | 
36 | function pull_common() {
37 |     echo "== pull openssl base =="
38 |     sh scripts/pull-repo-base.sh $IJK_OPENSSL_UPSTREAM $IJK_OPENSSL_LOCAL_REPO
39 | }
40 | 
41 | function pull_fork() {
42 |     echo "== pull openssl fork $1 =="
43 |     sh scripts/pull-repo-ref.sh $IJK_OPENSSL_FORK build/source/$FF_PLATFORM/openssl-$1 ${IJK_OPENSSL_LOCAL_REPO}
44 |     cd build/source/$FF_PLATFORM/openssl-$1
45 |     git checkout ${IJK_OPENSSL_COMMIT} -B SGPlayer
46 |     cd -
47 | }
48 | 
49 | function pull_fork_all() {
50 |     for ARCH in $FF_ALL_ARCHS
51 |     do
52 |         pull_fork $ARCH
53 |     done
54 | }
55 | 
56 | #----------
57 | if [ "$FF_PLATFORM" = "iOS" ]; then
58 |     FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS
59 | elif [ "$FF_PLATFORM" = "tvOS" ]; then
60 |     FF_ALL_ARCHS=$FF_ALL_ARCHS_TVOS
61 | elif [ "$FF_PLATFORM" = "macOS" ]; then
62 |     FF_ALL_ARCHS=$FF_ALL_ARCHS_MACOS
63 | else
64 |     echo "You must specific an platform 'iOS, tvOS, macOS'.\n"
65 |     exit 1
66 | fi
67 | 
68 | pull_common
69 | pull_fork_all
70 | 
71 | 


--------------------------------------------------------------------------------
/scripts/pull-repo-base.sh:
--------------------------------------------------------------------------------
 1 | #! /usr/bin/env bash
 2 | 
 3 | REMOTE_REPO=$1
 4 | LOCAL_WORKSPACE=$2
 5 | 
 6 | 
 7 | if [ -z $REMOTE_REPO -o -z $LOCAL_WORKSPACE ]; then
 8 |     echo "invalid call pull-repo.sh '$REMOTE_REPO' '$LOCAL_WORKSPACE'"
 9 | elif [ ! -d $LOCAL_WORKSPACE ]; then
10 |     git clone $REMOTE_REPO $LOCAL_WORKSPACE
11 | else
12 |     cd $LOCAL_WORKSPACE
13 |     git fetch --all --tags
14 |     cd -
15 | fi
16 | 


--------------------------------------------------------------------------------
/scripts/pull-repo-ref.sh:
--------------------------------------------------------------------------------
 1 | #! /usr/bin/env bash
 2 | 
 3 | REMOTE_REPO=$1
 4 | LOCAL_WORKSPACE=$2
 5 | REF_REPO=$3
 6 | 
 7 | if [ -z $1 -o -z $2 -o -z $3 ]; then
 8 |     echo "invalid call pull-repo.sh '$1' '$2' '$3'"
 9 | elif [ ! -d $LOCAL_WORKSPACE ]; then
10 |     git clone --reference $REF_REPO $REMOTE_REPO $LOCAL_WORKSPACE
11 |     cd $LOCAL_WORKSPACE
12 |     git repack -a
13 | else
14 |     cd $LOCAL_WORKSPACE
15 |     git fetch --all --tags
16 |     cd -
17 | fi
18 | 


--------------------------------------------------------------------------------