Compare commits

..

39 Commits

Author SHA1 Message Date
toss156 458759db08 rename h264 encode lib to avoid duplicate symbol error 2016-08-03 23:17:10 +08:00
Justin 408e6e17f5 Update LFLiveKit.podspec
fix issue  #36 关于use_frameworks!的问题
2016-08-03 23:16:38 +08:00
琨君 24e6c4576b change the AVAudioSession Category before start, or it will fail 2016-08-03 23:16:38 +08:00
chenliming 7a901b8b36 update.. 2016-08-03 23:16:37 +08:00
chenliming 6cf68fb370 update 2016-08-03 23:16:37 +08:00
chenliming 96f4415f1d update .. 2016-08-03 23:16:37 +08:00
chenliming f379e59a01 add a icon 2016-08-03 23:16:37 +08:00
chenliming 542d8b88d5 update read 2016-08-03 23:16:37 +08:00
chenliming 9566b8ceb9 update readme 2016-08-03 23:16:37 +08:00
chenliming 1e7296c566 update 2016-08-03 23:16:37 +08:00
chenliming 3f3007531f modify read 2016-08-03 23:16:37 +08:00
chenliming 9381d6c79b modify read 2016-08-03 23:16:37 +08:00
chenliming 605b6bc8e8 update travis 2016-08-03 23:16:37 +08:00
chenliming 9bb160132d update read 2016-08-03 23:16:37 +08:00
chenliming 2ada466726 update version2.0 2016-08-03 23:16:37 +08:00
chenliming 11185e3a4d add iOS encoder 2016-08-03 23:16:37 +08:00
chenliming acefbb6e24 add carthage 2016-08-03 23:15:43 +08:00
chenliming c1787ef6c5 update version 2016-08-03 23:15:42 +08:00
chenliming 77b1776e41 update version 2016-08-03 23:13:39 +08:00
chenliming d460a1105e update... 2016-08-03 23:13:39 +08:00
chenliming c89eece287 update.... 2016-08-03 23:13:39 +08:00
chenliming 6c4fc9a98b update.... 2016-08-03 23:13:39 +08:00
chenliming 33070a53c7 update... 2016-08-03 23:13:39 +08:00
chenliming 2d4360fc1d update。。。 2016-08-03 23:13:39 +08:00
chenliming 272165c84c update.. 2016-08-03 23:13:39 +08:00
chenliming 322b74ae2e update... 2016-08-03 23:13:39 +08:00
chenliming 5ee942d4b0 support carthage 2016-08-03 23:13:38 +08:00
chenliming a7595aa776 modify podspec 2016-08-03 23:13:09 +08:00
chenliming 48098066be update version 2016-08-03 23:13:09 +08:00
chenliming 4cf864b79c update read 2016-08-03 23:13:09 +08:00
chenliming 677680fa3f modify readme 2016-08-03 23:13:09 +08:00
chenliming b72b44fece update podspec 2016-08-03 23:12:09 +08:00
chenliming d749db1ddc update version 2016-08-03 23:12:09 +08:00
chenliming 8c492b130e compile question 2016-08-03 23:10:45 +08:00
chenliming 40bc03438d modify cropSize 2016-08-03 23:09:49 +08:00
chenliming 1d53c484e2 modify black screen bug 2016-08-03 23:09:49 +08:00
chenliming e97513c78f modify bug https://github.com/LaiFengiOS/LFLiveKit/issues/11#issuecomment-235147191 2016-08-03 23:09:49 +08:00
chenliming 65619a256a modify bug https://github.com/LaiFengiOS/LFLiveKit/issues/22 2016-08-03 23:09:48 +08:00
小歪~~~ 9f73c10d29 Merge pull request #23 from toss156/master
rename h264 encode lib to avoid duplicate symbol error
2016-07-26 13:46:35 +08:00
162 changed files with 4792 additions and 6579 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
language: objective-c
osx_image: xcode7
xcode_project: FrameWork/LFLiveKit.xcodeproj
xcode_project: LFLiveKit.xcodeproj
xcode_scheme: LFLiveKit
script:
- xctool -project FrameWork/LFLiveKit.xcodeproj -scheme 'LFLiveKit' -configuration Release -sdk iphonesimulator -arch i386 build
- xctool -project LFLiveKit.xcodeproj -scheme 'LFLiveKit' -configuration Release -sdk iphonesimulator -arch i386 build
File diff suppressed because it is too large Load Diff
@@ -1,26 +0,0 @@
//
// LFLiveKitFramework.h
// LFLiveKitFramework
//
// Created by admin on 2016/10/20.
// Copyright © 2016年 admin. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for LFLiveKitFramework.
FOUNDATION_EXPORT double LFLiveKitFrameworkVersionNumber;
//! Project version string for LFLiveKitFramework.
FOUNDATION_EXPORT const unsigned char LFLiveKitFrameworkVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <LFLiveKitFramework/PublicHeader.h>
#import <LFLiveKit/LFLiveSession.h>
#import <LFLiveKit/LFLiveAudioConfiguration.h>
#import <LFLiveKit/LFLiveVideoConfiguration.h>
#import <LFLiveKit/LFAudioFrame.h>
#import <LFLiveKit/LFFrame.h>
#import <LFLiveKit/LFLiveStreamInfo.h>
#import <LFLiveKit/LFVideoFrame.h>
#import <LFLiveKit/LFLiveDebug.h>
+3 -1
View File
@@ -2,7 +2,7 @@
Pod::Spec.new do |s|
s.name = "LFLiveKit"
s.version = "2.5"
s.version = "2.0"
s.summary = "LaiFeng ios Live. LFLiveKit."
s.homepage = "https://github.com/chenliming777"
s.license = { :type => "MIT", :file => "LICENSE" }
@@ -11,10 +11,12 @@ Pod::Spec.new do |s|
s.ios.deployment_target = "7.0"
s.source = { :git => "https://github.com/LaiFengiOS/LFLiveKit.git", :tag => "#{s.version}" }
s.source_files = "LFLiveKit/**/*.{h,m,mm,cpp,c}"
#s.public_header_files = "LFLiveKit/**/*.h"
s.public_header_files = ['LFLiveKit/*.h', 'LFLiveKit/objects/*.h', 'LFLiveKit/configuration/*.h']
s.frameworks = "VideoToolbox", "AudioToolbox","AVFoundation","Foundation","UIKit"
s.libraries = "c++", "z"
s.requires_arc = true
end
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:LFLiveKit.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "48F687CDE9990BD471D7883061F7E5D4"
BuildableName = "libCocoaAsyncSocket.a"
BlueprintName = "CocoaAsyncSocket"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "6610362E50A6DE8BACCA1F2885CD9157"
BuildableName = "libGPUImage.a"
BlueprintName = "GPUImage"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7C2BDDF89D4243C7BCA44592D146DEED"
BuildableName = "libPods-LFLiveKit.a"
BlueprintName = "Pods-LFLiveKit"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84001F891D0015D10026C63F"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKit"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84001F931D0015D10026C63F"
BuildableName = "LFLiveKitTests.xctest"
BlueprintName = "LFLiveKitTests"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84001F931D0015D10026C63F"
BuildableName = "LFLiveKitTests.xctest"
BlueprintName = "LFLiveKitTests"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84001F891D0015D10026C63F"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKit"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84001F891D0015D10026C63F"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKit"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84001F891D0015D10026C63F"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKit"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>LFLiveKit.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>84001F891D0015D10026C63F</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>84001F931D0015D10026C63F</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>84001F891D0015D10026C63F</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>84001F931D0015D10026C63F</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.5</string>
<string>2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
+2 -9
View File
@@ -2,13 +2,10 @@
// LFLiveKit.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by admin on 16/5/24.
// Copyright © 2016年 admin. All rights reserved.
//
#ifndef LFLiveKit_h
#define LFLiveKit_h
#import "LFLiveSession.h"
#import "LFLiveAudioConfiguration.h"
#import "LFLiveVideoConfiguration.h"
@@ -16,7 +13,3 @@
#import "LFFrame.h"
#import "LFLiveStreamInfo.h"
#import "LFVideoFrame.h"
#import "LFLiveDebug.h"
#endif
+3 -54
View File
@@ -2,9 +2,8 @@
// LFLiveSession.h
// LFLiveKit
//
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -17,28 +16,6 @@
#import "LFLiveDebug.h"
typedef NS_ENUM(NSInteger,LFLiveCaptureType) {
LFLiveCaptureAudio, //< capture only audio
LFLiveCaptureVideo, //< capture onlt video
LFLiveInputAudio, //< only audio (External input audio)
LFLiveInputVideo, //< only video (External input video)
};
///< 用来控制采集类型(可以内部采集也可以外部传入等各种组合,支持单音频与单视频,外部输入适用于录屏,无人机等外设介入)
typedef NS_ENUM(NSInteger,LFLiveCaptureTypeMask) {
LFLiveCaptureMaskAudio = (1 << LFLiveCaptureAudio), ///< only inner capture audio (no video)
LFLiveCaptureMaskVideo = (1 << LFLiveCaptureVideo), ///< only inner capture video (no audio)
LFLiveInputMaskAudio = (1 << LFLiveInputAudio), ///< only outer input audio (no video)
LFLiveInputMaskVideo = (1 << LFLiveInputVideo), ///< only outer input video (no audio)
LFLiveCaptureMaskAll = (LFLiveCaptureMaskAudio | LFLiveCaptureMaskVideo), ///< inner capture audio and video
LFLiveInputMaskAll = (LFLiveInputMaskAudio | LFLiveInputMaskVideo), ///< outer input audio and video(method see pushVideo and pushAudio)
LFLiveCaptureMaskAudioInputVideo = (LFLiveCaptureMaskAudio | LFLiveInputMaskVideo), ///< inner capture audio and outer input video(method pushVideo and setRunning)
LFLiveCaptureMaskVideoInputAudio = (LFLiveCaptureMaskVideo | LFLiveInputMaskAudio), ///< inner capture video and outer input audio(method pushAudio and setRunning)
LFLiveCaptureDefaultMask = LFLiveCaptureMaskAll ///< default is inner capture audio and video
};
@class LFLiveSession;
@protocol LFLiveSessionDelegate <NSObject>
@@ -101,9 +78,6 @@ typedef NS_ENUM(NSInteger,LFLiveCaptureTypeMask) {
/** The status of the stream .*/
@property (nonatomic, assign, readonly) LFLiveState state;
/** The captureType control inner or outer audio and video .*/
@property (nonatomic, assign, readonly) LFLiveCaptureTypeMask captureType;
/** The showDebugInfo control streamInfo and uploadInfo(1s) *.*/
@property (nonatomic, assign) BOOL showDebugInfo;
@@ -113,20 +87,6 @@ typedef NS_ENUM(NSInteger,LFLiveCaptureTypeMask) {
/** The reconnectCount control reconnect count (重连次数) *.*/
@property (nonatomic, assign) NSUInteger reconnectCount;
/*** The warterMarkView control whether the watermark is displayed or not ,if set ni,will remove watermark,otherwise add.
set alpha represent mix.Position relative to outVideoSize.
*.*/
@property (nonatomic, strong, nullable) UIView *warterMarkView;
/* The currentImage is videoCapture shot */
@property (nonatomic, strong,readonly ,nullable) UIImage *currentImage;
/* The saveLocalVideo is save the local video */
@property (nonatomic, assign) BOOL saveLocalVideo;
/* The saveLocalVideoPath is save the local video path */
@property (nonatomic, strong, nullable) NSURL *saveLocalVideoPath;
#pragma mark - Initializer
///=============================================================================
/// @name Initializer
@@ -138,13 +98,7 @@ typedef NS_ENUM(NSInteger,LFLiveCaptureTypeMask) {
The designated initializer. Multiple instances with the same configuration will make the
capture unstable.
*/
- (nullable instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration;
/**
The designated initializer. Multiple instances with the same configuration will make the
capture unstable.
*/
- (nullable instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration captureType:(LFLiveCaptureTypeMask)captureType NS_DESIGNATED_INITIALIZER;
- (nullable instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration NS_DESIGNATED_INITIALIZER;
/** The start stream .*/
- (void)startLive:(nonnull LFLiveStreamInfo *)streamInfo;
@@ -152,11 +106,6 @@ typedef NS_ENUM(NSInteger,LFLiveCaptureTypeMask) {
/** The stop stream .*/
- (void)stopLive;
/** support outer input yuv or rgb video(set LFLiveCaptureTypeMask) .*/
- (void)pushVideo:(nullable CVPixelBufferRef)pixelBuffer;
/** support outer input pcm audio(set LFLiveCaptureTypeMask) .*/
- (void)pushAudio:(nullable NSData*)audioData;
@end
+53 -139
View File
@@ -2,8 +2,8 @@
// LFLiveSession.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFLiveSession.h"
@@ -17,12 +17,15 @@
#import "LFGPUImageBeautyFilter.h"
#import "LFH264VideoEncoder.h"
#define LFLiveReportKey @"com.youku.liveSessionReport"
@interface LFLiveSession ()<LFAudioCaptureDelegate, LFVideoCaptureDelegate, LFAudioEncodingDelegate, LFVideoEncodingDelegate, LFStreamSocketDelegate>
/// 音频配置
{
dispatch_semaphore_t _lock;
}
///音频配置
@property (nonatomic, strong) LFLiveAudioConfiguration *audioConfiguration;
/// 视频配置
///视频配置
@property (nonatomic, strong) LFLiveVideoConfiguration *videoConfiguration;
/// 声音采集
@property (nonatomic, strong) LFAudioCapture *audioCaptureSource;
@@ -35,21 +38,17 @@
/// 上传
@property (nonatomic, strong) id<LFStreamSocket> socket;
#pragma mark -- 内部标识
/// 调试信息
/// 上报
@property (nonatomic, copy) dispatch_block_t reportBlock;
/// debugInfo
@property (nonatomic, strong) LFLiveDebug *debugInfo;
/// 流信息
/// streamInfo
@property (nonatomic, strong) LFLiveStreamInfo *streamInfo;
/// 是否开始上传
/// uploading
@property (nonatomic, assign) BOOL uploading;
/// 当前状态
/// state
@property (nonatomic, assign, readwrite) LFLiveState state;
/// 当前直播type
@property (nonatomic, assign, readwrite) LFLiveCaptureTypeMask captureType;
/// 时间戳锁
@property (nonatomic, strong) dispatch_semaphore_t lock;
@end
@@ -59,39 +58,30 @@
@interface LFLiveSession ()
/// 上传相对时间戳
@property (nonatomic, assign) uint64_t relativeTimestamps;
/// 音视频是否对齐
@property (nonatomic, assign) BOOL AVAlignment;
/// 当前是否采集到了音频
@property (nonatomic, assign) BOOL hasCaptureAudio;
/// 当前是否采集到了关键帧
@property (nonatomic, assign) BOOL hasKeyFrameVideo;
@property (nonatomic, assign) uint64_t timestamp;
@property (nonatomic, assign) BOOL isFirstFrame;
@property (nonatomic, assign) uint64_t currentTimestamp;
@end
@implementation LFLiveSession
#pragma mark -- LifeCycle
- (instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration {
return [self initWithAudioConfiguration:audioConfiguration videoConfiguration:videoConfiguration captureType:LFLiveCaptureDefaultMask];
}
- (nullable instancetype)initWithAudioConfiguration:(nullable LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(nullable LFLiveVideoConfiguration *)videoConfiguration captureType:(LFLiveCaptureTypeMask)captureType{
if((captureType & LFLiveCaptureMaskAudio || captureType & LFLiveInputMaskAudio) && !audioConfiguration) @throw [NSException exceptionWithName:@"LFLiveSession init error" reason:@"audioConfiguration is nil " userInfo:nil];
if((captureType & LFLiveCaptureMaskVideo || captureType & LFLiveInputMaskVideo) && !videoConfiguration) @throw [NSException exceptionWithName:@"LFLiveSession init error" reason:@"videoConfiguration is nil " userInfo:nil];
- (instancetype)initWithAudioConfiguration:(LFLiveAudioConfiguration *)audioConfiguration videoConfiguration:(LFLiveVideoConfiguration *)videoConfiguration {
if (!audioConfiguration || !videoConfiguration) @throw [NSException exceptionWithName:@"LFLiveSession init error" reason:@"audioConfiguration or videoConfiguration is nil " userInfo:nil];
if (self = [super init]) {
_audioConfiguration = audioConfiguration;
_videoConfiguration = videoConfiguration;
_lock = dispatch_semaphore_create(1);
_adaptiveBitrate = NO;
_captureType = captureType;
_isFirstFrame = YES;
}
return self;
}
- (void)dealloc {
_videoCaptureSource.running = NO;
_audioCaptureSource.running = NO;
self.audioCaptureSource.running = NO;
self.videoCaptureSource.running = NO;
}
#pragma mark -- CustomMethod
@@ -109,61 +99,30 @@
self.socket = nil;
}
- (void)pushVideo:(nullable CVPixelBufferRef)pixelBuffer{
if(self.captureType & LFLiveInputMaskVideo){
if (self.uploading) [self.videoEncoder encodeVideoData:pixelBuffer timeStamp:NOW];
}
}
- (void)pushAudio:(nullable NSData*)audioData{
if(self.captureType & LFLiveInputMaskAudio){
if (self.uploading) [self.audioEncoder encodeAudioData:audioData timeStamp:NOW];
}
}
#pragma mark -- PrivateMethod
- (void)pushSendBuffer:(LFFrame*)frame{
if(self.relativeTimestamps == 0){
self.relativeTimestamps = frame.timestamp;
}
frame.timestamp = [self uploadTimestamp:frame.timestamp];
[self.socket sendFrame:frame];
}
#pragma mark -- CaptureDelegate
- (void)captureOutput:(nullable LFAudioCapture *)capture audioData:(nullable NSData*)audioData {
if (self.uploading) [self.audioEncoder encodeAudioData:audioData timeStamp:NOW];
- (void)captureOutput:(nullable LFAudioCapture *)capture audioBuffer:(AudioBufferList)inBufferList {
if (self.uploading) [self.audioEncoder encodeAudioData:inBufferList timeStamp:self.currentTimestamp];
}
- (void)captureOutput:(nullable LFVideoCapture *)capture pixelBuffer:(nullable CVPixelBufferRef)pixelBuffer {
if (self.uploading) [self.videoEncoder encodeVideoData:pixelBuffer timeStamp:NOW];
- (void)captureOutput:(nullable LFVideoCapture *)capture pixelBuffer:(nullable CVImageBufferRef)pixelBuffer {
if (self.uploading) [self.videoEncoder encodeVideoData:pixelBuffer timeStamp:self.currentTimestamp];
}
#pragma mark -- EncoderDelegate
- (void)audioEncoder:(nullable id<LFAudioEncoding>)encoder audioFrame:(nullable LFAudioFrame *)frame {
//<上传 时间戳对齐
if (self.uploading){
self.hasCaptureAudio = YES;
if(self.AVAlignment) [self pushSendBuffer:frame];
}
if (self.uploading) [self.socket sendFrame:frame]; //<上传
}
- (void)videoEncoder:(nullable id<LFVideoEncoding>)encoder videoFrame:(nullable LFVideoFrame *)frame {
//<上传 时间戳对齐
if (self.uploading){
if(frame.isKeyFrame && self.hasCaptureAudio) self.hasKeyFrameVideo = YES;
if(self.AVAlignment) [self pushSendBuffer:frame];
}
if (self.uploading) [self.socket sendFrame:frame]; //<上传
}
#pragma mark -- LFStreamTcpSocketDelegate
- (void)socketStatus:(nullable id<LFStreamSocket>)socket status:(LFLiveState)status {
if (status == LFLiveStart) {
if (!self.uploading) {
self.AVAlignment = NO;
self.hasCaptureAudio = NO;
self.hasKeyFrameVideo = NO;
self.relativeTimestamps = 0;
self.timestamp = 0;
self.isFirstFrame = YES;
self.uploading = YES;
}
} else if(status == LFLiveStop || status == LFLiveError){
@@ -197,18 +156,18 @@
}
- (void)socketBufferStatus:(nullable id<LFStreamSocket>)socket status:(LFLiveBuffferState)status {
if((self.captureType & LFLiveCaptureMaskVideo || self.captureType & LFLiveInputMaskVideo) && self.adaptiveBitrate){
NSUInteger videoBitRate = [self.videoEncoder videoBitRate];
if (self.adaptiveBitrate) {
NSUInteger videoBitRate = [_videoEncoder videoBitRate];
if (status == LFLiveBuffferDecline) {
if (videoBitRate < _videoConfiguration.videoMaxBitRate) {
videoBitRate = videoBitRate + 50 * 1000;
[self.videoEncoder setVideoBitRate:videoBitRate];
[_videoEncoder setVideoBitRate:videoBitRate];
NSLog(@"Increase bitrate %@", @(videoBitRate));
}
} else {
if (videoBitRate > self.videoConfiguration.videoMinBitRate) {
if (videoBitRate > _videoConfiguration.videoMinBitRate) {
videoBitRate = videoBitRate - 100 * 1000;
[self.videoEncoder setVideoBitRate:videoBitRate];
[_videoEncoder setVideoBitRate:videoBitRate];
NSLog(@"Decline bitrate %@", @(videoBitRate));
}
}
@@ -251,23 +210,6 @@
[self didChangeValueForKey:@"beautyFace"];
}
- (BOOL)saveLocalVideo{
return self.videoCaptureSource.saveLocalVideo;
}
- (void)setSaveLocalVideo:(BOOL)saveLocalVideo{
[self.videoCaptureSource setSaveLocalVideo:saveLocalVideo];
}
- (NSURL*)saveLocalVideoPath{
return self.videoCaptureSource.saveLocalVideoPath;
}
- (void)setSaveLocalVideoPath:(NSURL*)saveLocalVideoPath{
[self.videoCaptureSource setSaveLocalVideoPath:saveLocalVideoPath];
}
- (BOOL)beautyFace {
return self.videoCaptureSource.beautyFace;
}
@@ -332,34 +274,18 @@
return self.audioCaptureSource.muted;
}
- (void)setWarterMarkView:(UIView *)warterMarkView{
[self.videoCaptureSource setWarterMarkView:warterMarkView];
}
- (nullable UIView*)warterMarkView{
return self.videoCaptureSource.warterMarkView;
}
- (nullable UIImage *)currentImage{
return self.videoCaptureSource.currentImage;
}
- (LFAudioCapture *)audioCaptureSource {
if (!_audioCaptureSource) {
if(self.captureType & LFLiveCaptureMaskAudio){
_audioCaptureSource = [[LFAudioCapture alloc] initWithAudioConfiguration:_audioConfiguration];
_audioCaptureSource.delegate = self;
}
_audioCaptureSource = [[LFAudioCapture alloc] initWithAudioConfiguration:_audioConfiguration];
_audioCaptureSource.delegate = self;
}
return _audioCaptureSource;
}
- (LFVideoCapture *)videoCaptureSource {
if (!_videoCaptureSource) {
if(self.captureType & LFLiveCaptureMaskVideo){
_videoCaptureSource = [[LFVideoCapture alloc] initWithVideoConfiguration:_videoConfiguration];
_videoCaptureSource.delegate = self;
}
_videoCaptureSource = [[LFVideoCapture alloc] initWithVideoConfiguration:_videoConfiguration];
_videoCaptureSource.delegate = self;
}
return _videoCaptureSource;
}
@@ -374,9 +300,9 @@
- (id<LFVideoEncoding>)videoEncoder {
if (!_videoEncoder) {
if([[UIDevice currentDevice].systemVersion floatValue] < 8.0){
if (SYSTEM_VERSION_LESS_THAN(@"8.0")) {
_videoEncoder = [[LFH264VideoEncoder alloc] initWithVideoStreamConfiguration:_videoConfiguration];
}else{
} else {
_videoEncoder = [[LFHardwareVideoEncoder alloc] initWithVideoStreamConfiguration:_videoConfiguration];
}
[_videoEncoder setDelegate:self];
@@ -386,7 +312,7 @@
- (id<LFStreamSocket>)socket {
if (!_socket) {
_socket = [[LFStreamRTMPSocket alloc] initWithStream:self.streamInfo reconnectInterval:self.reconnectInterval reconnectCount:self.reconnectCount];
_socket = [[LFStreamRTMPSocket alloc] initWithStream:self.streamInfo videoSize:self.videoConfiguration.videoSize reconnectInterval:self.reconnectInterval reconnectCount:self.reconnectCount];
[_socket setDelegate:self];
}
return _socket;
@@ -399,30 +325,18 @@
return _streamInfo;
}
- (dispatch_semaphore_t)lock{
if(!_lock){
_lock = dispatch_semaphore_create(1);
}
return _lock;
}
- (uint64_t)uploadTimestamp:(uint64_t)captureTimestamp{
dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER);
- (uint64_t)currentTimestamp {
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
uint64_t currentts = 0;
currentts = captureTimestamp - self.relativeTimestamps;
dispatch_semaphore_signal(self.lock);
if (_isFirstFrame) {
_timestamp = NOW;
_isFirstFrame = NO;
currentts = 0;
} else {
currentts = NOW - _timestamp;
}
dispatch_semaphore_signal(_lock);
return currentts;
}
- (BOOL)AVAlignment{
if((self.captureType & LFLiveCaptureMaskAudio || self.captureType & LFLiveInputMaskAudio) &&
(self.captureType & LFLiveCaptureMaskVideo || self.captureType & LFLiveInputMaskVideo)
){
if(self.hasCaptureAudio && self.hasKeyFrameVideo) return YES;
else return NO;
}else{
return YES;
}
}
@end
+6 -7
View File
@@ -86,10 +86,10 @@
GLubyte *imageData = (GLubyte *) calloc(1, (int)layerPixelSize.width * (int)layerPixelSize.height * 4);
CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();
CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();
CGContextRef imageContext = CGBitmapContextCreate(imageData, (int)layerPixelSize.width, (int)layerPixelSize.height, 8, (int)layerPixelSize.width * 4, genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
// CGContextRotateCTM(imageContext, M_PI_2);
CGContextTranslateCTM(imageContext, 0.0f, layerPixelSize.height);
// CGContextRotateCTM(imageContext, M_PI_2);
CGContextTranslateCTM(imageContext, 0.0f, layerPixelSize.height);
CGContextScaleCTM(imageContext, layer.contentsScale, -layer.contentsScale);
// CGContextSetBlendMode(imageContext, kCGBlendModeCopy); // From Technical Q&A QA1708: http://developer.apple.com/library/ios/#qa/qa1708/_index.html
@@ -100,13 +100,13 @@
// TODO: This may not work
outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:layerPixelSize textureOptions:self.outputTextureOptions onlyTexture:YES];
[outputFramebuffer disableReferenceCounting]; // Add this line, because GPUImageTwoInputFilter.m frametime updatedMovieFrameOppositeStillImage is YES, but the secondbuffer not lock
glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]);
// no need to use self.outputTextureOptions here, we always need these texture options
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)layerPixelSize.width, (int)layerPixelSize.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
free(imageData);
for (id<GPUImageInput> currentTarget in targets)
{
if (currentTarget != self.targetToIgnoreForUpdates)
@@ -115,10 +115,9 @@
NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];
[currentTarget setInputSize:layerPixelSize atIndex:textureIndexOfTarget];
[currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget]; // add this line, because the outputFramebuffer is update above
[currentTarget newFrameReadyAtTime:frameTime atIndex:textureIndexOfTarget];
}
}
}
}
@end
+3 -3
View File
@@ -2,8 +2,8 @@
// LFAudioCapture.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/1.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -17,7 +17,7 @@ extern NSString *_Nullable const LFAudioComponentFailedToCreateNotification;
@class LFAudioCapture;
/** LFAudioCapture callback audioData */
@protocol LFAudioCaptureDelegate <NSObject>
- (void)captureOutput:(nullable LFAudioCapture *)capture audioData:(nullable NSData*)audioData;
- (void)captureOutput:(nullable LFAudioCapture *)capture audioBuffer:(AudioBufferList)inBufferList;
@end
+55 -43
View File
@@ -2,8 +2,8 @@
// LFAudioCapture.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/1.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFAudioCapture.h"
@@ -18,52 +18,61 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
@property (nonatomic, assign) AudioComponent component;
@property (nonatomic, strong) dispatch_queue_t taskQueue;
@property (nonatomic, assign) BOOL isRunning;
@property (nonatomic, strong,nullable) LFLiveAudioConfiguration *configuration;
@property (nonatomic, strong) LFLiveAudioConfiguration *configuration;
@end
@implementation LFAudioCapture
#pragma mark -- LiftCycle
- (instancetype)initWithAudioConfiguration:(LFLiveAudioConfiguration *)configuration{
if(self = [super init]){
- (instancetype)initWithAudioConfiguration:(LFLiveAudioConfiguration *)configuration {
if (self = [super init]) {
_configuration = configuration;
self.isRunning = NO;
self.taskQueue = dispatch_queue_create("com.youku.Laifeng.audioCapture.Queue", NULL);
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setActive:YES error:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleRouteChange:)
name:AVAudioSessionRouteChangeNotification
object:session];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleInterruption:)
name:AVAudioSessionInterruptionNotification
object:session];
NSError *error = nil;
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(handleRouteChange:)
name: AVAudioSessionRouteChangeNotification
object: session];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(handleInterruption:)
name: AVAudioSessionInterruptionNotification
object: session];
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
if (![session setActive:YES error:&error]) {
[self handleAudioComponentCreationFailure];
}
AudioComponentDescription acd;
acd.componentType = kAudioUnitType_Output;
//acd.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
acd.componentSubType = kAudioUnitSubType_RemoteIO;
acd.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
acd.componentManufacturer = kAudioUnitManufacturer_Apple;
acd.componentFlags = 0;
acd.componentFlagsMask = 0;
self.component = AudioComponentFindNext(NULL, &acd);
OSStatus status = noErr;
status = AudioComponentInstanceNew(self.component, &_componetInstance);
if (noErr != status) {
[self handleAudioComponentCreationFailure];
}
UInt32 flagOne = 1;
AudioUnitSetProperty(self.componetInstance, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &flagOne, sizeof(flagOne));
AudioStreamBasicDescription desc = {0};
desc.mSampleRate = _configuration.audioSampleRate;
desc.mFormatID = kAudioFormatLinearPCM;
@@ -73,23 +82,22 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
desc.mBitsPerChannel = 16;
desc.mBytesPerFrame = desc.mBitsPerChannel / 8 * desc.mChannelsPerFrame;
desc.mBytesPerPacket = desc.mBytesPerFrame * desc.mFramesPerPacket;
AURenderCallbackStruct cb;
cb.inputProcRefCon = (__bridge void *)(self);
cb.inputProc = handleInputBuffer;
AudioUnitSetProperty(self.componetInstance, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &desc, sizeof(desc));
AudioUnitSetProperty(self.componetInstance, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 1, &cb, sizeof(cb));
status = AudioUnitInitialize(self.componetInstance);
if (noErr != status) {
[self handleAudioComponentCreationFailure];
}
[session setPreferredSampleRate:_configuration.audioSampleRate error:nil];
[session setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers error:nil];
[session setActive:YES withOptions:kAudioSessionSetActiveFlag_NotifyOthersOnDeactivation error:nil];
[session setActive:YES error:nil];
}
return self;
@@ -98,9 +106,8 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
dispatch_async(self.taskQueue, ^{
dispatch_sync(self.taskQueue, ^{
if (self.componetInstance) {
self.isRunning = NO;
AudioOutputUnitStop(self.componetInstance);
AudioComponentInstanceDispose(self.componetInstance);
self.componetInstance = nil;
@@ -117,15 +124,11 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
dispatch_async(self.taskQueue, ^{
self.isRunning = YES;
NSLog(@"MicrophoneSource: startRunning");
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
AudioOutputUnitStart(self.componetInstance);
});
} else {
dispatch_async(self.taskQueue, ^{
self.isRunning = NO;
NSLog(@"MicrophoneSource: stopRunning");
AudioOutputUnitStop(self.componetInstance);
});
self.isRunning = NO;
}
}
@@ -182,7 +185,7 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
reason = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] integerValue];
if (reason == AVAudioSessionInterruptionTypeBegan) {
if (self.isRunning) {
dispatch_async(self.taskQueue, ^{
dispatch_sync(self.taskQueue, ^{
NSLog(@"MicrophoneSource: stopRunning");
AudioOutputUnitStop(self.componetInstance);
});
@@ -196,7 +199,7 @@ NSString *const LFAudioComponentFailedToCreateNotification = @"LFAudioComponentF
case AVAudioSessionInterruptionOptionShouldResume:
if (self.isRunning) {
dispatch_async(self.taskQueue, ^{
NSLog(@"MicrophoneSource: startRunning");
NSLog(@"MicrophoneSource: stopRunning");
AudioOutputUnitStart(self.componetInstance);
});
}
@@ -239,6 +242,15 @@ static OSStatus handleInputBuffer(void *inRefCon,
inNumberFrames,
&buffers);
if (!source.isRunning) {
dispatch_sync(source.taskQueue, ^{
NSLog(@"MicrophoneSource: stopRunning");
AudioOutputUnitStop(source.componetInstance);
});
return status;
}
if (source.muted) {
for (int i = 0; i < buffers.mNumberBuffers; i++) {
AudioBuffer ab = buffers.mBuffers[i];
@@ -247,8 +259,8 @@ static OSStatus handleInputBuffer(void *inRefCon,
}
if (!status) {
if (source.delegate && [source.delegate respondsToSelector:@selector(captureOutput:audioData:)]) {
[source.delegate captureOutput:source audioData:[NSData dataWithBytes:buffers.mBuffers[0].mData length:buffers.mBuffers[0].mDataByteSize]];
if (source.delegate && [source.delegate respondsToSelector:@selector(captureOutput:audioBuffer:)]) {
[source.delegate captureOutput:source audioBuffer:buffers];
}
}
return status;
+3 -15
View File
@@ -2,8 +2,8 @@
// LFVideoCapture.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/1.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -13,7 +13,7 @@
@class LFVideoCapture;
/** LFVideoCapture callback videoData */
@protocol LFVideoCaptureDelegate <NSObject>
- (void)captureOutput:(nullable LFVideoCapture *)capture pixelBuffer:(nullable CVPixelBufferRef)pixelBuffer;
- (void)captureOutput:(nullable LFVideoCapture *)capture pixelBuffer:(nullable CVImageBufferRef)pixelBuffer;
@end
@interface LFVideoCapture : NSObject
@@ -56,18 +56,6 @@
/** The videoFrameRate control videoCapture output data count */
@property (nonatomic, assign) NSInteger videoFrameRate;
/*** The warterMarkView control whether the watermark is displayed or not ,if set ni,will remove watermark,otherwise add *.*/
@property (nonatomic, strong, nullable) UIView *warterMarkView;
/* The currentImage is videoCapture shot */
@property (nonatomic, strong, nullable) UIImage *currentImage;
/* The saveLocalVideo is save the local video */
@property (nonatomic, assign) BOOL saveLocalVideo;
/* The saveLocalVideoPath is save the local video path */
@property (nonatomic, strong, nullable) NSURL *saveLocalVideoPath;
#pragma mark - Initializer
///=============================================================================
/// @name Initializer
+160 -211
View File
@@ -2,37 +2,24 @@
// LFVideoCapture.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/1.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFVideoCapture.h"
#import "GPUImage.h"
#import "LFGPUImageBeautyFilter.h"
#import "LFGPUImageEmptyFilter.h"
#if __has_include(<GPUImage/GPUImage.h>)
#import <GPUImage/GPUImage.h>
#elif __has_include("GPUImage/GPUImage.h")
#import "GPUImage/GPUImage.h"
#else
#import "GPUImage.h"
#endif
@interface LFVideoCapture ()
@property (nonatomic, strong) GPUImageVideoCamera *videoCamera;
@property (nonatomic, strong) LFGPUImageBeautyFilter *beautyFilter;
@property (nonatomic, strong) GPUImageOutput<GPUImageInput> *filter;
@property (nonatomic, strong) GPUImageCropFilter *cropfilter;
@property (nonatomic, strong) GPUImageOutput<GPUImageInput> *output;
@property (nonatomic, strong) GPUImageView *gpuImageView;
@property (nonatomic, strong) LFLiveVideoConfiguration *configuration;
@property (nonatomic, strong) GPUImageAlphaBlendFilter *blendFilter;
@property (nonatomic, strong) GPUImageUIElement *uiElementInput;
@property (nonatomic, strong) UIView *waterMarkContentView;
@property (nonatomic, strong) GPUImageMovieWriter *movieWriter;
@property(nonatomic, strong) GPUImageVideoCamera *videoCamera;
@property(nonatomic, weak) LFGPUImageBeautyFilter *beautyFilter;
@property(nonatomic, strong) GPUImageOutput<GPUImageInput> *filter;
@property(nonatomic, strong) GPUImageOutput<GPUImageInput> *output;
@property(nonatomic, strong) GPUImageCropFilter *cropfilter;
@property(nonatomic, strong) GPUImageView *gpuImageView;
@property(nonatomic, strong) LFLiveVideoConfiguration *configuration;
@end
@@ -46,16 +33,45 @@
- (instancetype)initWithVideoConfiguration:(LFLiveVideoConfiguration *)configuration {
if (self = [super init]) {
_configuration = configuration;
if([self pixelBufferImageSize].width < configuration.videoSize.width || [self pixelBufferImageSize].height < configuration.videoSize.height){
@throw [NSException exceptionWithName:@"当前videoSize大小出错" reason:@"LFLiveVideoConfiguration videoSize error" userInfo:nil];
return nil;
}
_videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:_configuration.avSessionPreset cameraPosition:AVCaptureDevicePositionFront];
UIInterfaceOrientation statusBar = [[UIApplication sharedApplication] statusBarOrientation];
if (configuration.landscape) {
if (statusBar != UIInterfaceOrientationLandscapeLeft && statusBar != UIInterfaceOrientationLandscapeRight) {
@throw [NSException exceptionWithName:@"当前设置方向出错" reason:@"LFLiveVideoConfiguration landscape error" userInfo:nil];
_videoCamera.outputImageOrientation = UIInterfaceOrientationLandscapeLeft;
} else {
_videoCamera.outputImageOrientation = statusBar;
}
} else {
if (statusBar != UIInterfaceOrientationPortrait && statusBar != UIInterfaceOrientationPortraitUpsideDown) {
@throw [NSException exceptionWithName:@"当前设置方向出错" reason:@"LFLiveVideoConfiguration landscape error" userInfo:nil];
_videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
} else {
_videoCamera.outputImageOrientation = statusBar;
}
}
_videoCamera.horizontallyMirrorFrontFacingCamera = NO;
_videoCamera.horizontallyMirrorRearFacingCamera = NO;
_videoCamera.frameRate = (int32_t)_configuration.videoFrameRate;
_gpuImageView = [[GPUImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
[_gpuImageView setFillMode:kGPUImageFillModePreserveAspectRatioAndFill];
[_gpuImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[_gpuImageView setInputRotation:kGPUImageFlipHorizonal atIndex:0];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterBackground:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterForeground:) name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarChanged:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
self.beautyFace = YES;
self.beautyLevel = 0.5;
self.brightLevel = 0.5;
self.zoomScale = 1.0;
self.mirror = YES;
}
return self;
}
@@ -64,83 +80,67 @@
[UIApplication sharedApplication].idleTimerDisabled = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_videoCamera stopCameraCapture];
if(_gpuImageView){
[_gpuImageView removeFromSuperview];
_gpuImageView = nil;
}
}
#pragma mark -- Setter Getter
- (GPUImageVideoCamera *)videoCamera{
if(!_videoCamera){
_videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:_configuration.avSessionPreset cameraPosition:AVCaptureDevicePositionFront];
_videoCamera.outputImageOrientation = _configuration.outputImageOrientation;
_videoCamera.horizontallyMirrorFrontFacingCamera = NO;
_videoCamera.horizontallyMirrorRearFacingCamera = NO;
_videoCamera.frameRate = (int32_t)_configuration.videoFrameRate;
}
return _videoCamera;
}
- (void)setRunning:(BOOL)running {
if (_running == running) return;
_running = running;
if (!_running) {
[UIApplication sharedApplication].idleTimerDisabled = NO;
[self.videoCamera stopCameraCapture];
if(self.saveLocalVideo) [self.movieWriter finishRecording];
[_videoCamera stopCameraCapture];
} else {
[UIApplication sharedApplication].idleTimerDisabled = YES;
[self reloadFilter];
[self.videoCamera startCameraCapture];
if(self.saveLocalVideo) [self.movieWriter startRecording];
[_videoCamera startCameraCapture];
}
}
- (void)setPreView:(UIView *)preView {
if (self.gpuImageView.superview) [self.gpuImageView removeFromSuperview];
[preView insertSubview:self.gpuImageView atIndex:0];
self.gpuImageView.frame = CGRectMake(0, 0, preView.frame.size.width, preView.frame.size.height);
if (_gpuImageView.superview) [_gpuImageView removeFromSuperview];
[preView insertSubview:_gpuImageView atIndex:0];
}
- (UIView *)preView {
return self.gpuImageView.superview;
return _gpuImageView.superview;
}
- (void)setCaptureDevicePosition:(AVCaptureDevicePosition)captureDevicePosition {
[self.videoCamera rotateCamera];
self.videoCamera.frameRate = (int32_t)_configuration.videoFrameRate;
[self reloadMirror];
[_videoCamera rotateCamera];
_videoCamera.frameRate = (int32_t)_configuration.videoFrameRate;
if (captureDevicePosition == AVCaptureDevicePositionFront) {
[_gpuImageView setInputRotation:kGPUImageFlipHorizonal atIndex:0];
} else {
[_gpuImageView setInputRotation:kGPUImageNoRotation atIndex:0];
}
}
- (AVCaptureDevicePosition)captureDevicePosition {
return [self.videoCamera cameraPosition];
return [_videoCamera cameraPosition];
}
- (void)setVideoFrameRate:(NSInteger)videoFrameRate {
if (videoFrameRate <= 0) return;
if (videoFrameRate == self.videoCamera.frameRate) return;
self.videoCamera.frameRate = (uint32_t)videoFrameRate;
if (videoFrameRate == _videoCamera.frameRate) return;
_videoCamera.frameRate = (uint32_t)videoFrameRate;
}
- (NSInteger)videoFrameRate {
return self.videoCamera.frameRate;
return _videoCamera.frameRate;
}
- (void)setTorch:(BOOL)torch {
BOOL ret;
if (!self.videoCamera.captureSession) return;
AVCaptureSession *session = (AVCaptureSession *)self.videoCamera.captureSession;
if (!_videoCamera.captureSession) return;
AVCaptureSession *session = (AVCaptureSession *)_videoCamera.captureSession;
[session beginConfiguration];
if (self.videoCamera.inputCamera) {
if (self.videoCamera.inputCamera.torchAvailable) {
if (_videoCamera.inputCamera) {
if (_videoCamera.inputCamera.torchAvailable) {
NSError *err = nil;
if ([self.videoCamera.inputCamera lockForConfiguration:&err]) {
[self.videoCamera.inputCamera setTorchMode:(torch ? AVCaptureTorchModeOn : AVCaptureTorchModeOff) ];
[self.videoCamera.inputCamera unlockForConfiguration];
ret = (self.videoCamera.inputCamera.torchMode == AVCaptureTorchModeOn);
if ([_videoCamera.inputCamera lockForConfiguration:&err]) {
[_videoCamera.inputCamera setTorchMode:(torch ? AVCaptureTorchModeOn : AVCaptureTorchModeOff) ];
[_videoCamera.inputCamera unlockForConfiguration];
ret = (_videoCamera.inputCamera.torchMode == AVCaptureTorchModeOn);
} else {
NSLog(@"Error while locking device for torch: %@", err);
ret = false;
@@ -154,22 +154,22 @@
}
- (BOOL)torch {
return self.videoCamera.inputCamera.torchMode;
return _videoCamera.inputCamera.torchMode;
}
- (void)setMirror:(BOOL)mirror {
_mirror = mirror;
_videoCamera.horizontallyMirrorFrontFacingCamera = mirror;
_videoCamera.horizontallyMirrorRearFacingCamera = mirror;
}
- (void)setBeautyFace:(BOOL)beautyFace{
_beautyFace = beautyFace;
[self reloadFilter];
- (BOOL)mirror {
return _videoCamera.horizontallyMirrorFrontFacingCamera;
}
- (void)setBeautyLevel:(CGFloat)beautyLevel {
_beautyLevel = beautyLevel;
if (self.beautyFilter) {
[self.beautyFilter setBeautyLevel:_beautyLevel];
if (_beautyFilter) {
[_beautyFilter setBeautyLevel:_beautyLevel];
}
}
@@ -179,8 +179,8 @@
- (void)setBrightLevel:(CGFloat)brightLevel {
_brightLevel = brightLevel;
if (self.beautyFilter) {
[self.beautyFilter setBrightLevel:brightLevel];
if (_beautyFilter) {
[_beautyFilter setBrightLevel:brightLevel];
}
}
@@ -203,67 +203,54 @@
return _zoomScale;
}
- (void)setWarterMarkView:(UIView *)warterMarkView{
if(_warterMarkView && _warterMarkView.superview){
[_warterMarkView removeFromSuperview];
_warterMarkView = nil;
}
_warterMarkView = warterMarkView;
self.blendFilter.mix = warterMarkView.alpha;
[self.waterMarkContentView addSubview:_warterMarkView];
[self reloadFilter];
}
- (void)setBeautyFace:(BOOL)beautyFace {
- (GPUImageUIElement *)uiElementInput{
if(!_uiElementInput){
_uiElementInput = [[GPUImageUIElement alloc] initWithView:self.waterMarkContentView];
}
return _uiElementInput;
}
_beautyFace = beautyFace;
[_filter removeAllTargets];
[_cropfilter removeAllTargets];
[_videoCamera removeAllTargets];
- (GPUImageAlphaBlendFilter *)blendFilter{
if(!_blendFilter){
_blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
_blendFilter.mix = 1.0;
[_blendFilter disableSecondFrameCheck];
if (_beautyFace) {
_output = [[LFGPUImageEmptyFilter alloc] init];
_filter = [[LFGPUImageBeautyFilter alloc] init];
_beautyFilter = _filter;
__weak typeof(self) _self = self;
[_output setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {
[_self processVideo:output];
}];
} else {
_filter = [[LFGPUImageEmptyFilter alloc] init];
_beautyFilter = nil;
__weak typeof(self) _self = self;
[_filter setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {
[_self processVideo:output];
}];
}
return _blendFilter;
}
- (UIView *)waterMarkContentView{
if(!_waterMarkContentView){
_waterMarkContentView = [UIView new];
_waterMarkContentView.frame = CGRectMake(0, 0, self.configuration.videoSize.width, self.configuration.videoSize.height);
_waterMarkContentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
CGSize imageSize = [self pixelBufferImageSize];
CGFloat cropLeft = (imageSize.width - self.configuration.videoSize.width)/2.0/imageSize.width;
CGFloat cropTop = (imageSize.height - self.configuration.videoSize.height)/2.0/imageSize.height;
if(cropLeft == 0 && cropTop == 0){
[_videoCamera addTarget:_filter];
}else{
_cropfilter = [[GPUImageCropFilter alloc] initWithCropRegion:CGRectMake(cropLeft, cropTop, 1 - cropLeft*2, 1 - cropTop*2)];
[_videoCamera addTarget:_cropfilter];
[_cropfilter addTarget:_filter];
}
if (_beautyFace) {
[_filter addTarget:_output];
[_output addTarget:_gpuImageView];
} else {
[_filter addTarget:_gpuImageView];
}
return _waterMarkContentView;
}
- (GPUImageView *)gpuImageView{
if(!_gpuImageView){
_gpuImageView = [[GPUImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
[_gpuImageView setFillMode:kGPUImageFillModePreserveAspectRatioAndFill];
[_gpuImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
if (_videoCamera.cameraPosition == AVCaptureDevicePositionFront) {
[_gpuImageView setInputRotation:kGPUImageFlipHorizonal atIndex:0];
} else {
[_gpuImageView setInputRotation:kGPUImageNoRotation atIndex:0];
}
return _gpuImageView;
}
-(UIImage *)currentImage{
if(_filter){
[_filter useNextFrameForImageCapture];
return _filter.imageFromCurrentFramebuffer;
}
return nil;
}
- (GPUImageMovieWriter*)movieWriter{
if(!_movieWriter){
_movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:self.saveLocalVideoPath size:self.configuration.videoSize];
_movieWriter.encodingLiveVideo = YES;
_movieWriter.shouldPassthroughAudio = YES;
self.videoCamera.audioEncodingTarget = self.movieWriter;
}
return _movieWriter;
}
#pragma mark -- Custom Method
@@ -272,76 +259,11 @@
@autoreleasepool {
GPUImageFramebuffer *imageFramebuffer = output.framebufferForOutput;
CVPixelBufferRef pixelBuffer = [imageFramebuffer pixelBuffer];
if (pixelBuffer && _self.delegate && [_self.delegate respondsToSelector:@selector(captureOutput:pixelBuffer:)]) {
[_self.delegate captureOutput:_self pixelBuffer:pixelBuffer];
}
}
}
- (void)reloadFilter{
[self.filter removeAllTargets];
[self.blendFilter removeAllTargets];
[self.uiElementInput removeAllTargets];
[self.videoCamera removeAllTargets];
[self.output removeAllTargets];
[self.cropfilter removeAllTargets];
if (self.beautyFace) {
self.output = [[LFGPUImageEmptyFilter alloc] init];
self.filter = [[LFGPUImageBeautyFilter alloc] init];
self.beautyFilter = (LFGPUImageBeautyFilter*)self.filter;
} else {
self.output = [[LFGPUImageEmptyFilter alloc] init];
self.filter = [[LFGPUImageEmptyFilter alloc] init];
self.beautyFilter = nil;
}
///< 调节镜像
[self reloadMirror];
//< 480*640 比例为4:3 强制转换为16:9
if([self.configuration.avSessionPreset isEqualToString:AVCaptureSessionPreset640x480]){
CGRect cropRect = self.configuration.landscape ? CGRectMake(0, 0.125, 1, 0.75) : CGRectMake(0.125, 0, 0.75, 1);
self.cropfilter = [[GPUImageCropFilter alloc] initWithCropRegion:cropRect];
[self.videoCamera addTarget:self.cropfilter];
[self.cropfilter addTarget:self.filter];
}else{
[self.videoCamera addTarget:self.filter];
}
//< 添加水印
if(self.warterMarkView){
[self.filter addTarget:self.blendFilter];
[self.uiElementInput addTarget:self.blendFilter];
[self.blendFilter addTarget:self.gpuImageView];
if(self.saveLocalVideo) [self.blendFilter addTarget:self.movieWriter];
[self.filter addTarget:self.output];
[self.uiElementInput update];
}else{
[self.filter addTarget:self.output];
[self.output addTarget:self.gpuImageView];
if(self.saveLocalVideo) [self.output addTarget:self.movieWriter];
}
[self.filter forceProcessingAtSize:self.configuration.videoSize];
[self.output forceProcessingAtSize:self.configuration.videoSize];
[self.blendFilter forceProcessingAtSize:self.configuration.videoSize];
[self.uiElementInput forceProcessingAtSize:self.configuration.videoSize];
//< 输出数据
__weak typeof(self) _self = self;
[self.output setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {
[_self processVideo:output];
}];
}
- (void)reloadMirror{
if(self.mirror && self.captureDevicePosition == AVCaptureDevicePositionFront){
self.videoCamera.horizontallyMirrorFrontFacingCamera = YES;
}else{
self.videoCamera.horizontallyMirrorFrontFacingCamera = NO;
}
}
@@ -349,36 +271,63 @@
- (void)willEnterBackground:(NSNotification *)notification {
[UIApplication sharedApplication].idleTimerDisabled = NO;
[self.videoCamera pauseCameraCapture];
[_videoCamera pauseCameraCapture];
runSynchronouslyOnVideoProcessingQueue(^{
glFinish();
});
}
- (void)willEnterForeground:(NSNotification *)notification {
[self.videoCamera resumeCameraCapture];
[_videoCamera resumeCameraCapture];
[UIApplication sharedApplication].idleTimerDisabled = YES;
}
- (void)statusBarChanged:(NSNotification *)notification {
NSLog(@"UIApplicationWillChangeStatusBarOrientationNotification. UserInfo: %@", notification.userInfo);
UIInterfaceOrientation statusBar = [[UIApplication sharedApplication] statusBarOrientation];
if(self.configuration.autorotate){
if (self.configuration.landscape) {
if (statusBar == UIInterfaceOrientationLandscapeLeft) {
self.videoCamera.outputImageOrientation = UIInterfaceOrientationLandscapeRight;
} else if (statusBar == UIInterfaceOrientationLandscapeRight) {
self.videoCamera.outputImageOrientation = UIInterfaceOrientationLandscapeLeft;
}
} else {
if (statusBar == UIInterfaceOrientationPortrait) {
self.videoCamera.outputImageOrientation = UIInterfaceOrientationPortraitUpsideDown;
} else if (statusBar == UIInterfaceOrientationPortraitUpsideDown) {
self.videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
}
if (_configuration.landscape) {
if (statusBar == UIInterfaceOrientationLandscapeLeft) {
self.videoCamera.outputImageOrientation = UIInterfaceOrientationLandscapeRight;
} else if (statusBar == UIInterfaceOrientationLandscapeRight) {
self.videoCamera.outputImageOrientation = UIInterfaceOrientationLandscapeLeft;
}
} else {
if (statusBar == UIInterfaceOrientationPortrait) {
self.videoCamera.outputImageOrientation = UIInterfaceOrientationPortraitUpsideDown;
} else if (statusBar == UIInterfaceOrientationPortraitUpsideDown) {
self.videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
}
}
}
#pragma mark --
- (CGSize)pixelBufferImageSize{
CGSize videoSize = CGSizeZero;
switch (self.configuration.sessionPreset) {
case LFCaptureSessionPreset360x640:
{
videoSize = CGSizeMake(480, 640);
}
break;
case LFCaptureSessionPreset540x960:
{
videoSize = CGSizeMake(540, 960);
}
break;
case LFCaptureSessionPreset720x1280:
{
videoSize = CGSizeMake(720, 1280);
}
break;
default:
break;
}
if(self.configuration.landscape){
return CGSizeMake(videoSize.height, videoSize.width);
}
return videoSize;
}
@end
+2 -4
View File
@@ -11,13 +11,10 @@
#import <AVFoundation/AVAssetWriterInput.h>
#import <AVFoundation/AVMediaFormat.h>
#import <AVFoundation/AVVideoSettings.h>
#import <sys/stat.h>
#import "sys/stat.h"
#import "LFVideoEncoder.h"
#import "LFMP4Atom.h"
typedef int (^encoder_handler_t)(NSArray *data, CMTimeValue ptsValue);
typedef int (^param_handler_t)(NSData *params);
@@ -29,6 +26,7 @@ typedef int (^param_handler_t)(NSData *params);
- (void)encodeWithBlock:(encoder_handler_t)block onParams:(param_handler_t)paramsHandler;
- (void)encodeFrame:(CMSampleBufferRef)sampleBuffer;
- (void)encodePixelBuffer:(CVPixelBufferRef)pixelBuffer pts:(CMTime)pts;
- (NSData *)getConfigData;
- (void)shutdown;
+8 -8
View File
@@ -91,12 +91,12 @@ static unsigned int to_host(unsigned char *p){
_width = width;
_bitrate = bitrate;
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:@"params.mp4"];
_headerWriter = [LFVideoEncoder encoderForPath:path Height:height andWidth:width bitrate:(int)self.bitrate];
_headerWriter = [LFVideoEncoder encoderForPath:path Height:height andWidth:width bitrate:self.bitrate];
_times = [NSMutableArray arrayWithCapacity:10];
// swap between 3 filenames
_currentFile = 1;
_writer = [LFVideoEncoder encoderForPath:[self makeFilename] Height:height andWidth:width bitrate:(int)self.bitrate];
_writer = [LFVideoEncoder encoderForPath:[self makeFilename] Height:height andWidth:width bitrate:self.bitrate];
[self addObserver:self forKeyPath:NSStringFromSelector(@selector(bitrate)) options:0 context:AVEncoderContext];
}
@@ -123,7 +123,7 @@ static unsigned int to_host(unsigned char *p){
NSFileHandle *file = [NSFileHandle fileHandleForReadingAtPath:path];
struct stat s;
fstat([file fileDescriptor], &s);
LFMP4Atom *movie = [LFMP4Atom atomAt:0 size:(int)s.st_size type:(OSType)('file') inFile:file];
LFMP4Atom *movie = [LFMP4Atom atomAt:0 size:s.st_size type:(OSType)('file') inFile:file];
LFMP4Atom *moov = [movie childOfType:(OSType)('moov') startAt:0];
LFMP4Atom *trak = nil;
if (moov != nil) {
@@ -164,7 +164,7 @@ static unsigned int to_host(unsigned char *p){
LFMP4Atom *esd = [avc1 childOfType:(OSType)('avcC') startAt:78];
if (esd != nil) {
// this is the avcC record that we are looking for
_avcC = [esd readAt:0 size:(int)esd.length];
_avcC = [esd readAt:0 size:esd.length];
if (_avcC != nil) {
// extract size of length field
unsigned char *p = (unsigned char *)[_avcC bytes];
@@ -236,7 +236,7 @@ static unsigned int to_host(unsigned char *p){
_currentFile = 1;
}
//NSLog(@"Swap to file %d", _currentFile);
_writer = [LFVideoEncoder encoderForPath:[self makeFilename] Height:_height andWidth:_width bitrate:(int)self.bitrate];
_writer = [LFVideoEncoder encoderForPath:[self makeFilename] Height:_height andWidth:_width bitrate:self.bitrate];
// to do this seamlessly requires a few steps in the right order
// first, suspend the read source
@@ -319,7 +319,7 @@ static unsigned int to_host(unsigned char *p){
// called whenever there is more data to read in the main encoder output file.
struct stat s;
fstat([_inputFile fileDescriptor], &s);
int cReady = (int)(s.st_size - [_inputFile offsetInFile]);
int cReady = s.st_size - [_inputFile offsetInFile];
// locate the mdat atom if needed
while (!_foundMDAT && (cReady > 8)) {
@@ -385,7 +385,7 @@ static unsigned int to_host(unsigned char *p){
int naltype = pNal[0] & 0x1f;
if (_pendingNALU) {
LFNALUnit nal(pNal, (int)[nalu length]);
LFNALUnit nal(pNal, [nalu length]);
// we have existing data —is this the same frame?
// typically there are a couple of NALUs per frame in iOS encoding.
@@ -397,7 +397,7 @@ static unsigned int to_host(unsigned char *p){
bNew = YES;
} else if ((naltype >= 1) && (naltype <= 5)) {
nal.Skip(8);
int first_mb = (int)nal.GetUE();
int first_mb = nal.GetUE();
if (first_mb == 0) {
bNew = YES;
}
+1 -1
View File
@@ -73,7 +73,7 @@ static unsigned int to_host(unsigned char *p){
int64_t offset = _nextChild + cHeader;
_nextChild += len;
len -= cHeader;
return [LFMP4Atom atomAt:offset+_offset size:(int)len type:fourcc inFile:_file];
return [LFMP4Atom atomAt:offset+_offset size:len type:fourcc inFile:_file];
}
return nil;
}
+11 -11
View File
@@ -222,7 +222,7 @@ ScalingList(int size, LFNALUnit *pnalu){
long delta = pnalu->GetSE();
nextScale = (lastScale + delta + 256) %256;
}
int scaling_list_j = (nextScale == 0) ? (int)lastScale : (int)nextScale;
int scaling_list_j = (nextScale == 0) ? lastScale : nextScale;
lastScale = scaling_list_j;
}
}
@@ -237,21 +237,21 @@ LFSeqParamSet::Parse(LFNALUnit *pnalu){
// to get through to the ones we want
pnalu->ResetBitstream();
pnalu->Skip(8); // type
m_Profile =(int) pnalu->GetWord(8);
m_Profile = pnalu->GetWord(8);
m_Compatibility = (BYTE)pnalu->GetWord(8);
m_Level = (int)pnalu->GetWord(8);
m_Level = pnalu->GetWord(8);
/*int seq_param_id =*/ pnalu->GetUE();
if ((m_Profile == 100) || (m_Profile == 110) || (m_Profile == 122) || (m_Profile == 144)) {
int chroma_fmt = (int)pnalu->GetUE();
int chroma_fmt = pnalu->GetUE();
if (chroma_fmt == 3) {
pnalu->Skip(1);
}
/* int bit_depth_luma_minus8 = */ pnalu->GetUE();
/* int bit_depth_chroma_minus8 = */ pnalu->GetUE();
pnalu->Skip(1);
int seq_scaling_matrix_present = (int)pnalu->GetBit();
int seq_scaling_matrix_present = pnalu->GetBit();
if (seq_scaling_matrix_present) {
for (int i = 0; i < 8; i++) {
if (pnalu->GetBit()) {
@@ -265,16 +265,16 @@ LFSeqParamSet::Parse(LFNALUnit *pnalu){
}
}
int log2_frame_minus4 = (int)pnalu->GetUE();
int log2_frame_minus4 = pnalu->GetUE();
m_FrameBits = log2_frame_minus4 + 4;
int POCtype = (int)pnalu->GetUE();
int POCtype = pnalu->GetUE();
if (POCtype == 0) {
/*int log2_poc_minus4 =*/ pnalu->GetUE();
} else if (POCtype == 1) {
pnalu->Skip(1); // delta always zero
/*int nsp_offset =*/ pnalu->GetSE();
/*int nsp_top_to_bottom = */ pnalu->GetSE();
int num_ref_in_cycle = (int)pnalu->GetUE();
int num_ref_in_cycle = pnalu->GetUE();
for (int i = 0; i < num_ref_in_cycle; i++) {
/*int sf_offset =*/ pnalu->GetSE();
}
@@ -286,8 +286,8 @@ LFSeqParamSet::Parse(LFNALUnit *pnalu){
/*int num_ref_frames =*/ pnalu->GetUE();
/*int gaps_allowed =*/ pnalu->GetBit();
int mbs_width = (int)pnalu->GetUE();
int mbs_height = (int)pnalu->GetUE();
int mbs_width = pnalu->GetUE();
int mbs_height = pnalu->GetUE();
m_cx = (mbs_width+1) * 16;
m_cy = (mbs_height+1) * 16;
@@ -359,7 +359,7 @@ LFSliceHeader::Parse(LFNALUnit *pnalu){
pnalu->GetUE(); // slice type
pnalu->GetUE(); // pic param set id
m_framenum = (int)pnalu->GetWord(m_nBitsFrame);
m_framenum = pnalu->GetWord(m_nBitsFrame);
return true;
}
+4 -4
View File
@@ -7,10 +7,10 @@
//
#import <Foundation/Foundation.h>
#import <AVFoundation/AVAssetWriter.h>
#import <AVFoundation/AVAssetWriterInput.h>
#import <AVFoundation/AVMediaFormat.h>
#import <AVFoundation/AVVideoSettings.h>
#import "AVFoundation/AVAssetWriter.h"
#import "AVFoundation/AVAssetWriterInput.h"
#import "AVFoundation/AVMediaFormat.h"
#import "AVFoundation/AVVideoSettings.h"
@interface LFVideoEncoder : NSObject
+15
View File
@@ -0,0 +1,15 @@
# GDCL Source Code License
Last updated: 20th February 2013
**License Agreement for Source Code provided by GDCL**
This software is supplied to you by Geraint Davies Consulting Ltd ('GDCL') in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this software.
In consideration of your agreement to abide by the following terms, and subject to these terms, GDCL grants you a personal, non-exclusive license, to use, reproduce, modify and redistribute the software, with or without modifications, in source and/or binary forms; provided that if you redistribute the software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the software, and that in all cases attribution of GDCL as the original author of the source code shall be included in all such resulting software products or distributions.
Neither the name, trademarks, service marks or logos of Geraint Davies or GDCL may be used to endorse or promote products derived from the software without specific prior written permission from GDCL. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by GDCL herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the software may be incorporated.
The software is provided by GDCL on an "AS IS" basis. GDCL MAKE NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL GDCL BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF GDCL HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+3 -5
View File
@@ -2,8 +2,8 @@
// LFAudioEncoding.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -11,8 +11,6 @@
#import "LFAudioFrame.h"
#import "LFLiveAudioConfiguration.h"
@protocol LFAudioEncoding;
/// 编码器编码后回调
@protocol LFAudioEncodingDelegate <NSObject>
@@ -23,7 +21,7 @@
/// 编码器抽象的接口
@protocol LFAudioEncoding <NSObject>
@required
- (void)encodeAudioData:(nullable NSData*)audioData timeStamp:(uint64_t)timeStamp;
- (void)encodeAudioData:(AudioBufferList)inBufferList timeStamp:(uint64_t)timeStamp;
- (void)stopEncoder;
@optional
- (nullable instancetype)initWithAudioStreamConfiguration:(nullable LFLiveAudioConfiguration *)configuration;
+2 -3
View File
@@ -2,10 +2,9 @@
// LFH264VideoEncoder
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by feng on 7/5/16.
// Copyright (c) 2014 zhanqi.tv. All rights reserved.
//
#import "LFVideoEncoding.h"
@interface LFH264VideoEncoder : NSObject <LFVideoEncoding> {
+21 -14
View File
@@ -2,8 +2,8 @@
// LFH264VideoEncoder
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by feng on 7/5/16.
// Copyright (c) 2014 zhanqi.tv. All rights reserved.
//
#import <CoreMedia/CoreMedia.h>
@@ -60,7 +60,7 @@
[self initForFilePath];
#endif
_encoder = [LFAVEncoder encoderForHeight:(int)_configuration.videoSize.height andWidth:(int)_configuration.videoSize.width bitrate:(int)_configuration.videoBitRate];
_encoder = [LFAVEncoder encoderForHeight:_configuration.videoSize.height andWidth:_configuration.videoSize.width bitrate:_configuration.videoBitRate];
[_encoder encodeWithBlock:^int(NSArray* dataArray, CMTimeValue ptsValue) {
[self incomingVideoFrames:dataArray ptsValue:ptsValue];
return 0;
@@ -85,7 +85,7 @@
if (!config) {
return;
}
LFavcCHeader avcC((const BYTE*)[config bytes], (int)[config length]);
LFavcCHeader avcC((const BYTE*)[config bytes], [config length]);
LFSeqParamSet seqParams;
seqParams.Parse(avcC.sps());
@@ -107,8 +107,6 @@
[_videoSPSandPPS appendData:ppsData];
}
- (void)setVideoBitRate:(NSInteger)videoBitRate{
_currentVideoBitRate = videoBitRate;
_encoder.bitrate = _currentVideoBitRate;
@@ -164,7 +162,7 @@
[totalFrames addObjectsFromArray:frames];
NSMutableData *aggregateFrameData = [NSMutableData data];
//BOOL hasKeyframe = NO;
BOOL hasKeyframe = NO;
for (NSData *data in totalFrames) {
unsigned char* pNal = (unsigned char*)[data bytes];
@@ -176,7 +174,7 @@
_sei = [NSMutableData dataWithData:data];
continue;
} else if (naltype == 5) { // IDR
//hasKeyframe = YES;
hasKeyframe = YES;
NSMutableData *IDRData = [NSMutableData dataWithData:_videoSPSandPPS];
if (_sei) {
[IDRData appendData:_naluStartCode];
@@ -248,16 +246,25 @@
}
- (void)initForFilePath {
NSString *path = [self GetFilePathByfileName:@"IOSCamDemo.h264"];
NSLog(@"%@", path);
self->fp = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "wb");
char *path = [self GetFilePathByfileName:"IOSCamDemo.h264"];
NSLog(@"%s", path);
self->fp = fopen(path, "wb");
}
- (NSString *)GetFilePathByfileName:(NSString*)filename {
- (char *)GetFilePathByfileName:(char *)filename {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:filename];
return writablePath;
NSString *strName = [NSString stringWithFormat:@"%s", filename];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:strName];
NSUInteger len = [writablePath length];
char *filepath = (char *)malloc(sizeof(char) * (len + 1));
[writablePath getCString:filepath maxLength:len + 1 encoding:[NSString defaultCStringEncoding]];
return filepath;
}
@end
+2 -2
View File
@@ -2,8 +2,8 @@
// LFHardwareAudioEncoder.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFAudioEncoding.h"
+43 -154
View File
@@ -2,19 +2,15 @@
// LFHardwareAudioEncoder.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFHardwareAudioEncoder.h"
@interface LFHardwareAudioEncoder (){
AudioConverterRef m_converter;
char *leftBuf;
char *aacBuf;
NSInteger leftLength;
FILE *fp;
BOOL enabledWriteVideoFile;
}
@property (nonatomic, strong) LFLiveAudioConfiguration *configuration;
@property (nonatomic, weak) id<LFAudioEncodingDelegate> aacDeleage;
@@ -23,31 +19,16 @@
@implementation LFHardwareAudioEncoder
- (instancetype)initWithAudioStreamConfiguration:(nullable LFLiveAudioConfiguration *)configuration {
- (instancetype)initWithAudioStreamConfiguration:(LFLiveAudioConfiguration *)configuration {
if (self = [super init]) {
NSLog(@"USE LFHardwareAudioEncoder");
_configuration = configuration;
if (!leftBuf) {
leftBuf = malloc(_configuration.bufferLength);
}
if (!aacBuf) {
aacBuf = malloc(_configuration.bufferLength);
}
#ifdef DEBUG
enabledWriteVideoFile = NO;
[self initForFilePath];
#endif
}
return self;
}
- (void)dealloc {
if (aacBuf) free(aacBuf);
if (leftBuf) free(leftBuf);
}
#pragma mark -- LFAudioEncoder
@@ -55,67 +36,29 @@
_aacDeleage = delegate;
}
- (void)encodeAudioData:(nullable NSData*)audioData timeStamp:(uint64_t)timeStamp {
- (void)encodeAudioData:(AudioBufferList)inBufferList timeStamp:(uint64_t)timeStamp {
if (![self createAudioConvert]) {
return;
}
if(leftLength + audioData.length >= self.configuration.bufferLength){
///<  发送
NSInteger totalSize = leftLength + audioData.length;
NSInteger encodeCount = totalSize/self.configuration.bufferLength;
char *totalBuf = malloc(totalSize);
char *p = totalBuf;
memset(totalBuf, (int)totalSize, 0);
memcpy(totalBuf, leftBuf, leftLength);
memcpy(totalBuf + leftLength, audioData.bytes, audioData.length);
for(NSInteger index = 0;index < encodeCount;index++){
[self encodeBuffer:p timeStamp:timeStamp];
p += self.configuration.bufferLength;
}
leftLength = totalSize%self.configuration.bufferLength;
memset(leftBuf, 0, self.configuration.bufferLength);
memcpy(leftBuf, totalBuf + (totalSize -leftLength), leftLength);
free(totalBuf);
}else{
///< 积累
memcpy(leftBuf+leftLength, audioData.bytes, audioData.length);
leftLength = leftLength + audioData.length;
}
}
- (void)encodeBuffer:(char*)buf timeStamp:(uint64_t)timeStamp{
AudioBuffer inBuffer;
inBuffer.mNumberChannels = 1;
inBuffer.mData = buf;
inBuffer.mDataByteSize = (UInt32)self.configuration.bufferLength;
AudioBufferList buffers;
buffers.mNumberBuffers = 1;
buffers.mBuffers[0] = inBuffer;
if (!aacBuf) {
aacBuf = malloc(inBufferList.mBuffers[0].mDataByteSize);
}
// 初始化一个输出缓冲列表
AudioBufferList outBufferList;
outBufferList.mNumberBuffers = 1;
outBufferList.mBuffers[0].mNumberChannels = inBuffer.mNumberChannels;
outBufferList.mBuffers[0].mDataByteSize = inBuffer.mDataByteSize; // 设置缓冲区大小
outBufferList.mBuffers[0].mNumberChannels = inBufferList.mBuffers[0].mNumberChannels;
outBufferList.mBuffers[0].mDataByteSize = inBufferList.mBuffers[0].mDataByteSize; // 设置缓冲区大小
outBufferList.mBuffers[0].mData = aacBuf; // 设置AAC缓冲区
UInt32 outputDataPacketSize = 1;
if (AudioConverterFillComplexBuffer(m_converter, inputDataProc, &buffers, &outputDataPacketSize, &outBufferList, NULL) != noErr) {
if (AudioConverterFillComplexBuffer(m_converter, inputDataProc, &inBufferList, &outputDataPacketSize, &outBufferList, NULL) != noErr) {
return;
}
LFAudioFrame *audioFrame = [LFAudioFrame new];
audioFrame.timestamp = timeStamp;
audioFrame.data = [NSData dataWithBytes:aacBuf length:outBufferList.mBuffers[0].mDataByteSize];
char exeData[2];
exeData[0] = _configuration.asc[0];
exeData[1] = _configuration.asc[1];
@@ -123,17 +66,10 @@
if (self.aacDeleage && [self.aacDeleage respondsToSelector:@selector(audioEncoder:audioFrame:)]) {
[self.aacDeleage audioEncoder:self audioFrame:audioFrame];
}
if (self->enabledWriteVideoFile) {
NSData *adts = [self adtsData:_configuration.numberOfChannels rawDataLength:audioFrame.data.length];
fwrite(adts.bytes, 1, adts.length, self->fp);
fwrite(audioFrame.data.bytes, 1, audioFrame.data.length, self->fp);
}
}
- (void)stopEncoder {
}
#pragma mark -- CustomMethod
@@ -141,7 +77,7 @@
if (m_converter != nil) {
return TRUE;
}
AudioStreamBasicDescription inputFormat = {0};
inputFormat.mSampleRate = _configuration.audioSampleRate;
inputFormat.mFormatID = kAudioFormatLinearPCM;
@@ -151,14 +87,14 @@
inputFormat.mBitsPerChannel = 16;
inputFormat.mBytesPerFrame = inputFormat.mBitsPerChannel / 8 * inputFormat.mChannelsPerFrame;
inputFormat.mBytesPerPacket = inputFormat.mBytesPerFrame * inputFormat.mFramesPerPacket;
AudioStreamBasicDescription outputFormat; // 这里开始是输出音频格式
memset(&outputFormat, 0, sizeof(outputFormat));
outputFormat.mSampleRate = inputFormat.mSampleRate; // 采样率保持一致
outputFormat.mFormatID = kAudioFormatMPEG4AAC; // AAC编码 kAudioFormatMPEG4AAC kAudioFormatMPEG4AAC_HE_V2
outputFormat.mChannelsPerFrame = (UInt32)_configuration.numberOfChannels;;
outputFormat.mFramesPerPacket = 1024; // AAC一帧是1024个字节
const OSType subtype = kAudioFormatMPEG4AAC;
AudioClassDescription requestedCodecs[2] = {
{
@@ -172,19 +108,35 @@
kAppleHardwareAudioCodecManufacturer
}
};
OSStatus result = AudioConverterNewSpecific(&inputFormat, &outputFormat, 2, requestedCodecs, &m_converter);;
UInt32 outputBitrate = _configuration.audioBitrate;
UInt32 propSize = sizeof(outputBitrate);
if(result == noErr) {
result = AudioConverterSetProperty(m_converter, kAudioConverterEncodeBitRate, propSize, &outputBitrate);
}
OSStatus result = AudioConverterNewSpecific(&inputFormat, &outputFormat, 2, requestedCodecs, &m_converter);
if (result != noErr) return NO;
return YES;
}
- (AudioClassDescription *)getAudioClassDescriptionWithType:(UInt32)type fromManufacturer:(UInt32)manufacturer { // 获得相应的编码器
static AudioClassDescription audioDesc;
UInt32 encoderSpecifier = type, size = 0;
OSStatus status;
memset(&audioDesc, 0, sizeof(audioDesc));
status = AudioFormatGetPropertyInfo(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier), &encoderSpecifier, &size);
if (status) {
return nil;
}
uint32_t count = size / sizeof(AudioClassDescription);
AudioClassDescription descs[count];
AudioFormatGetProperty(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier), &encoderSpecifier, &size, descs);
for (uint32_t i = 0; i < count; i++) {
if ((type == descs[i].mSubType) && (manufacturer == descs[i].mManufacturer)) {
memcpy(&audioDesc, &descs[i], sizeof(audioDesc));
break;
}
}
return &audioDesc;
}
#pragma mark -- AudioCallBack
OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription * *outDataPacketDescription, void *inUserData) { //<span style="font-family: Arial, Helvetica, sans-serif;">AudioConverterFillComplexBuffer 编码过程中,会要求这个函数来填充输入数据,也就是原始PCM数据</span>
@@ -195,8 +147,6 @@ OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPacket
return noErr;
}
#pragma mark -- Custom Method
/**
* Add ADTS header at the beginning of each and every AAC packet.
* This is needed as MediaCodec encoder generates a packet of raw
@@ -212,7 +162,7 @@ OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPacket
// Variables Recycled by addADTStoPacket
int profile = 2; //AAC LC
//39=MediaCodecInfo.CodecProfileLevel.AACObjectELD;
NSInteger freqIdx = [self sampleRateIndex:self.configuration.audioSampleRate]; //44.1KHz
int freqIdx = 4; //44.1KHz
int chanCfg = (int)channel; //MPEG-4 Audio Channel Configuration. 1 Channel front-center
NSUInteger fullLength = adtsLength + rawDataLength;
// fill in ADTS data
@@ -227,65 +177,4 @@ OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPacket
return data;
}
- (NSInteger)sampleRateIndex:(NSInteger)frequencyInHz {
NSInteger sampleRateIndex = 0;
switch (frequencyInHz) {
case 96000:
sampleRateIndex = 0;
break;
case 88200:
sampleRateIndex = 1;
break;
case 64000:
sampleRateIndex = 2;
break;
case 48000:
sampleRateIndex = 3;
break;
case 44100:
sampleRateIndex = 4;
break;
case 32000:
sampleRateIndex = 5;
break;
case 24000:
sampleRateIndex = 6;
break;
case 22050:
sampleRateIndex = 7;
break;
case 16000:
sampleRateIndex = 8;
break;
case 12000:
sampleRateIndex = 9;
break;
case 11025:
sampleRateIndex = 10;
break;
case 8000:
sampleRateIndex = 11;
break;
case 7350:
sampleRateIndex = 12;
break;
default:
sampleRateIndex = 15;
}
return sampleRateIndex;
}
- (void)initForFilePath {
NSString *path = [self GetFilePathByfileName:@"IOSCamDemo_HW.aac"];
NSLog(@"%@", path);
self->fp = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "wb");
}
- (NSString *)GetFilePathByfileName:(NSString*)filename {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:filename];
return writablePath;
}
@end
+2 -2
View File
@@ -2,8 +2,8 @@
// LFHardwareVideoEncoder.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFVideoEncoding.h"
+37 -28
View File
@@ -2,9 +2,10 @@
// LFHardwareVideoEncoder.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFHardwareVideoEncoder.h"
#import <VideoToolbox/VideoToolbox.h>
@@ -19,8 +20,8 @@
@property (nonatomic, strong) LFLiveVideoConfiguration *configuration;
@property (nonatomic, weak) id<LFVideoEncodingDelegate> h264Delegate;
@property (nonatomic) NSInteger currentVideoBitRate;
@property (nonatomic) BOOL isBackGround;
@property (nonatomic) NSInteger currentVideoBitRate;
@end
@@ -31,19 +32,20 @@
if (self = [super init]) {
NSLog(@"USE LFHardwareVideoEncoder");
_configuration = configuration;
[self resetCompressionSession];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterBackground:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterForeground:) name:UIApplicationDidBecomeActiveNotification object:nil];
[self initCompressionSession];
#ifdef DEBUG
enabledWriteVideoFile = NO;
[self initForFilePath];
#endif
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterBackground:) name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willEnterForeground:) name:UIApplicationDidBecomeActiveNotification object:nil];
}
return self;
}
- (void)resetCompressionSession {
- (void)initCompressionSession {
if (compressionSession) {
VTCompressionSessionCompleteFrames(compressionSession, kCMTimeInvalid);
@@ -59,12 +61,12 @@
_currentVideoBitRate = _configuration.videoBitRate;
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_MaxKeyFrameInterval, (__bridge CFTypeRef)@(_configuration.videoMaxKeyframeInterval));
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, (__bridge CFTypeRef)@(_configuration.videoMaxKeyframeInterval/_configuration.videoFrameRate));
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, (__bridge CFTypeRef)@(_configuration.videoMaxKeyframeInterval));
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_ExpectedFrameRate, (__bridge CFTypeRef)@(_configuration.videoFrameRate));
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_AverageBitRate, (__bridge CFTypeRef)@(_configuration.videoBitRate));
NSArray *limit = @[@(_configuration.videoBitRate * 1.5/8), @(1)];
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_DataRateLimits, (__bridge CFArrayRef)limit);
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_RealTime, kCFBooleanTrue);
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_RealTime, kCFBooleanFalse);
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_ProfileLevel, kVTProfileLevel_H264_Main_AutoLevel);
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanTrue);
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_H264EntropyMode, kVTH264EntropyMode_CABAC);
@@ -73,7 +75,7 @@
}
- (void)setVideoBitRate:(NSInteger)videoBitRate {
if(_isBackGround) return;
if (_isBackGround) return;
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_AverageBitRate, (__bridge CFTypeRef)@(videoBitRate));
NSArray *limit = @[@(videoBitRate * 1.5/8), @(1)];
VTSessionSetProperty(compressionSession, kVTCompressionPropertyKey_DataRateLimits, (__bridge CFArrayRef)limit);
@@ -96,10 +98,11 @@
}
#pragma mark -- LFVideoEncoder
- (void)encodeVideoData:(CVPixelBufferRef)pixelBuffer timeStamp:(uint64_t)timeStamp {
if(_isBackGround) return;
- (void)encodeVideoData:(CVImageBufferRef)pixelBuffer timeStamp:(uint64_t)timeStamp {
if (_isBackGround) return;
frameCount++;
CMTime presentationTimeStamp = CMTimeMake(frameCount, (int32_t)_configuration.videoFrameRate);
CMTime presentationTimeStamp = CMTimeMake(frameCount, 1000);
VTEncodeInfoFlags flags;
CMTime duration = CMTimeMake(1, (int32_t)_configuration.videoFrameRate);
@@ -109,10 +112,7 @@
}
NSNumber *timeNumber = @(timeStamp);
OSStatus status = VTCompressionSessionEncodeFrame(compressionSession, pixelBuffer, presentationTimeStamp, duration, (__bridge CFDictionaryRef)properties, (__bridge_retained void *)timeNumber, &flags);
if(status != noErr){
[self resetCompressionSession];
}
VTCompressionSessionEncodeFrame(compressionSession, pixelBuffer, presentationTimeStamp, duration, (__bridge CFDictionaryRef)properties, (__bridge_retained void *)timeNumber, &flags);
}
- (void)stopEncoder {
@@ -123,13 +123,13 @@
_h264Delegate = delegate;
}
#pragma mark -- Notification
- (void)willEnterBackground:(NSNotification*)notification{
#pragma mark -- NSNotification
- (void)willEnterBackground:(NSNotification *)notification {
_isBackGround = YES;
}
- (void)willEnterForeground:(NSNotification*)notification{
[self resetCompressionSession];
- (void)willEnterForeground:(NSNotification *)notification {
[self initCompressionSession];
_isBackGround = NO;
}
@@ -226,16 +226,25 @@ static void VideoCompressonOutputCallback(void *VTref, void *VTFrameRef, OSStatu
}
- (void)initForFilePath {
NSString *path = [self GetFilePathByfileName:@"IOSCamDemo.h264"];
NSLog(@"%@", path);
self->fp = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "wb");
char *path = [self GetFilePathByfileName:"IOSCamDemo_HW.h264"];
NSLog(@"%s", path);
self->fp = fopen(path, "wb");
}
- (NSString *)GetFilePathByfileName:(NSString*)filename {
- (char *)GetFilePathByfileName:(char *)filename {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:filename];
return writablePath;
NSString *strName = [NSString stringWithFormat:@"%s", filename];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:strName];
NSUInteger len = [writablePath length];
char *filepath = (char *)malloc(sizeof(char) * (len + 1));
[writablePath getCString:filepath maxLength:len + 1 encoding:[NSString defaultCStringEncoding]];
return filepath;
}
@end
+5 -4
View File
@@ -2,8 +2,8 @@
// LFVideoEncoding.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -20,11 +20,12 @@
/// 编码器抽象的接口
@protocol LFVideoEncoding <NSObject>
@required
- (void)encodeVideoData:(nullable CVPixelBufferRef)pixelBuffer timeStamp:(uint64_t)timeStamp;
- (void)encodeVideoData:(nullable CVImageBufferRef)pixelBuffer timeStamp:(uint64_t)timeStamp;
- (void)stopEncoder;
@optional
@property (nonatomic, assign) NSInteger videoBitRate;
- (nullable instancetype)initWithVideoStreamConfiguration:(nullable LFLiveVideoConfiguration *)configuration;
- (void)setDelegate:(nullable id<LFVideoEncodingDelegate>)delegate;
- (void)stopEncoder;
@end
@@ -2,8 +2,8 @@
// LFLiveAudioConfiguration.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/1.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -19,16 +19,14 @@ typedef NS_ENUM (NSUInteger, LFLiveAudioBitRate) {
/// 128Kbps 音频码率
LFLiveAudioBitRate_128Kbps = 128000,
/// 默认音频码率,默认为 64Kbps
LFLiveAudioBitRate_Default = LFLiveAudioBitRate_96Kbps
LFLiveAudioBitRate_Default = LFLiveAudioBitRate_64Kbps
};
/// 采样率 (默认44.1Hz)
/// 采样率 (默认44.1Hz iphoneg6以上48Hz)
typedef NS_ENUM (NSUInteger, LFLiveAudioSampleRate){
/// 16KHz 采样率
LFLiveAudioSampleRate_16000Hz = 16000,
/// 44.1KHz 采样率
/// 44.1Hz 采样率
LFLiveAudioSampleRate_44100Hz = 44100,
/// 48KHz 采样率
/// 48Hz 采样率
LFLiveAudioSampleRate_48000Hz = 48000,
/// 默认音频码率,默认为 64Kbps
LFLiveAudioSampleRate_Default = LFLiveAudioSampleRate_44100Hz
@@ -36,16 +34,16 @@ typedef NS_ENUM (NSUInteger, LFLiveAudioSampleRate){
/// Audio Live quality(音频质量)
typedef NS_ENUM (NSUInteger, LFLiveAudioQuality){
/// 高音频质量 audio sample rate: 16KHz audio bitrate: numberOfChannels 1 : 32Kbps 2 : 64Kbps
/// 高音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 32Kbps
LFLiveAudioQuality_Low = 0,
/// 高音频质量 audio sample rate: 44KHz audio bitrate: 96Kbps
/// 高音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 64Kbps
LFLiveAudioQuality_Medium = 1,
/// 高音频质量 audio sample rate: 44MHz audio bitrate: 128Kbps
/// 高音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 96Kbps
LFLiveAudioQuality_High = 2,
/// 高音频质量 audio sample rate: 48MHz, audio bitrate: 128Kbps
/// 高音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 128Kbps
LFLiveAudioQuality_VeryHigh = 3,
/// 默认音频质量 audio sample rate: 44MHz, audio bitrate: 96Kbps
LFLiveAudioQuality_Default = LFLiveAudioQuality_High
/// 默认音频质量 audio sample rate: 44MHz(默认44.1Hz iphoneg6以上48Hz), audio bitrate: 64Kbps
LFLiveAudioQuality_Default = LFLiveAudioQuality_Medium
};
@interface LFLiveAudioConfiguration : NSObject<NSCoding, NSCopying>
@@ -67,7 +65,5 @@ typedef NS_ENUM (NSUInteger, LFLiveAudioQuality){
@property (nonatomic, assign) LFLiveAudioBitRate audioBitrate;
/// flv编码音频头 44100 为0x12 0x10
@property (nonatomic, assign, readonly) char *asc;
/// 缓存区长度
@property (nonatomic, assign,readonly) NSUInteger bufferLength;
@end
@@ -2,8 +2,8 @@
// LFLiveAudioConfiguration.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/1.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFLiveAudioConfiguration.h"
@@ -21,32 +21,24 @@
LFLiveAudioConfiguration *audioConfig = [LFLiveAudioConfiguration new];
audioConfig.numberOfChannels = 2;
switch (audioQuality) {
case LFLiveAudioQuality_Default: {
audioConfig.audioBitrate = LFLiveAudioBitRate_64Kbps;
}
break;
case LFLiveAudioQuality_Low: {
audioConfig.audioBitrate = audioConfig.numberOfChannels == 1 ? LFLiveAudioBitRate_32Kbps : LFLiveAudioBitRate_64Kbps;
audioConfig.audioSampleRate = LFLiveAudioSampleRate_16000Hz;
audioConfig.audioBitrate = LFLiveAudioBitRate_32Kbps;
}
break;
case LFLiveAudioQuality_Medium: {
audioConfig.audioBitrate = LFLiveAudioBitRate_96Kbps;
audioConfig.audioSampleRate = LFLiveAudioSampleRate_44100Hz;
}
break;
case LFLiveAudioQuality_High: {
audioConfig.audioBitrate = LFLiveAudioBitRate_128Kbps;
audioConfig.audioSampleRate = LFLiveAudioSampleRate_44100Hz;
audioConfig.audioBitrate = LFLiveAudioBitRate_96Kbps;
}
break;
case LFLiveAudioQuality_VeryHigh: {
audioConfig.audioBitrate = LFLiveAudioBitRate_128Kbps;
audioConfig.audioSampleRate = LFLiveAudioSampleRate_48000Hz;
}
break;
default:{
audioConfig.audioBitrate = LFLiveAudioBitRate_96Kbps;
audioConfig.audioSampleRate = LFLiveAudioSampleRate_44100Hz;
}
break;
default:
break;
}
audioConfig.audioSampleRate = [self.class isNewThaniPhone6] ? LFLiveAudioSampleRate_48000Hz : LFLiveAudioSampleRate_44100Hz;
return audioConfig;
}
@@ -66,21 +58,17 @@
- (void)setAudioSampleRate:(LFLiveAudioSampleRate)audioSampleRate {
_audioSampleRate = audioSampleRate;
NSInteger sampleRateIndex = [self sampleRateIndex:audioSampleRate];
self.asc[0] = 0x10 | ((sampleRateIndex>>1) & 0x7);
self.asc[0] = 0x10 | ((sampleRateIndex>>1) & 0x3);
self.asc[1] = ((sampleRateIndex & 0x1)<<7) | ((self.numberOfChannels & 0xF) << 3);
}
- (void)setNumberOfChannels:(NSUInteger)numberOfChannels {
_numberOfChannels = numberOfChannels;
NSInteger sampleRateIndex = [self sampleRateIndex:self.audioSampleRate];
self.asc[0] = 0x10 | ((sampleRateIndex>>1) & 0x7);
self.asc[0] = 0x10 | ((sampleRateIndex>>1) & 0x3);
self.asc[1] = ((sampleRateIndex & 0x1)<<7) | ((numberOfChannels & 0xF) << 3);
}
- (NSUInteger)bufferLength{
return 1024*2*self.numberOfChannels;
}
#pragma mark -- CustomMethod
- (NSInteger)sampleRateIndex:(NSInteger)frequencyInHz {
NSInteger sampleRateIndex = 0;
@@ -130,6 +118,57 @@
return sampleRateIndex;
}
#pragma mark -- DeviceCategory
+ (NSString *)deviceName {
struct utsname systemInfo;
uname(&systemInfo);
return [NSString stringWithCString:systemInfo.machine
encoding:NSUTF8StringEncoding];
}
//@"iPad4,1" on 5th Generation iPad (iPad Air) - Wifi
//@"iPad4,2" on 5th Generation iPad (iPad Air) - Cellular
//@"iPad4,4" on 2nd Generation iPad Mini - Wifi
//@"iPad4,5" on 2nd Generation iPad Mini - Cellular
//@"iPad4,7" on 3rd Generation iPad Mini - Wifi (model A1599)
//@"iPhone7,1" on iPhone 6 Plus
//@"iPhone7,2" on iPhone 6
//@"iPhone8,1" on iPhone 6S
//@"iPhone8,2" on iPhone 6S Plus
+ (BOOL)isNewThaniPhone6 {
NSString *device = [self deviceName];
NSLog(@"device %@", device);
if (device == nil) {
return NO;
}
NSArray *array = [device componentsSeparatedByString:@","];
if (array.count < 2) {
return NO;
}
NSString *model = [array objectAtIndex:0];
NSLog(@"model %@", model);
if ([model hasPrefix:@"iPhone"]) {
NSString *str1 = [model substringFromIndex:[@"iPhone" length]];
NSUInteger num = [str1 integerValue];
NSLog(@"num %lu", (unsigned long)num);
if (num > 7) {
return YES;
}
}
if ([model hasPrefix:@"iPad"]) {
NSString *str1 = [model substringFromIndex:[@"iPad" length]];
NSUInteger num = [str1 integerValue];
if (num > 4) {
return YES;
}
}
return NO;
}
#pragma mark -- Encoder
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:@(self.numberOfChannels) forKey:@"numberOfChannels"];
@@ -2,8 +2,8 @@
// LFLiveVideoConfiguration.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/1.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -51,23 +51,17 @@ typedef NS_ENUM (NSUInteger, LFLiveVideoQuality){
+ (instancetype)defaultConfigurationForQuality:(LFLiveVideoQuality)videoQuality;
/// 视频配置(质量 & 是否是横屏)
+ (instancetype)defaultConfigurationForQuality:(LFLiveVideoQuality)videoQuality outputImageOrientation:(UIInterfaceOrientation)outputImageOrientation;
+ (instancetype)defaultConfigurationForQuality:(LFLiveVideoQuality)videoQuality landscape:(BOOL)landscape;
#pragma mark - Attribute
///=============================================================================
/// @name Attribute
///=============================================================================
/// 视频的分辨率,宽高务必设定为 2 的倍数,否则解码播放时可能出现绿边(这个videoSizeRespectingAspectRatio设置为YES则可能会改变)
/// 视频的分辨率,宽高务必设定为 2 的倍数,否则解码播放时可能出现绿边
@property (nonatomic, assign) CGSize videoSize;
/// 输出图像是否等比例,默认为NO
@property (nonatomic, assign) BOOL videoSizeRespectingAspectRatio;
/// 视频输出方向
@property (nonatomic, assign) UIInterfaceOrientation outputImageOrientation;
/// 自动旋转(这里只支持 left 变 right portrait 变 portraitUpsideDown)
@property (nonatomic, assign) BOOL autorotate;
@property (nonatomic, assign) BOOL landscape;
/// 视频的帧率,即 fps
@property (nonatomic, assign) NSUInteger videoFrameRate;
@@ -96,7 +90,4 @@ typedef NS_ENUM (NSUInteger, LFLiveVideoQuality){
///< ≈sde3分辨率
@property (nonatomic, assign, readonly) NSString *avSessionPreset;
///< 是否是横屏
@property (nonatomic, assign, readonly) BOOL landscape;
@end
@@ -2,32 +2,31 @@
// LFLiveVideoConfiguration.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/1.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFLiveVideoConfiguration.h"
#import <AVFoundation/AVFoundation.h>
@implementation LFLiveVideoConfiguration
#pragma mark -- LifeCycle
+ (instancetype)defaultConfiguration {
LFLiveVideoConfiguration *configuration = [LFLiveVideoConfiguration defaultConfigurationForQuality:LFLiveVideoQuality_Default];
return configuration;
}
+ (instancetype)defaultConfigurationForQuality:(LFLiveVideoQuality)videoQuality {
LFLiveVideoConfiguration *configuration = [LFLiveVideoConfiguration defaultConfigurationForQuality:videoQuality outputImageOrientation:UIInterfaceOrientationPortrait];
LFLiveVideoConfiguration *configuration = [LFLiveVideoConfiguration defaultConfigurationForQuality:videoQuality landscape:NO];
return configuration;
}
+ (instancetype)defaultConfigurationForQuality:(LFLiveVideoQuality)videoQuality outputImageOrientation:(UIInterfaceOrientation)outputImageOrientation {
+ (instancetype)defaultConfigurationForQuality:(LFLiveVideoQuality)videoQuality landscape:(BOOL)landscape {
LFLiveVideoConfiguration *configuration = [LFLiveVideoConfiguration new];
switch (videoQuality) {
case LFLiveVideoQuality_Low1:{
case LFLiveVideoQuality_Low1:
{
configuration.sessionPreset = LFCaptureSessionPreset360x640;
configuration.videoFrameRate = 15;
configuration.videoMaxFrameRate = 15;
@@ -37,8 +36,9 @@
configuration.videoMinBitRate = 400 * 1000;
configuration.videoSize = CGSizeMake(360, 640);
}
break;
case LFLiveVideoQuality_Low2:{
break;
case LFLiveVideoQuality_Low2:
{
configuration.sessionPreset = LFCaptureSessionPreset360x640;
configuration.videoFrameRate = 24;
configuration.videoMaxFrameRate = 24;
@@ -48,8 +48,9 @@
configuration.videoMinBitRate = 500 * 1000;
configuration.videoSize = CGSizeMake(360, 640);
}
break;
case LFLiveVideoQuality_Low3: {
break;
case LFLiveVideoQuality_Low3:
{
configuration.sessionPreset = LFCaptureSessionPreset360x640;
configuration.videoFrameRate = 30;
configuration.videoMaxFrameRate = 30;
@@ -59,8 +60,9 @@
configuration.videoMinBitRate = 600 * 1000;
configuration.videoSize = CGSizeMake(360, 640);
}
break;
case LFLiveVideoQuality_Medium1:{
break;
case LFLiveVideoQuality_Medium1:
{
configuration.sessionPreset = LFCaptureSessionPreset540x960;
configuration.videoFrameRate = 15;
configuration.videoMaxFrameRate = 15;
@@ -70,8 +72,9 @@
configuration.videoMinBitRate = 500 * 1000;
configuration.videoSize = CGSizeMake(540, 960);
}
break;
case LFLiveVideoQuality_Medium2:{
break;
case LFLiveVideoQuality_Medium2:
{
configuration.sessionPreset = LFCaptureSessionPreset540x960;
configuration.videoFrameRate = 24;
configuration.videoMaxFrameRate = 24;
@@ -81,8 +84,9 @@
configuration.videoMinBitRate = 500 * 1000;
configuration.videoSize = CGSizeMake(540, 960);
}
break;
case LFLiveVideoQuality_Medium3:{
break;
case LFLiveVideoQuality_Medium3:
{
configuration.sessionPreset = LFCaptureSessionPreset540x960;
configuration.videoFrameRate = 30;
configuration.videoMaxFrameRate = 30;
@@ -92,8 +96,9 @@
configuration.videoMinBitRate = 500 * 1000;
configuration.videoSize = CGSizeMake(540, 960);
}
break;
case LFLiveVideoQuality_High1:{
break;
case LFLiveVideoQuality_High1:
{
configuration.sessionPreset = LFCaptureSessionPreset720x1280;
configuration.videoFrameRate = 15;
configuration.videoMaxFrameRate = 15;
@@ -103,8 +108,9 @@
configuration.videoMinBitRate = 500 * 1000;
configuration.videoSize = CGSizeMake(720, 1280);
}
break;
case LFLiveVideoQuality_High2:{
break;
case LFLiveVideoQuality_High2:
{
configuration.sessionPreset = LFCaptureSessionPreset720x1280;
configuration.videoFrameRate = 24;
configuration.videoMaxFrameRate = 24;
@@ -114,8 +120,9 @@
configuration.videoMinBitRate = 800 * 1000;
configuration.videoSize = CGSizeMake(720, 1280);
}
break;
case LFLiveVideoQuality_High3:{
break;
case LFLiveVideoQuality_High3:
{
configuration.sessionPreset = LFCaptureSessionPreset720x1280;
configuration.videoFrameRate = 30;
configuration.videoMaxFrameRate = 30;
@@ -125,58 +132,49 @@
configuration.videoMinBitRate = 500 * 1000;
configuration.videoSize = CGSizeMake(720, 1280);
}
break;
break;
default:
break;
}
configuration.sessionPreset = [configuration supportSessionPreset:configuration.sessionPreset];
configuration.videoMaxKeyframeInterval = configuration.videoFrameRate*2;
configuration.outputImageOrientation = outputImageOrientation;
configuration.landscape = landscape;
CGSize size = configuration.videoSize;
if(configuration.landscape) {
if (landscape) {
configuration.videoSize = CGSizeMake(size.height, size.width);
} else {
configuration.videoSize = CGSizeMake(size.width, size.height);
}
return configuration;
}
#pragma mark -- Setter Getter
- (NSString *)avSessionPreset {
NSString *avSessionPreset = nil;
switch (self.sessionPreset) {
case LFCaptureSessionPreset360x640:{
case LFCaptureSessionPreset360x640:
{
avSessionPreset = AVCaptureSessionPreset640x480;
}
break;
case LFCaptureSessionPreset540x960:{
break;
case LFCaptureSessionPreset540x960:
{
avSessionPreset = AVCaptureSessionPresetiFrame960x540;
}
break;
case LFCaptureSessionPreset720x1280:{
break;
case LFCaptureSessionPreset720x1280:
{
avSessionPreset = AVCaptureSessionPreset1280x720;
}
break;
break;
default: {
avSessionPreset = AVCaptureSessionPreset640x480;
}
break;
break;
}
return avSessionPreset;
}
- (BOOL)landscape{
return (self.outputImageOrientation == UIInterfaceOrientationLandscapeLeft || self.outputImageOrientation == UIInterfaceOrientationLandscapeRight) ? YES : NO;
}
- (CGSize)videoSize{
if(_videoSizeRespectingAspectRatio){
return self.aspectRatioVideoSize;
}
return _videoSize;
}
- (void)setVideoMaxBitRate:(NSUInteger)videoMaxBitRate {
if (videoMaxBitRate <= _videoBitRate) return;
_videoMaxBitRate = videoMaxBitRate;
@@ -197,31 +195,15 @@
_videoMinFrameRate = videoMinFrameRate;
}
- (void)setSessionPreset:(LFLiveVideoSessionPreset)sessionPreset{
_sessionPreset = sessionPreset;
_sessionPreset = [self supportSessionPreset:sessionPreset];
}
#pragma mark -- Custom Method
- (LFLiveVideoSessionPreset)supportSessionPreset:(LFLiveVideoSessionPreset)sessionPreset {
NSString *avSessionPreset = [self avSessionPreset];
AVCaptureSession *session = [[AVCaptureSession alloc] init];
AVCaptureDevice *inputCamera;
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices){
if ([device position] == AVCaptureDevicePositionFront){
inputCamera = device;
}
}
AVCaptureDeviceInput *videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:inputCamera error:nil];
if ([session canAddInput:videoInput]){
[session addInput:videoInput];
}
if (![session canSetSessionPreset:self.avSessionPreset]) {
if (![session canSetSessionPreset:avSessionPreset]) {
if (sessionPreset == LFCaptureSessionPreset720x1280) {
sessionPreset = LFCaptureSessionPreset540x960;
if (![session canSetSessionPreset:self.avSessionPreset]) {
if (![session canSetSessionPreset:avSessionPreset]) {
sessionPreset = LFCaptureSessionPreset360x640;
}
} else if (sessionPreset == LFCaptureSessionPreset540x960) {
@@ -231,73 +213,24 @@
return sessionPreset;
}
- (CGSize)captureOutVideoSize{
CGSize videoSize = CGSizeZero;
switch (_sessionPreset) {
case LFCaptureSessionPreset360x640:{
videoSize = CGSizeMake(360, 640);
}
break;
case LFCaptureSessionPreset540x960:{
videoSize = CGSizeMake(540, 960);
}
break;
case LFCaptureSessionPreset720x1280:{
videoSize = CGSizeMake(720, 1280);
}
break;
default:{
videoSize = CGSizeMake(360, 640);
}
break;
}
if (self.landscape){
return CGSizeMake(videoSize.height, videoSize.width);
}
return videoSize;
}
- (CGSize)aspectRatioVideoSize{
CGSize size = AVMakeRectWithAspectRatioInsideRect(self.captureOutVideoSize, CGRectMake(0, 0, _videoSize.width, _videoSize.height)).size;
NSInteger width = ceil(size.width);
NSInteger height = ceil(size.height);
if(width %2 != 0) width = width - 1;
if(height %2 != 0) height = height - 1;
return CGSizeMake(width, height);
}
#pragma mark -- encoder
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:[NSValue valueWithCGSize:self.videoSize] forKey:@"videoSize"];
[aCoder encodeObject:@(self.videoFrameRate) forKey:@"videoFrameRate"];
[aCoder encodeObject:@(self.videoMaxFrameRate) forKey:@"videoMaxFrameRate"];
[aCoder encodeObject:@(self.videoMinFrameRate) forKey:@"videoMinFrameRate"];
[aCoder encodeObject:@(self.videoMaxKeyframeInterval) forKey:@"videoMaxKeyframeInterval"];
[aCoder encodeObject:@(self.videoBitRate) forKey:@"videoBitRate"];
[aCoder encodeObject:@(self.videoMaxBitRate) forKey:@"videoMaxBitRate"];
[aCoder encodeObject:@(self.videoMinBitRate) forKey:@"videoMinBitRate"];
[aCoder encodeObject:@(self.sessionPreset) forKey:@"sessionPreset"];
[aCoder encodeObject:@(self.outputImageOrientation) forKey:@"outputImageOrientation"];
[aCoder encodeObject:@(self.autorotate) forKey:@"autorotate"];
[aCoder encodeObject:@(self.videoSizeRespectingAspectRatio) forKey:@"videoSizeRespectingAspectRatio"];
[aCoder encodeObject:@(self.landscape) forKey:@"landscape"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
_videoSize = [[aDecoder decodeObjectForKey:@"videoSize"] CGSizeValue];
_videoFrameRate = [[aDecoder decodeObjectForKey:@"videoFrameRate"] unsignedIntegerValue];
_videoMaxFrameRate = [[aDecoder decodeObjectForKey:@"videoMaxFrameRate"] unsignedIntegerValue];
_videoMinFrameRate = [[aDecoder decodeObjectForKey:@"videoMinFrameRate"] unsignedIntegerValue];
_videoMaxKeyframeInterval = [[aDecoder decodeObjectForKey:@"videoMaxKeyframeInterval"] unsignedIntegerValue];
_videoBitRate = [[aDecoder decodeObjectForKey:@"videoBitRate"] unsignedIntegerValue];
_videoMaxBitRate = [[aDecoder decodeObjectForKey:@"videoMaxBitRate"] unsignedIntegerValue];
_videoMinBitRate = [[aDecoder decodeObjectForKey:@"videoMinBitRate"] unsignedIntegerValue];
_sessionPreset = [[aDecoder decodeObjectForKey:@"sessionPreset"] unsignedIntegerValue];
_outputImageOrientation = [[aDecoder decodeObjectForKey:@"outputImageOrientation"] unsignedIntegerValue];
_autorotate = [[aDecoder decodeObjectForKey:@"autorotate"] boolValue];
_videoSizeRespectingAspectRatio = [[aDecoder decodeObjectForKey:@"videoSizeRespectingAspectRatio"] unsignedIntegerValue];
_landscape = [[aDecoder decodeObjectForKey:@"landscape"] unsignedIntegerValue];
return self;
}
@@ -313,9 +246,7 @@
@(self.videoMinBitRate),
self.avSessionPreset,
@(self.sessionPreset),
@(self.outputImageOrientation),
@(self.autorotate),
@(self.videoSizeRespectingAspectRatio)];
@(self.landscape), ];
for (NSObject *value in values) {
hash ^= value.hash;
@@ -340,9 +271,7 @@
object.videoMinBitRate == self.videoMinBitRate &&
[object.avSessionPreset isEqualToString:self.avSessionPreset] &&
object.sessionPreset == self.sessionPreset &&
object.outputImageOrientation == self.outputImageOrientation &&
object.autorotate == self.autorotate &&
object.videoSizeRespectingAspectRatio == self.videoSizeRespectingAspectRatio;
object.landscape == self.landscape;
}
}
@@ -355,7 +284,6 @@
NSMutableString *desc = @"".mutableCopy;
[desc appendFormat:@"<LFLiveVideoConfiguration: %p>", self];
[desc appendFormat:@" videoSize:%@", NSStringFromCGSize(self.videoSize)];
[desc appendFormat:@" videoSizeRespectingAspectRatio:%zi",self.videoSizeRespectingAspectRatio];
[desc appendFormat:@" videoFrameRate:%zi", self.videoFrameRate];
[desc appendFormat:@" videoMaxFrameRate:%zi", self.videoMaxFrameRate];
[desc appendFormat:@" videoMinFrameRate:%zi", self.videoMinFrameRate];
@@ -365,8 +293,7 @@
[desc appendFormat:@" videoMinBitRate:%zi", self.videoMinBitRate];
[desc appendFormat:@" avSessionPreset:%@", self.avSessionPreset];
[desc appendFormat:@" sessionPreset:%zi", self.sessionPreset];
[desc appendFormat:@" outputImageOrientation:%zi", self.outputImageOrientation];
[desc appendFormat:@" autorotate:%zi", self.autorotate];
[desc appendFormat:@" landscape:%zi", self.landscape];
return desc;
}
+1 -5
View File
@@ -1,8 +1,4 @@
#if __has_include(<GPUImage/GPUImageFramework.h>)
#import <GPUImage/GPUImageFramework.h>
#else
#import "GPUImage.h"
#endif
#import "GPUImageFilter.h"
@interface LFGPUImageBeautyFilter : GPUImageFilter {
}
@@ -238,6 +238,7 @@ NSString *const kLFGPUImageBeautyFragmentShaderString = SHADER_STRING
}
- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex {
CGSize oldInputSize = inputTextureSize;
[super setInputSize:newSize atIndex:textureIndex];
inputTextureSize = newSize;
+1 -5
View File
@@ -1,8 +1,4 @@
#if __has_include(<GPUImage/GPUImageFramework.h>)
#import <GPUImage/GPUImageFramework.h>
#else
#import "GPUImage.h"
#endif
#import "GPUImageFilter.h"
@interface LFGPUImageEmptyFilter : GPUImageFilter
{
+2 -2
View File
@@ -2,8 +2,8 @@
// LFAudioFrame.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFFrame.h"
+2 -2
View File
@@ -2,8 +2,8 @@
// LFAudioFrame.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFAudioFrame.h"
+3 -3
View File
@@ -2,15 +2,15 @@
// LFFrame.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface LFFrame : NSObject
@property (nonatomic, assign,) uint64_t timestamp;
@property (nonatomic, assign) uint64_t timestamp;
@property (nonatomic, strong) NSData *data;
///< flv或者rtmp包头
@property (nonatomic, strong) NSData *header;
+2 -2
View File
@@ -2,8 +2,8 @@
// LFFrame.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFFrame.h"
+2 -2
View File
@@ -2,8 +2,8 @@
// LFLiveDebug.h
// LaiFeng
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by admin on 16/5/19.
// Copyright © 2016年 live Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
+2 -2
View File
@@ -2,8 +2,8 @@
// LFLiveDebug.m
// LaiFeng
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by admin on 16/5/19.
// Copyright © 2016年 live Interactive. All rights reserved.
//
#import "LFLiveDebug.h"
+5 -8
View File
@@ -2,16 +2,14 @@
// LFLiveStreamInfo.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
//
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
// 真正的上传地址 token等
#import <Foundation/Foundation.h>
#import "LFLiveAudioConfiguration.h"
#import "LFLiveVideoConfiguration.h"
/// 流状态
typedef NS_ENUM (NSUInteger, LFLiveState){
/// 准备
@@ -23,9 +21,7 @@ typedef NS_ENUM (NSUInteger, LFLiveState){
/// 已断开
LFLiveStop = 3,
/// 连接出错
LFLiveError = 4,
///  正在刷新
LFLiveRefresh = 5
LFLiveError = 4
};
typedef NS_ENUM (NSUInteger, LFLiveSocketErrorCode) {
@@ -50,4 +46,5 @@ typedef NS_ENUM (NSUInteger, LFLiveSocketErrorCode) {
///视频配置
@property (nonatomic, strong) LFLiveVideoConfiguration *videoConfiguration;
@end
+2 -2
View File
@@ -2,8 +2,8 @@
// LFLiveStreamInfo.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFLiveStreamInfo.h"
+2 -3
View File
@@ -2,13 +2,12 @@
// LFVideoFrame.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFFrame.h"
@interface LFVideoFrame : LFFrame
@property (nonatomic, assign) BOOL isKeyFrame;
+2 -2
View File
@@ -2,8 +2,8 @@
// LFVideoFrame.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFVideoFrame.h"
+2 -2
View File
@@ -2,8 +2,8 @@
// LFStreamRTMPSocket.h
// LaiFeng
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by admin on 16/5/18.
// Copyright © 2016年 live Interactive. All rights reserved.
//
#import "LFStreamSocket.h"
@@ -2,19 +2,14 @@
// LFStreamRTMPSocket.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016 LaiFeng All rights reserved.
// Created by admin on 16/5/18.
// Copyright © 2016 live Interactive. All rights reserved.
//
#import "LFStreamRTMPSocket.h"
#if __has_include(<pili-librtmp/rtmp.h>)
#import <pili-librtmp/rtmp.h>
#else
#import "rtmp.h"
#endif
static const NSInteger RetryTimesBreaken = 5; ///< 1 3 20
static const NSInteger RetryTimesBreaken = 20; ///< 1 3 20
static const NSInteger RetryTimesMargin = 3;
@@ -26,7 +21,7 @@ static const NSInteger RetryTimesMargin = 3;
#define SAVC(x) static const AVal av_ ## x = AVC(#x)
static const AVal av_setDataFrame = AVC("@setDataFrame");
static const AVal av_SDKVersion = AVC("LFLiveKit 2.4.0");
static const AVal av_SDKVersion = AVC("LFLiveKit 1.8.0");
SAVC(onMetaData);
SAVC(duration);
SAVC(width);
@@ -38,10 +33,10 @@ SAVC(audiocodecid);
SAVC(audiodatarate);
SAVC(audiosamplerate);
SAVC(audiosamplesize);
//SAVC(audiochannels);
SAVC(audiochannels);
SAVC(stereo);
SAVC(encoder);
//SAVC(av_stereo);
SAVC(av_stereo);
SAVC(fileSize);
SAVC(avc1);
SAVC(mp4a);
@@ -74,17 +69,13 @@ SAVC(mp4a);
@implementation LFStreamRTMPSocket
#pragma mark -- LFStreamSocket
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream{
return [self initWithStream:stream reconnectInterval:0 reconnectCount:0];
}
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream reconnectInterval:(NSInteger)reconnectInterval reconnectCount:(NSInteger)reconnectCount{
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream videoSize:(CGSize)videoSize reconnectInterval:(NSInteger)reconnectInterval reconnectCount:(NSInteger)reconnectCount {
if (!stream) @throw [NSException exceptionWithName:@"LFStreamRtmpSocket init error" reason:@"stream is nil" userInfo:nil];
if (self = [super init]) {
_stream = stream;
if (reconnectInterval > 0) _reconnectInterval = reconnectInterval;
else _reconnectInterval = RetryTimesMargin;
if (reconnectCount > 0) _reconnectCount = reconnectCount;
else _reconnectCount = RetryTimesBreaken;
@@ -110,24 +101,12 @@ SAVC(mp4a);
self.debugInfo.streamId = self.stream.streamId;
self.debugInfo.uploadUrl = self.stream.url;
self.debugInfo.isRtmp = YES;
if (_isConnecting) return;
_isConnecting = YES;
if (self.delegate && [self.delegate respondsToSelector:@selector(socketStatus:status:)]) {
[self.delegate socketStatus:self status:LFLivePending];
}
if (_rtmp != NULL) {
PILI_RTMP_Close(_rtmp, &_error);
PILI_RTMP_Free(_rtmp);
}
[self RTMP264_Connect:(char *)[_stream.url cStringUsingEncoding:NSASCIIStringEncoding]];
}
- (void)stop {
dispatch_async(self.rtmpSendQueue, ^{
[self _stop];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
});
}
@@ -141,12 +120,12 @@ SAVC(mp4a);
_rtmp = NULL;
}
[self clean];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
- (void)sendFrame:(LFFrame *)frame {
if (!frame) return;
[self.buffer appendObject:frame];
if(!self.isSending){
[self sendFrame];
}
@@ -158,75 +137,74 @@ SAVC(mp4a);
#pragma mark -- CustomMethod
- (void)sendFrame {
__weak typeof(self) _self = self;
dispatch_async(self.rtmpSendQueue, ^{
if (!_self.isSending && _self.buffer.list.count > 0) {
_self.isSending = YES;
if (!self.isSending && self.buffer.list.count > 0) {
self.isSending = YES;
if (!_self.isConnected || _self.isReconnecting || _self.isConnecting || !_rtmp){
_self.isSending = NO;
if (!_isConnected || _isReconnecting || _isConnecting || !_rtmp){
self.isSending = NO;
return;
}
//
LFFrame *frame = [_self.buffer popFirstObject];
LFFrame *frame = [self.buffer popFirstObject];
if ([frame isKindOfClass:[LFVideoFrame class]]) {
if (!_self.sendVideoHead) {
_self.sendVideoHead = YES;
if (!self.sendVideoHead) {
self.sendVideoHead = YES;
if(!((LFVideoFrame*)frame).sps || !((LFVideoFrame*)frame).pps){
_self.isSending = NO;
self.isSending = NO;
return;
}
[_self sendVideoHeader:(LFVideoFrame *)frame];
[self sendVideoHeader:(LFVideoFrame *)frame];
} else {
[_self sendVideo:(LFVideoFrame *)frame];
[self sendVideo:(LFVideoFrame *)frame];
}
} else {
if (!_self.sendAudioHead) {
_self.sendAudioHead = YES;
if (!self.sendAudioHead) {
self.sendAudioHead = YES;
if(!((LFAudioFrame*)frame).audioInfo){
_self.isSending = NO;
self.isSending = NO;
return;
}
[_self sendAudioHeader:(LFAudioFrame *)frame];
[self sendAudioHeader:(LFAudioFrame *)frame];
} else {
[_self sendAudio:frame];
[self sendAudio:frame];
}
}
//debug更新
_self.debugInfo.totalFrame++;
_self.debugInfo.dropFrame += _self.buffer.lastDropFrames;
_self.buffer.lastDropFrames = 0;
self.debugInfo.totalFrame++;
self.debugInfo.dropFrame += self.buffer.lastDropFrames;
self.buffer.lastDropFrames = 0;
_self.debugInfo.dataFlow += frame.data.length;
_self.debugInfo.elapsedMilli = CACurrentMediaTime() * 1000 - _self.debugInfo.timeStamp;
if (_self.debugInfo.elapsedMilli < 1000) {
_self.debugInfo.bandwidth += frame.data.length;
self.debugInfo.dataFlow += frame.data.length;
self.debugInfo.elapsedMilli = CACurrentMediaTime() * 1000 - self.debugInfo.timeStamp;
if (self.debugInfo.elapsedMilli < 1000) {
self.debugInfo.bandwidth += frame.data.length;
if ([frame isKindOfClass:[LFAudioFrame class]]) {
_self.debugInfo.capturedAudioCount++;
self.debugInfo.capturedAudioCount++;
} else {
_self.debugInfo.capturedVideoCount++;
self.debugInfo.capturedVideoCount++;
}
_self.debugInfo.unSendCount = _self.buffer.list.count;
self.debugInfo.unSendCount = self.buffer.list.count;
} else {
_self.debugInfo.currentBandwidth = _self.debugInfo.bandwidth;
_self.debugInfo.currentCapturedAudioCount = _self.debugInfo.capturedAudioCount;
_self.debugInfo.currentCapturedVideoCount = _self.debugInfo.capturedVideoCount;
if (_self.delegate && [_self.delegate respondsToSelector:@selector(socketDebug:debugInfo:)]) {
[_self.delegate socketDebug:_self debugInfo:_self.debugInfo];
self.debugInfo.currentBandwidth = self.debugInfo.bandwidth;
self.debugInfo.currentCapturedAudioCount = self.debugInfo.capturedAudioCount;
self.debugInfo.currentCapturedVideoCount = self.debugInfo.capturedVideoCount;
if (self.delegate && [self.delegate respondsToSelector:@selector(socketDebug:debugInfo:)]) {
[self.delegate socketDebug:self debugInfo:self.debugInfo];
}
_self.debugInfo.bandwidth = 0;
_self.debugInfo.capturedAudioCount = 0;
_self.debugInfo.capturedVideoCount = 0;
_self.debugInfo.timeStamp = CACurrentMediaTime() * 1000;
self.debugInfo.bandwidth = 0;
self.debugInfo.capturedAudioCount = 0;
self.debugInfo.capturedVideoCount = 0;
self.debugInfo.timeStamp = CACurrentMediaTime() * 1000;
}
//
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
//< sendFrame方法
_self.isSending = NO;
self.isSending = NO;
});
}
@@ -248,6 +226,18 @@ SAVC(mp4a);
- (NSInteger)RTMP264_Connect:(char *)push_url {
//timestamp是一直在累加
//
if (_isConnecting) return -1;
_isConnecting = YES;
if (self.delegate && [self.delegate respondsToSelector:@selector(socketStatus:status:)]) {
[self.delegate socketStatus:self status:LFLivePending];
}
if (_rtmp != NULL) {
PILI_RTMP_Close(_rtmp, &_error);
PILI_RTMP_Free(_rtmp);
}
_rtmp = PILI_RTMP_Alloc();
PILI_RTMP_Init(_rtmp);
@@ -262,7 +252,6 @@ SAVC(mp4a);
_rtmp->m_userData = (__bridge void *)self;
_rtmp->m_msgCounter = 1;
_rtmp->Link.timeout = RTMP_RECEIVE_TIMEOUT;
//使
PILI_RTMP_EnableWrite(_rtmp);
@@ -286,13 +275,19 @@ SAVC(mp4a);
_isConnecting = NO;
_isReconnecting = NO;
_isSending = NO;
_retryTimes4netWorkBreaken = 0;
return 0;
Failed:
PILI_RTMP_Close(_rtmp, &_error);
PILI_RTMP_Free(_rtmp);
_rtmp = NULL;
[self reconnect];
if (self.delegate && [self.delegate respondsToSelector:@selector(socketDidError:errorCode:)]) {
[self.delegate socketDidError:self errorCode:LFLiveSocketError_ConnectSocket];
}
if (self.delegate && [self.delegate respondsToSelector:@selector(socketStatus:status:)]) {
[self.delegate socketStatus:self status:LFLiveError];
}
return -1;
}
@@ -345,7 +340,7 @@ Failed:
*enc++ = 0;
*enc++ = AMF_OBJECT_END;
packet.m_nBodySize = (uint32_t)(enc - packet.m_body);
packet.m_nBodySize = enc - packet.m_body;
if (!PILI_RTMP_SendPacket(_rtmp, &packet, FALSE, &_error)) {
return;
}
@@ -484,61 +479,36 @@ Failed:
// 线
- (void)reconnect {
dispatch_async(self.rtmpSendQueue, ^{
if (self.retryTimes4netWorkBreaken++ < self.reconnectCount && !self.isReconnecting) {
self.isConnected = NO;
self.isConnecting = NO;
self.isReconnecting = YES;
dispatch_async(dispatch_get_main_queue(), ^{
[self performSelector:@selector(_reconnect) withObject:nil afterDelay:self.reconnectInterval];
});
} else if (self.retryTimes4netWorkBreaken >= self.reconnectCount) {
if (self.delegate && [self.delegate respondsToSelector:@selector(socketStatus:status:)]) {
[self.delegate socketStatus:self status:LFLiveError];
}
if (self.delegate && [self.delegate respondsToSelector:@selector(socketDidError:errorCode:)]) {
[self.delegate socketDidError:self errorCode:LFLiveSocketError_ReConnectTimeOut];
}
}
});
}
_isReconnecting = NO;
if (_isConnected) return;
- (void)_reconnect{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
_isReconnecting = NO;
if(_isConnected) return;
_isReconnecting = NO;
if (_isConnected) return;
if (_rtmp != NULL) {
PILI_RTMP_Close(_rtmp, &_error);
PILI_RTMP_Free(_rtmp);
_rtmp = NULL;
}
_sendAudioHead = NO;
_sendVideoHead = NO;
if (self.delegate && [self.delegate respondsToSelector:@selector(socketStatus:status:)]) {
[self.delegate socketStatus:self status:LFLiveRefresh];
}
if (_rtmp != NULL) {
PILI_RTMP_Close(_rtmp, &_error);
PILI_RTMP_Free(_rtmp);
}
[self RTMP264_Connect:(char *)[_stream.url cStringUsingEncoding:NSASCIIStringEncoding]];
[self _stop];
[self _start];
});
}
#pragma mark -- CallBack
void RTMPErrorCallback(RTMPError *error, void *userData) {
LFStreamRTMPSocket *socket = (__bridge LFStreamRTMPSocket *)userData;
if (error->code < 0) {
[socket reconnect];
if (socket.retryTimes4netWorkBreaken++ < socket.reconnectCount && !socket.isReconnecting) {
socket.isConnected = NO;
socket.isConnecting = NO;
socket.isReconnecting = YES;
[socket performSelectorOnMainThread:@selector(reconnect) withObject:nil waitUntilDone:socket.reconnectInterval];
} else if (socket.retryTimes4netWorkBreaken >= socket.reconnectCount) {
if (socket.delegate && [socket.delegate respondsToSelector:@selector(socketStatus:status:)]) {
[socket.delegate socketStatus:socket status:LFLiveError];
}
if (socket.delegate && [socket.delegate respondsToSelector:@selector(socketDidError:errorCode:)]) {
[socket.delegate socketDidError:socket errorCode:LFLiveSocketError_ReConnectTimeOut];
}
}
}
}
void ConnectionTimeCallback(PILI_CONNECTION_TIME *conn_time, void *userData) {
//LFStreamRTMPSocket *socket = (__bridge LFStreamRTMPSocket*)userData;
}
#pragma mark -- LFStreamingBufferDelegate
@@ -563,7 +533,6 @@ void ConnectionTimeCallback(PILI_CONNECTION_TIME *conn_time, void *userData) {
if (!_buffer) {
_buffer = [[LFStreamingBuffer alloc] init];
_buffer.delegate = self;
}
return _buffer;
}
+4 -5
View File
@@ -2,8 +2,8 @@
// LFStreamSocket.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by admin on 16/5/3.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -11,8 +11,6 @@
#import "LFStreamingBuffer.h"
#import "LFLiveDebug.h"
@protocol LFStreamSocket;
@protocol LFStreamSocketDelegate <NSObject>
@@ -34,5 +32,6 @@
- (void)setDelegate:(nullable id <LFStreamSocketDelegate>)delegate;
@optional
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream;
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream reconnectInterval:(NSInteger)reconnectInterval reconnectCount:(NSInteger)reconnectCount;
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream videoSize:(CGSize)videoSize;
- (nullable instancetype)initWithStream:(nullable LFLiveStreamInfo *)stream videoSize:(CGSize)videoSize reconnectInterval:(NSInteger)reconnectInterval reconnectCount:(NSInteger)reconnectCount;
@end
+2 -4
View File
@@ -2,15 +2,14 @@
// LFStreamingBuffer.h
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LFAudioFrame.h"
#import "LFVideoFrame.h"
/** current buffer status */
typedef NS_ENUM (NSUInteger, LFLiveBuffferState) {
LFLiveBuffferUnknown = 0, //< 未知
@@ -28,7 +27,6 @@ typedef NS_ENUM (NSUInteger, LFLiveBuffferState) {
@interface LFStreamingBuffer : NSObject
/** The delegate of the buffer. buffer callback */
@property (nullable, nonatomic, weak) id <LFStreamingBufferDelegate> delegate;
+10 -10
View File
@@ -2,14 +2,14 @@
// LFStreamingBuffer.m
// LFLiveKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by 倾慕 on 16/5/2.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "LFStreamingBuffer.h"
#import "NSMutableArray+LFAdd.h"
static const NSUInteger defaultSortBufferMaxCount = 5;///< 排序10个内
static const NSUInteger defaultSortBufferMaxCount = 10;///< 排序10个内
static const NSUInteger defaultUpdateInterval = 1;///< 更新频率为1s
static const NSUInteger defaultCallBackInterval = 5;///< 5s计时一次
static const NSUInteger defaultSendBufferMaxCount = 600;///< 最大缓冲区为600
@@ -97,14 +97,14 @@ static const NSUInteger defaultSendBufferMaxCount = 600;///< 最大缓冲区为6
[self.list removeObjectsInArray:pFrames];
return;
}
NSArray *iFrames = [self expireIFrames];///<  删除一个I帧(但一个I帧可能对应多个nal)
self.lastDropFrames += [iFrames count];
if (iFrames) {
[self.list removeObjectsInArray:iFrames];
return;
}
[self.list removeAllObjects];
}
@@ -155,9 +155,9 @@ NSInteger frameDataCompare(id obj1, id obj2, void *context){
NSInteger decreaseCount = 0;
for (NSNumber *number in self.thresholdList) {
if (number.integerValue > currentCount) {
if (number.integerValue >= currentCount) {
increaseCount++;
} else{
} else {
decreaseCount++;
}
currentCount = [number integerValue];
@@ -170,7 +170,7 @@ NSInteger frameDataCompare(id obj1, id obj2, void *context){
if (decreaseCount >= self.callBackInterval) {
return LFLiveBuffferDecline;
}
return LFLiveBuffferUnknown;
}
@@ -204,7 +204,7 @@ NSInteger frameDataCompare(id obj1, id obj2, void *context){
dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER);
[self.thresholdList addObject:@(self.list.count)];
dispatch_semaphore_signal(_lock);
if (self.currentInterval >= self.callBackInterval) {
LFLiveBuffferState state = [self currentBufferState];
if (state == LFLiveBuffferIncrease) {
@@ -222,7 +222,7 @@ NSInteger frameDataCompare(id obj1, id obj2, void *context){
}
__weak typeof(self) _self = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.updateInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
__strong typeof(_self) self = _self;
__weak typeof(_self) self = _self;
[self tick];
});
}
+2 -2
View File
@@ -2,8 +2,8 @@
// NSMutableArray+LFAdd.h
// YYKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by admin on 16/5/20.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import <Foundation/Foundation.h>
+2 -2
View File
@@ -2,8 +2,8 @@
// NSMutableArray+LFAdd.m
// YYKit
//
// Created by LaiFeng on 16/5/20.
// Copyright © 2016年 LaiFeng All rights reserved.
// Created by admin on 16/5/20.
// Copyright © 2016年 倾慕. All rights reserved.
//
#import "NSMutableArray+LFAdd.h"
+4
View File
@@ -0,0 +1,4 @@
#CocoaPods
Pods/
Podfile.lock
@@ -7,177 +7,184 @@
objects = {
/* Begin PBXBuildFile section */
84D8B42B1D75778B00752B56 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B42A1D75778B00752B56 /* main.m */; };
84D8B42E1D75778B00752B56 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B42D1D75778B00752B56 /* AppDelegate.m */; };
84D8B4311D75778B00752B56 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B4301D75778B00752B56 /* ViewController.m */; };
84D8B4341D75778B00752B56 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4321D75778B00752B56 /* Main.storyboard */; };
84D8B4361D75778B00752B56 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4351D75778B00752B56 /* Assets.xcassets */; };
84D8B4391D75778B00752B56 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4371D75778B00752B56 /* LaunchScreen.storyboard */; };
84D8B44B1D75781200752B56 /* LFLivePreview.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B44A1D75781200752B56 /* LFLivePreview.m */; };
84D8B45B1D75782700752B56 /* UIControl+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B44E1D75782700752B56 /* UIControl+YYAdd.m */; };
84D8B45C1D75782700752B56 /* UIView+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = 84D8B4501D75782700752B56 /* UIView+YYAdd.m */; };
84D8B45D1D75782700752B56 /* camra_beauty@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4521D75782700752B56 /* camra_beauty@2x.png */; };
84D8B45E1D75782700752B56 /* camra_beauty@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4531D75782700752B56 /* camra_beauty@3x.png */; };
84D8B45F1D75782700752B56 /* camra_beauty_close@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4541D75782700752B56 /* camra_beauty_close@2x.png */; };
84D8B4601D75782700752B56 /* camra_beauty_close@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4551D75782700752B56 /* camra_beauty_close@3x.png */; };
84D8B4611D75782700752B56 /* camra_preview@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4561D75782700752B56 /* camra_preview@2x.png */; };
84D8B4621D75782700752B56 /* camra_preview@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4571D75782700752B56 /* camra_preview@3x.png */; };
84D8B4631D75782700752B56 /* close_preview@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4581D75782700752B56 /* close_preview@2x.png */; };
84D8B4641D75782700752B56 /* close_preview@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B4591D75782700752B56 /* close_preview@3x.png */; };
84D8B4651D75782700752B56 /* ios-29x29.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D8B45A1D75782700752B56 /* ios-29x29.png */; };
84D8B4CF1D757F0700752B56 /* libstdc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 84D8B4CE1D757F0700752B56 /* libstdc++.tbd */; };
BC8B37EEE1CEEF9B5614DC91 /* libPods-LFLiveKitDemo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5B1CCEEE06FCFAF75D105A51 /* libPods-LFLiveKitDemo.a */; };
81E848D8BD2C446C2DD4876A /* libPods-LFLiveKitDemo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6FD9F92833FE7856CDDD3CED /* libPods-LFLiveKitDemo.a */; };
B2D23E7F1D348F3D00B34CA8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B2D23E7E1D348F3D00B34CA8 /* main.m */; };
B2D23E821D348F3D00B34CA8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B2D23E811D348F3D00B34CA8 /* AppDelegate.m */; };
B2D23E851D348F3D00B34CA8 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B2D23E841D348F3D00B34CA8 /* ViewController.m */; };
B2D23E881D348F3D00B34CA8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B2D23E861D348F3D00B34CA8 /* Main.storyboard */; };
B2D23E8D1D348F3D00B34CA8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B2D23E8B1D348F3D00B34CA8 /* LaunchScreen.storyboard */; };
B2D23EAA1D348F7100B34CA8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B2D23E941D348F7100B34CA8 /* Assets.xcassets */; };
B2D23EAB1D348F7100B34CA8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B2D23E961D348F7100B34CA8 /* LaunchScreen.storyboard */; };
B2D23EAC1D348F7100B34CA8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B2D23E981D348F7100B34CA8 /* Main.storyboard */; };
B2D23EAD1D348F7100B34CA8 /* UIControl+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = B2D23E9C1D348F7100B34CA8 /* UIControl+YYAdd.m */; };
B2D23EAE1D348F7100B34CA8 /* UIView+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = B2D23E9E1D348F7100B34CA8 /* UIView+YYAdd.m */; };
B2D23EAF1D348F7100B34CA8 /* camra_beauty@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B2D23EA01D348F7100B34CA8 /* camra_beauty@2x.png */; };
B2D23EB01D348F7100B34CA8 /* camra_beauty@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B2D23EA11D348F7100B34CA8 /* camra_beauty@3x.png */; };
B2D23EB11D348F7100B34CA8 /* camra_beauty_close@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B2D23EA21D348F7100B34CA8 /* camra_beauty_close@2x.png */; };
B2D23EB21D348F7100B34CA8 /* camra_beauty_close@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B2D23EA31D348F7100B34CA8 /* camra_beauty_close@3x.png */; };
B2D23EB31D348F7100B34CA8 /* camra_preview@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B2D23EA41D348F7100B34CA8 /* camra_preview@2x.png */; };
B2D23EB41D348F7100B34CA8 /* camra_preview@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B2D23EA51D348F7100B34CA8 /* camra_preview@3x.png */; };
B2D23EB51D348F7100B34CA8 /* close_preview@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B2D23EA61D348F7100B34CA8 /* close_preview@2x.png */; };
B2D23EB61D348F7100B34CA8 /* close_preview@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = B2D23EA71D348F7100B34CA8 /* close_preview@3x.png */; };
B2D23EB71D348F7100B34CA8 /* LFLivePreview.m in Sources */ = {isa = PBXBuildFile; fileRef = B2D23EA91D348F7100B34CA8 /* LFLivePreview.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
289A9C4510CD7EA6F4CE9897 /* Pods-LFLiveKitDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LFLiveKitDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo.debug.xcconfig"; sourceTree = "<group>"; };
5B1CCEEE06FCFAF75D105A51 /* libPods-LFLiveKitDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LFLiveKitDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
84D8B4261D75778B00752B56 /* LFLiveKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LFLiveKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
84D8B42A1D75778B00752B56 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
84D8B42C1D75778B00752B56 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
84D8B42D1D75778B00752B56 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
84D8B42F1D75778B00752B56 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
84D8B4301D75778B00752B56 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
84D8B4331D75778B00752B56 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
84D8B4351D75778B00752B56 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
84D8B4381D75778B00752B56 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
84D8B43A1D75778B00752B56 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
84D8B4491D75781200752B56 /* LFLivePreview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFLivePreview.h; sourceTree = "<group>"; };
84D8B44A1D75781200752B56 /* LFLivePreview.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFLivePreview.m; sourceTree = "<group>"; };
84D8B44D1D75782700752B56 /* UIControl+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIControl+YYAdd.h"; sourceTree = "<group>"; };
84D8B44E1D75782700752B56 /* UIControl+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIControl+YYAdd.m"; sourceTree = "<group>"; };
84D8B44F1D75782700752B56 /* UIView+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+YYAdd.h"; sourceTree = "<group>"; };
84D8B4501D75782700752B56 /* UIView+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+YYAdd.m"; sourceTree = "<group>"; };
84D8B4521D75782700752B56 /* camra_beauty@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_beauty@2x.png"; sourceTree = "<group>"; };
84D8B4531D75782700752B56 /* camra_beauty@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_beauty@3x.png"; sourceTree = "<group>"; };
84D8B4541D75782700752B56 /* camra_beauty_close@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_beauty_close@2x.png"; sourceTree = "<group>"; };
84D8B4551D75782700752B56 /* camra_beauty_close@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_beauty_close@3x.png"; sourceTree = "<group>"; };
84D8B4561D75782700752B56 /* camra_preview@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_preview@2x.png"; sourceTree = "<group>"; };
84D8B4571D75782700752B56 /* camra_preview@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_preview@3x.png"; sourceTree = "<group>"; };
84D8B4581D75782700752B56 /* close_preview@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "close_preview@2x.png"; sourceTree = "<group>"; };
84D8B4591D75782700752B56 /* close_preview@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "close_preview@3x.png"; sourceTree = "<group>"; };
84D8B45A1D75782700752B56 /* ios-29x29.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ios-29x29.png"; sourceTree = "<group>"; };
84D8B4CE1D757F0700752B56 /* libstdc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libstdc++.tbd"; path = "usr/lib/libstdc++.tbd"; sourceTree = SDKROOT; };
96E1231310083A3881AD2AB6 /* Pods-LFLiveKitDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LFLiveKitDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo.release.xcconfig"; sourceTree = "<group>"; };
6FD9F92833FE7856CDDD3CED /* libPods-LFLiveKitDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LFLiveKitDemo.a"; sourceTree = BUILT_PRODUCTS_DIR; };
8FAAEBE1A4F099C69588B394 /* Pods-LFLiveKitDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LFLiveKitDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo.release.xcconfig"; sourceTree = "<group>"; };
AFD491825C5DB2AD871189B5 /* Pods-LFLiveKitDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LFLiveKitDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo.debug.xcconfig"; sourceTree = "<group>"; };
B2D23E7A1D348F3D00B34CA8 /* LFLiveKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LFLiveKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
B2D23E7E1D348F3D00B34CA8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
B2D23E801D348F3D00B34CA8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
B2D23E811D348F3D00B34CA8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
B2D23E831D348F3D00B34CA8 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
B2D23E841D348F3D00B34CA8 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
B2D23E871D348F3D00B34CA8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
B2D23E8C1D348F3D00B34CA8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
B2D23E8E1D348F3D00B34CA8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
B2D23E941D348F7100B34CA8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
B2D23E971D348F7100B34CA8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
B2D23E991D348F7100B34CA8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Main.storyboard; sourceTree = "<group>"; };
B2D23E9B1D348F7100B34CA8 /* UIControl+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIControl+YYAdd.h"; sourceTree = "<group>"; };
B2D23E9C1D348F7100B34CA8 /* UIControl+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIControl+YYAdd.m"; sourceTree = "<group>"; };
B2D23E9D1D348F7100B34CA8 /* UIView+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+YYAdd.h"; sourceTree = "<group>"; };
B2D23E9E1D348F7100B34CA8 /* UIView+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+YYAdd.m"; sourceTree = "<group>"; };
B2D23EA01D348F7100B34CA8 /* camra_beauty@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_beauty@2x.png"; sourceTree = "<group>"; };
B2D23EA11D348F7100B34CA8 /* camra_beauty@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_beauty@3x.png"; sourceTree = "<group>"; };
B2D23EA21D348F7100B34CA8 /* camra_beauty_close@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_beauty_close@2x.png"; sourceTree = "<group>"; };
B2D23EA31D348F7100B34CA8 /* camra_beauty_close@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_beauty_close@3x.png"; sourceTree = "<group>"; };
B2D23EA41D348F7100B34CA8 /* camra_preview@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_preview@2x.png"; sourceTree = "<group>"; };
B2D23EA51D348F7100B34CA8 /* camra_preview@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "camra_preview@3x.png"; sourceTree = "<group>"; };
B2D23EA61D348F7100B34CA8 /* close_preview@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "close_preview@2x.png"; sourceTree = "<group>"; };
B2D23EA71D348F7100B34CA8 /* close_preview@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "close_preview@3x.png"; sourceTree = "<group>"; };
B2D23EA81D348F7100B34CA8 /* LFLivePreview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFLivePreview.h; sourceTree = "<group>"; };
B2D23EA91D348F7100B34CA8 /* LFLivePreview.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFLivePreview.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
84D8B4231D75778B00752B56 /* Frameworks */ = {
B2D23E771D348F3D00B34CA8 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
84D8B4CF1D757F0700752B56 /* libstdc++.tbd in Frameworks */,
BC8B37EEE1CEEF9B5614DC91 /* libPods-LFLiveKitDemo.a in Frameworks */,
81E848D8BD2C446C2DD4876A /* libPods-LFLiveKitDemo.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
65E0CF98FF954863E543A0E1 /* Frameworks */ = {
2A74A5AD65CD9450ED23C3E0 /* Pods */ = {
isa = PBXGroup;
children = (
5B1CCEEE06FCFAF75D105A51 /* libPods-LFLiveKitDemo.a */,
AFD491825C5DB2AD871189B5 /* Pods-LFLiveKitDemo.debug.xcconfig */,
8FAAEBE1A4F099C69588B394 /* Pods-LFLiveKitDemo.release.xcconfig */,
);
name = Frameworks;
name = Pods;
sourceTree = "<group>";
};
84D8B41D1D75778B00752B56 = {
B2D23E711D348F3D00B34CA8 = {
isa = PBXGroup;
children = (
84D8B4CE1D757F0700752B56 /* libstdc++.tbd */,
84D8B4281D75778B00752B56 /* LFLiveKitDemo */,
84D8B4271D75778B00752B56 /* Products */,
F3E359B8A7561F963C47A62F /* Pods */,
65E0CF98FF954863E543A0E1 /* Frameworks */,
B2D23E7C1D348F3D00B34CA8 /* LFLiveKitDemo */,
B2D23E7B1D348F3D00B34CA8 /* Products */,
2A74A5AD65CD9450ED23C3E0 /* Pods */,
E6AF2D0BFA2946745BB5F365 /* Frameworks */,
);
sourceTree = "<group>";
};
84D8B4271D75778B00752B56 /* Products */ = {
B2D23E7B1D348F3D00B34CA8 /* Products */ = {
isa = PBXGroup;
children = (
84D8B4261D75778B00752B56 /* LFLiveKitDemo.app */,
B2D23E7A1D348F3D00B34CA8 /* LFLiveKitDemo.app */,
);
name = Products;
sourceTree = "<group>";
};
84D8B4281D75778B00752B56 /* LFLiveKitDemo */ = {
B2D23E7C1D348F3D00B34CA8 /* LFLiveKitDemo */ = {
isa = PBXGroup;
children = (
84D8B42C1D75778B00752B56 /* AppDelegate.h */,
84D8B42D1D75778B00752B56 /* AppDelegate.m */,
84D8B42F1D75778B00752B56 /* ViewController.h */,
84D8B4301D75778B00752B56 /* ViewController.m */,
84D8B4491D75781200752B56 /* LFLivePreview.h */,
84D8B44A1D75781200752B56 /* LFLivePreview.m */,
84D8B44C1D75782700752B56 /* category */,
84D8B4511D75782700752B56 /* images */,
84D8B4321D75778B00752B56 /* Main.storyboard */,
84D8B4351D75778B00752B56 /* Assets.xcassets */,
84D8B4371D75778B00752B56 /* LaunchScreen.storyboard */,
84D8B43A1D75778B00752B56 /* Info.plist */,
84D8B4291D75778B00752B56 /* Supporting Files */,
B2D23E941D348F7100B34CA8 /* Assets.xcassets */,
B2D23E951D348F7100B34CA8 /* Base.lproj */,
B2D23E9A1D348F7100B34CA8 /* category */,
B2D23E9F1D348F7100B34CA8 /* images */,
B2D23EA81D348F7100B34CA8 /* LFLivePreview.h */,
B2D23EA91D348F7100B34CA8 /* LFLivePreview.m */,
B2D23E801D348F3D00B34CA8 /* AppDelegate.h */,
B2D23E811D348F3D00B34CA8 /* AppDelegate.m */,
B2D23E831D348F3D00B34CA8 /* ViewController.h */,
B2D23E841D348F3D00B34CA8 /* ViewController.m */,
B2D23E861D348F3D00B34CA8 /* Main.storyboard */,
B2D23E8B1D348F3D00B34CA8 /* LaunchScreen.storyboard */,
B2D23E8E1D348F3D00B34CA8 /* Info.plist */,
B2D23E7D1D348F3D00B34CA8 /* Supporting Files */,
);
path = LFLiveKitDemo;
sourceTree = "<group>";
};
84D8B4291D75778B00752B56 /* Supporting Files */ = {
B2D23E7D1D348F3D00B34CA8 /* Supporting Files */ = {
isa = PBXGroup;
children = (
84D8B42A1D75778B00752B56 /* main.m */,
B2D23E7E1D348F3D00B34CA8 /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
84D8B44C1D75782700752B56 /* category */ = {
B2D23E951D348F7100B34CA8 /* Base.lproj */ = {
isa = PBXGroup;
children = (
84D8B44D1D75782700752B56 /* UIControl+YYAdd.h */,
84D8B44E1D75782700752B56 /* UIControl+YYAdd.m */,
84D8B44F1D75782700752B56 /* UIView+YYAdd.h */,
84D8B4501D75782700752B56 /* UIView+YYAdd.m */,
B2D23E961D348F7100B34CA8 /* LaunchScreen.storyboard */,
B2D23E981D348F7100B34CA8 /* Main.storyboard */,
);
path = Base.lproj;
sourceTree = "<group>";
};
B2D23E9A1D348F7100B34CA8 /* category */ = {
isa = PBXGroup;
children = (
B2D23E9B1D348F7100B34CA8 /* UIControl+YYAdd.h */,
B2D23E9C1D348F7100B34CA8 /* UIControl+YYAdd.m */,
B2D23E9D1D348F7100B34CA8 /* UIView+YYAdd.h */,
B2D23E9E1D348F7100B34CA8 /* UIView+YYAdd.m */,
);
path = category;
sourceTree = "<group>";
};
84D8B4511D75782700752B56 /* images */ = {
B2D23E9F1D348F7100B34CA8 /* images */ = {
isa = PBXGroup;
children = (
84D8B4521D75782700752B56 /* camra_beauty@2x.png */,
84D8B4531D75782700752B56 /* camra_beauty@3x.png */,
84D8B4541D75782700752B56 /* camra_beauty_close@2x.png */,
84D8B4551D75782700752B56 /* camra_beauty_close@3x.png */,
84D8B4561D75782700752B56 /* camra_preview@2x.png */,
84D8B4571D75782700752B56 /* camra_preview@3x.png */,
84D8B4581D75782700752B56 /* close_preview@2x.png */,
84D8B4591D75782700752B56 /* close_preview@3x.png */,
84D8B45A1D75782700752B56 /* ios-29x29.png */,
B2D23EA01D348F7100B34CA8 /* camra_beauty@2x.png */,
B2D23EA11D348F7100B34CA8 /* camra_beauty@3x.png */,
B2D23EA21D348F7100B34CA8 /* camra_beauty_close@2x.png */,
B2D23EA31D348F7100B34CA8 /* camra_beauty_close@3x.png */,
B2D23EA41D348F7100B34CA8 /* camra_preview@2x.png */,
B2D23EA51D348F7100B34CA8 /* camra_preview@3x.png */,
B2D23EA61D348F7100B34CA8 /* close_preview@2x.png */,
B2D23EA71D348F7100B34CA8 /* close_preview@3x.png */,
);
path = images;
sourceTree = "<group>";
};
F3E359B8A7561F963C47A62F /* Pods */ = {
E6AF2D0BFA2946745BB5F365 /* Frameworks */ = {
isa = PBXGroup;
children = (
289A9C4510CD7EA6F4CE9897 /* Pods-LFLiveKitDemo.debug.xcconfig */,
96E1231310083A3881AD2AB6 /* Pods-LFLiveKitDemo.release.xcconfig */,
6FD9F92833FE7856CDDD3CED /* libPods-LFLiveKitDemo.a */,
);
name = Pods;
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
84D8B4251D75778B00752B56 /* LFLiveKitDemo */ = {
B2D23E791D348F3D00B34CA8 /* LFLiveKitDemo */ = {
isa = PBXNativeTarget;
buildConfigurationList = 84D8B43D1D75778B00752B56 /* Build configuration list for PBXNativeTarget "LFLiveKitDemo" */;
buildConfigurationList = B2D23E911D348F3D00B34CA8 /* Build configuration list for PBXNativeTarget "LFLiveKitDemo" */;
buildPhases = (
A819C09CC049A57DC5C97E12 /* 📦 Check Pods Manifest.lock */,
84D8B4221D75778B00752B56 /* Sources */,
84D8B4231D75778B00752B56 /* Frameworks */,
84D8B4241D75778B00752B56 /* Resources */,
883533331BE4DCC0DB5075CF /* 📦 Embed Pods Frameworks */,
4CC4C37B93D109913E475307 /* 📦 Copy Pods Resources */,
6A9D2ED37E623D4A31A8D2C9 /* 📦 Check Pods Manifest.lock */,
B2D23E761D348F3D00B34CA8 /* Sources */,
B2D23E771D348F3D00B34CA8 /* Frameworks */,
B2D23E781D348F3D00B34CA8 /* Resources */,
34EEB2C8F5E0D371D13B66CA /* 📦 Copy Pods Resources */,
7336E9C92EDCA6C7449F2624 /* 📦 Embed Pods Frameworks */,
);
buildRules = (
);
@@ -185,25 +192,24 @@
);
name = LFLiveKitDemo;
productName = LFLiveKitDemo;
productReference = 84D8B4261D75778B00752B56 /* LFLiveKitDemo.app */;
productReference = B2D23E7A1D348F3D00B34CA8 /* LFLiveKitDemo.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
84D8B41E1D75778B00752B56 /* Project object */ = {
B2D23E721D348F3D00B34CA8 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0730;
ORGANIZATIONNAME = admin;
ORGANIZATIONNAME = zhanqi.tv;
TargetAttributes = {
84D8B4251D75778B00752B56 = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = G497YX6CBT;
B2D23E791D348F3D00B34CA8 = {
CreatedOnToolsVersion = 7.3;
};
};
};
buildConfigurationList = 84D8B4211D75778B00752B56 /* Build configuration list for PBXProject "LFLiveKitDemo" */;
buildConfigurationList = B2D23E751D348F3D00B34CA8 /* Build configuration list for PBXProject "LFLiveKitDemo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
@@ -211,40 +217,41 @@
en,
Base,
);
mainGroup = 84D8B41D1D75778B00752B56;
productRefGroup = 84D8B4271D75778B00752B56 /* Products */;
mainGroup = B2D23E711D348F3D00B34CA8;
productRefGroup = B2D23E7B1D348F3D00B34CA8 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
84D8B4251D75778B00752B56 /* LFLiveKitDemo */,
B2D23E791D348F3D00B34CA8 /* LFLiveKitDemo */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
84D8B4241D75778B00752B56 /* Resources */ = {
B2D23E781D348F3D00B34CA8 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
84D8B45F1D75782700752B56 /* camra_beauty_close@2x.png in Resources */,
84D8B4391D75778B00752B56 /* LaunchScreen.storyboard in Resources */,
84D8B45D1D75782700752B56 /* camra_beauty@2x.png in Resources */,
84D8B4361D75778B00752B56 /* Assets.xcassets in Resources */,
84D8B4621D75782700752B56 /* camra_preview@3x.png in Resources */,
84D8B4601D75782700752B56 /* camra_beauty_close@3x.png in Resources */,
84D8B4651D75782700752B56 /* ios-29x29.png in Resources */,
84D8B4641D75782700752B56 /* close_preview@3x.png in Resources */,
84D8B4631D75782700752B56 /* close_preview@2x.png in Resources */,
84D8B4341D75778B00752B56 /* Main.storyboard in Resources */,
84D8B4611D75782700752B56 /* camra_preview@2x.png in Resources */,
84D8B45E1D75782700752B56 /* camra_beauty@3x.png in Resources */,
B2D23E8D1D348F3D00B34CA8 /* LaunchScreen.storyboard in Resources */,
B2D23EAA1D348F7100B34CA8 /* Assets.xcassets in Resources */,
B2D23EAC1D348F7100B34CA8 /* Main.storyboard in Resources */,
B2D23EAB1D348F7100B34CA8 /* LaunchScreen.storyboard in Resources */,
B2D23EB21D348F7100B34CA8 /* camra_beauty_close@3x.png in Resources */,
B2D23EAF1D348F7100B34CA8 /* camra_beauty@2x.png in Resources */,
B2D23EB61D348F7100B34CA8 /* close_preview@3x.png in Resources */,
B2D23EB41D348F7100B34CA8 /* camra_preview@3x.png in Resources */,
B2D23EB51D348F7100B34CA8 /* close_preview@2x.png in Resources */,
B2D23EB11D348F7100B34CA8 /* camra_beauty_close@2x.png in Resources */,
B2D23EB01D348F7100B34CA8 /* camra_beauty@3x.png in Resources */,
B2D23EB31D348F7100B34CA8 /* camra_preview@2x.png in Resources */,
B2D23E881D348F3D00B34CA8 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
4CC4C37B93D109913E475307 /* 📦 Copy Pods Resources */ = {
34EEB2C8F5E0D371D13B66CA /* 📦 Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -259,22 +266,7 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo-resources.sh\"\n";
showEnvVarsInLog = 0;
};
883533331BE4DCC0DB5075CF /* 📦 Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "📦 Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
A819C09CC049A57DC5C97E12 /* 📦 Check Pods Manifest.lock */ = {
6A9D2ED37E623D4A31A8D2C9 /* 📦 Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -289,45 +281,76 @@
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
7336E9C92EDCA6C7449F2624 /* 📦 Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "📦 Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-LFLiveKitDemo/Pods-LFLiveKitDemo-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
84D8B4221D75778B00752B56 /* Sources */ = {
B2D23E761D348F3D00B34CA8 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
84D8B45B1D75782700752B56 /* UIControl+YYAdd.m in Sources */,
84D8B4311D75778B00752B56 /* ViewController.m in Sources */,
84D8B45C1D75782700752B56 /* UIView+YYAdd.m in Sources */,
84D8B42E1D75778B00752B56 /* AppDelegate.m in Sources */,
84D8B44B1D75781200752B56 /* LFLivePreview.m in Sources */,
84D8B42B1D75778B00752B56 /* main.m in Sources */,
B2D23EB71D348F7100B34CA8 /* LFLivePreview.m in Sources */,
B2D23E851D348F3D00B34CA8 /* ViewController.m in Sources */,
B2D23EAD1D348F7100B34CA8 /* UIControl+YYAdd.m in Sources */,
B2D23E821D348F3D00B34CA8 /* AppDelegate.m in Sources */,
B2D23EAE1D348F7100B34CA8 /* UIView+YYAdd.m in Sources */,
B2D23E7F1D348F3D00B34CA8 /* main.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
84D8B4321D75778B00752B56 /* Main.storyboard */ = {
B2D23E861D348F3D00B34CA8 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
84D8B4331D75778B00752B56 /* Base */,
B2D23E871D348F3D00B34CA8 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
84D8B4371D75778B00752B56 /* LaunchScreen.storyboard */ = {
B2D23E8B1D348F3D00B34CA8 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
84D8B4381D75778B00752B56 /* Base */,
B2D23E8C1D348F3D00B34CA8 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
B2D23E961D348F7100B34CA8 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
B2D23E971D348F7100B34CA8 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
B2D23E981D348F7100B34CA8 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
B2D23E991D348F7100B34CA8 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
84D8B43B1D75778B00752B56 /* Debug */ = {
B2D23E8F1D348F3D00B34CA8 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
@@ -350,6 +373,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -364,14 +388,17 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
HEADER_SEARCH_PATHS = "$(inherited)";
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LIBRARY_SEARCH_PATHS = "$(inherited)";
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "$(inherited)";
SDKROOT = iphoneos;
};
name = Debug;
};
84D8B43C1D75778B00752B56 /* Release */ = {
B2D23E901D348F3D00B34CA8 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
@@ -394,6 +421,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -402,19 +430,21 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
HEADER_SEARCH_PATHS = "$(inherited)";
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LIBRARY_SEARCH_PATHS = "$(inherited)";
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_LDFLAGS = "$(inherited)";
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
84D8B43E1D75778B00752B56 /* Debug */ = {
B2D23E921D348F3D00B34CA8 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 289A9C4510CD7EA6F4CE9897 /* Pods-LFLiveKitDemo.debug.xcconfig */;
baseConfigurationReference = AFD491825C5DB2AD871189B5 /* Pods-LFLiveKitDemo.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = G497YX6CBT;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
HEADER_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = LFLiveKitDemo/Info.plist;
@@ -422,17 +452,16 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = com.youku.LaiFeng;
PRODUCT_BUNDLE_IDENTIFIER = com.gameabc.LFLiveKitDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
84D8B43F1D75778B00752B56 /* Release */ = {
B2D23E931D348F3D00B34CA8 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 96E1231310083A3881AD2AB6 /* Pods-LFLiveKitDemo.release.xcconfig */;
baseConfigurationReference = 8FAAEBE1A4F099C69588B394 /* Pods-LFLiveKitDemo.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
DEVELOPMENT_TEAM = G497YX6CBT;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
HEADER_SEARCH_PATHS = "$(inherited)";
INFOPLIST_FILE = LFLiveKitDemo/Info.plist;
@@ -440,7 +469,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
PRODUCT_BUNDLE_IDENTIFIER = com.youku.LaiFeng;
PRODUCT_BUNDLE_IDENTIFIER = com.gameabc.LFLiveKitDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
@@ -448,25 +477,25 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
84D8B4211D75778B00752B56 /* Build configuration list for PBXProject "LFLiveKitDemo" */ = {
B2D23E751D348F3D00B34CA8 /* Build configuration list for PBXProject "LFLiveKitDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
84D8B43B1D75778B00752B56 /* Debug */,
84D8B43C1D75778B00752B56 /* Release */,
B2D23E8F1D348F3D00B34CA8 /* Debug */,
B2D23E901D348F3D00B34CA8 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
84D8B43D1D75778B00752B56 /* Build configuration list for PBXNativeTarget "LFLiveKitDemo" */ = {
B2D23E911D348F3D00B34CA8 /* Build configuration list for PBXNativeTarget "LFLiveKitDemo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
84D8B43E1D75778B00752B56 /* Debug */,
84D8B43F1D75778B00752B56 /* Release */,
B2D23E921D348F3D00B34CA8 /* Debug */,
B2D23E931D348F3D00B34CA8 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 84D8B41E1D75778B00752B56 /* Project object */;
rootObject = B2D23E721D348F3D00B34CA8 /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:LFLiveKitDemo.xcodeproj">
</FileRef>
</Workspace>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -14,10 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8495F66A1DB8F14600542124"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKitFramework"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -29,6 +29,15 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
@@ -42,15 +51,16 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8495F66A1DB8F14600542124"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKitFramework"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
@@ -60,15 +70,16 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8495F66A1DB8F14600542124"
BuildableName = "LFLiveKit.framework"
BlueprintName = "LFLiveKitFramework"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>LFLiveKitDemo.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>B2D23E791D348F3D00B34CA8</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "840762EB1D07C7D0000FD0BF"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "840763041D07C7D0000FD0BF"
BuildableName = "LFLiveKitDemoTests.xctest"
BlueprintName = "LFLiveKitDemoTests"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8407630F1D07C7D0000FD0BF"
BuildableName = "LFLiveKitDemoUITests.xctest"
BlueprintName = "LFLiveKitDemoUITests"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "840762EB1D07C7D0000FD0BF"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "840762EB1D07C7D0000FD0BF"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "840762EB1D07C7D0000FD0BF"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>LFLiveKitDemo.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>840762EB1D07C7D0000FD0BF</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>840763041D07C7D0000FD0BF</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>8407630F1D07C7D0000FD0BF</key>
<dict>
<key>primary</key>
<true/>
</dict>
<key>B2D23E791D348F3D00B34CA8</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0800"
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -14,10 +14,10 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84D003751DB8FE1000560583"
BuildableName = "LFLiveKitFramework-universal"
BlueprintName = "LFLiveKitFramework-universal"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
@@ -29,6 +29,15 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
@@ -42,15 +51,16 @@
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84D003751DB8FE1000560583"
BuildableName = "LFLiveKitFramework-universal"
BlueprintName = "LFLiveKitFramework-universal"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
@@ -60,15 +70,16 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "84D003751DB8FE1000560583"
BuildableName = "LFLiveKitFramework-universal"
BlueprintName = "LFLiveKitFramework-universal"
ReferencedContainer = "container:LFLiveKit.xcodeproj">
BlueprintIdentifier = "B2D23E791D348F3D00B34CA8"
BuildableName = "LFLiveKitDemo.app"
BlueprintName = "LFLiveKitDemo"
ReferencedContainer = "container:LFLiveKitDemo.xcodeproj">
</BuildableReference>
</MacroExpansion>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>LFLiveKitDemo.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>5</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>B2D23E791D348F3D00B34CA8</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:LFLiveKitDemo.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
type = "0"
version = "2.0">
</Bucket>
@@ -2,7 +2,7 @@
// AppDelegate.h
// LFLiveKitDemo
//
// Created by admin on 16/8/30.
// Created by admin on 16/6/8.
// Copyright © 2016年 admin. All rights reserved.
//
@@ -2,11 +2,12 @@
// AppDelegate.m
// LFLiveKitDemo
//
// Created by admin on 16/8/30.
// Created by admin on 16/6/8.
// Copyright © 2016 admin. All rights reserved.
//
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@@ -17,9 +18,17 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
// nav.navigationBarHidden = YES;
self.window.rootViewController = [[ViewController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
@@ -29,6 +29,41 @@
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "83.5x83.5",
"scale" : "2x"
}
],
"info" : {

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

@@ -22,20 +22,26 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>NSCameraUsageDescription</key>
<string>cameraDesciption</string>
<key>NSMicrophoneUsageDescription</key>
<string>microphoneDesciption</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
@@ -9,7 +9,7 @@
#import "LFLivePreview.h"
#import "UIControl+YYAdd.h"
#import "UIView+YYAdd.h"
#import "LFLiveKit.h"
#import "LFLiveSession.h"
inline static NSString *formatedSpeed(float bytes, float elapsed_milli) {
if (elapsed_milli <= 0) {
@@ -156,17 +156,7 @@ inline static NSString *formatedSpeed(float bytes, float elapsed_milli) {
/***  默认分辨率368 640 音频:44.1 iphone6以上48 双声道 方向竖屏 ***/
LFLiveVideoConfiguration *videoConfiguration = [LFLiveVideoConfiguration new];
videoConfiguration.videoSize = CGSizeMake(640, 360);
videoConfiguration.videoBitRate = 800*1024;
videoConfiguration.videoMaxBitRate = 1000*1024;
videoConfiguration.videoMinBitRate = 500*1024;
videoConfiguration.videoFrameRate = 24;
videoConfiguration.videoMaxKeyframeInterval = 48;
videoConfiguration.outputImageOrientation = UIInterfaceOrientationLandscapeLeft;
videoConfiguration.autorotate = NO;
videoConfiguration.sessionPreset = LFCaptureSessionPreset720x1280;
_session = [[LFLiveSession alloc] initWithAudioConfiguration:[LFLiveAudioConfiguration defaultConfiguration] videoConfiguration:videoConfiguration captureType:LFLiveCaptureDefaultMask];
_session = [[LFLiveSession alloc] initWithAudioConfiguration:[LFLiveAudioConfiguration defaultConfiguration] videoConfiguration:[LFLiveVideoConfiguration defaultConfigurationForQuality:LFLiveVideoQuality_Medium3 landscape:NO]];
/**   自己定制单声道 */
/*
@@ -223,8 +213,8 @@ inline static NSString *formatedSpeed(float bytes, float elapsed_milli) {
videoConfiguration.videoMinBitRate = 500*1024;
videoConfiguration.videoFrameRate = 15;
videoConfiguration.videoMaxKeyframeInterval = 30;
videoConfiguration.landscape = NO;
videoConfiguration.sessionPreset = LFCaptureSessionPreset360x640;
videoConfiguration.orientation = UIInterfaceOrientationPortrait;
videoConfiguration.sessionPreset = LFCaptureSessionPreset720x1280;
_session = [[LFLiveSession alloc] initWithAudioConfiguration:audioConfiguration videoConfiguration:videoConfiguration];
*/
@@ -249,26 +239,11 @@ inline static NSString *formatedSpeed(float bytes, float elapsed_milli) {
videoConfiguration.sessionPreset = LFCaptureSessionPreset720x1280;
_session = [[LFLiveSession alloc] initWithAudioConfiguration:audioConfiguration videoConfiguration:videoConfiguration];
*/
*/
_session.delegate = self;
_session.showDebugInfo = NO;
_session.preView = self;
/*本地存储*/
// _session.saveLocalVideo = YES;
// NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/Movie.mp4"];
// unlink([pathToMovie UTF8String]); // If a file already exists, AVAssetWriter won't let you record new frames, so delete the old movie
// NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
// _session.saveLocalVideoPath = movieURL;
/*
UIImageView *imageView = [[UIImageView alloc] init];
imageView.alpha = 0.8;
imageView.frame = CGRectMake(100, 100, 29, 29);
imageView.image = [UIImage imageNamed:@"ios-29x29"];
_session.warterMarkView = imageView;*/
}
return _session;
}
@@ -329,8 +304,8 @@ inline static NSString *formatedSpeed(float bytes, float elapsed_milli) {
_beautyButton = [UIButton new];
_beautyButton.size = CGSizeMake(44, 44);
_beautyButton.origin = CGPointMake(_cameraButton.left - 10 - _beautyButton.width, 20);
[_beautyButton setImage:[UIImage imageNamed:@"camra_beauty"] forState:UIControlStateNormal];
[_beautyButton setImage:[UIImage imageNamed:@"camra_beauty_close"] forState:UIControlStateSelected];
[_beautyButton setImage:[UIImage imageNamed:@"camra_beauty"] forState:UIControlStateSelected];
[_beautyButton setImage:[UIImage imageNamed:@"camra_beauty_close"] forState:UIControlStateNormal];
_beautyButton.exclusiveTouch = YES;
__weak typeof(self) _self = self;
[_beautyButton addBlockForControlEvents:UIControlEventTouchUpInside block:^(id sender) {
@@ -359,7 +334,7 @@ inline static NSString *formatedSpeed(float bytes, float elapsed_milli) {
if (_self.startLiveButton.selected) {
[_self.startLiveButton setTitle:@"结束直播" forState:UIControlStateNormal];
LFLiveStreamInfo *stream = [LFLiveStreamInfo new];
stream.url = @"rtmp://live.hkstv.hk.lxdns.com:1935/live/stream153";
stream.url = @"rtmp://live.hkstv.hk.lxdns.com:1935/live/stream123";
[_self.session startLive:stream];
} else {
[_self.startLiveButton setTitle:@"开始直播" forState:UIControlStateNormal];
@@ -2,7 +2,7 @@
// ViewController.h
// LFLiveKitDemo
//
// Created by admin on 16/8/30.
// Created by admin on 16/6/8.
// Copyright © 2016年 admin. All rights reserved.
//
@@ -1,19 +1,19 @@
//
// SecondViewController.m
// LFLiveKitFrameworkDemo
// ViewController.m
// LFLiveKitDemo
//
// Created by admin on 2016/10/20.
// Created by admin on 16/6/8.
// Copyright © 2016 admin. All rights reserved.
//
#import "SecondViewController.h"
#import "ViewController.h"
#import "LFLivePreview.h"
@interface SecondViewController ()
@interface ViewController ()
@end
@implementation SecondViewController
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
@@ -21,6 +21,10 @@
[self.view addSubview:[[LFLivePreview alloc] initWithFrame:self.view.bounds]];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
@@ -30,5 +34,4 @@
return YES;
}
@end
@@ -17,13 +17,13 @@
Create a snapshot image of the complete view hierarchy.
This method should be called in main thread.
*/
- (nullable UIImage *)snapshotImage;
- (UIImage *)snapshotImage;
/**
Create a snapshot PDF of the complete view hierarchy.
This method should be called in main thread.
*/
- (nullable NSData *)snapshotPDF;
- (NSData *)snapshotPDF;
/**
Shortcut to set the view.layer's shadow
@@ -32,13 +32,13 @@
@param offset Shadow offset
@param radius Shadow radius
*/
- (void)setLayerShadow:(nullable UIColor*)color offset:(CGSize)offset radius:(CGFloat)radius;
- (void)setLayerShadow:(UIColor*)color offset:(CGSize)offset radius:(CGFloat)radius;
/**
* liyuan+
*/
- (void) makeInsetShadow;
- (void) makeInsetShadowWithRadius:(float)radius Alpha:(float)alpha;
- (void) makeInsetShadowWithRadius:(float)radius Color:(nullable UIColor *)color Directions:(nullable NSArray *)directions;
- (void) makeInsetShadowWithRadius:(float)radius Color:(UIColor *)color Directions:(NSArray *)directions;
/**
Remove all subviews.
@@ -50,7 +50,7 @@
/**
Returns the view's view controller (may be nil).
*/
@property (nonatomic, readonly,nullable) UIViewController *viewController;
@property (nonatomic, readonly) UIViewController *viewController;
@property (nonatomic) CGFloat left; ///< Shortcut for frame.origin.x.
@property (nonatomic) CGFloat top; ///< Shortcut for frame.origin.y
@@ -78,7 +78,7 @@
If view is nil, this method instead converts to window base coordinates.
@return The point converted to the coordinate system of view.
*/
- (CGPoint)convertPoint:(CGPoint)point toViewOrWindow:(nullable UIView *)view;
- (CGPoint)convertPoint:(CGPoint)point toViewOrWindow:(UIView *)view;
/**
Converts a point from the coordinate system of a given view or window to that of the receiver.
@@ -88,7 +88,7 @@
If view is nil, this method instead converts from window base coordinates.
@return The point converted to the local coordinate system (bounds) of the receiver.
*/
- (CGPoint)convertPoint:(CGPoint)point fromViewOrWindow:(nullable UIView *)view;
- (CGPoint)convertPoint:(CGPoint)point fromViewOrWindow:(UIView *)view;
/**
Converts a rectangle from the receiver's coordinate system to that of another view or window.
@@ -97,7 +97,7 @@
@param view The view or window that is the target of the conversion operation. If view is nil, this method instead converts to window base coordinates.
@return The converted rectangle.
*/
- (CGRect)convertRect:(CGRect)rect toViewOrWindow:(nullable UIView *)view;
- (CGRect)convertRect:(CGRect)rect toViewOrWindow:(UIView *)view;
/**
Converts a rectangle from the coordinate system of another view or window to that of the receiver.
@@ -107,7 +107,7 @@
If view is nil, this method instead converts from window base coordinates.
@return The converted rectangle.
*/
- (CGRect)convertRect:(CGRect)rect fromViewOrWindow:(nullable UIView *)view;
- (CGRect)convertRect:(CGRect)rect fromViewOrWindow:(UIView *)view;
/**
* Objc
@@ -128,5 +128,5 @@
- (void)removeAllGesturesWithSubViews;
/// 在 block 内禁用动画
+ (void)disableAnimationWithBlock:(nullable void (^)(void))block;
+ (void)disableAnimationWithBlock:(void (^)(void))block;
@end

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Before

Width:  |  Height:  |  Size: 907 B

After

Width:  |  Height:  |  Size: 907 B

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -2,7 +2,7 @@
// main.m
// LFLiveKitDemo
//
// Created by admin on 16/8/30.
// Created by admin on 16/6/8.
// Copyright © 2016 admin. All rights reserved.
//
+3 -2
View File
@@ -1,6 +1,7 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios,'7.0'
target LFLiveKitDemo do
pod 'LFLiveKit', :path => '../../.'
target 'LFLiveKitDemo' do
pod 'LFLiveKit', path: '../'
end
+4
View File
@@ -0,0 +1,4 @@
#CocoaPods
Pods/
Podfile.lock

Some files were not shown because too many files have changed in this diff Show More