提交 58f51ab0 编写于 作者: 杨时权

【需求】提交编码代码。

上级 8a373ef9
......@@ -20,9 +20,11 @@
A2847D7B26CF9E6500AF0E60 /* Author.m in Sources */ = {isa = PBXBuildFile; fileRef = A2847D7A26CF9E6500AF0E60 /* Author.m */; };
A2847D8626CFB6BC00AF0E60 /* LWCheckBoxView.m in Sources */ = {isa = PBXBuildFile; fileRef = A2847D8526CFB6BC00AF0E60 /* LWCheckBoxView.m */; };
A2847DB726D0BE1100AF0E60 /* LWCheckBoxButton.m in Sources */ = {isa = PBXBuildFile; fileRef = A2847DB626D0BE1100AF0E60 /* LWCheckBoxButton.m */; };
A2847DBC26D0C7DA00AF0E60 /* LWEncoderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = A2847DBB26D0C7DA00AF0E60 /* LWEncoderConfig.m */; };
A2847DBC26D0C7DA00AF0E60 /* LWVideoEncoderConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = A2847DBB26D0C7DA00AF0E60 /* LWVideoEncoderConfig.m */; };
A2847DC326D1FC2800AF0E60 /* LWVideoCaptureSession.m in Sources */ = {isa = PBXBuildFile; fileRef = A2847DC226D1FC2800AF0E60 /* LWVideoCaptureSession.m */; };
A2847DC826D1FCF000AF0E60 /* LWVideoCaptureConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = A2847DC726D1FCF000AF0E60 /* LWVideoCaptureConfig.m */; };
A2847DF626D3849600AF0E60 /* LWVideoEncoder.m in Sources */ = {isa = PBXBuildFile; fileRef = A2847DF526D3849500AF0E60 /* LWVideoEncoder.m */; };
A2847DFC26D387AC00AF0E60 /* LWVideoOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = A2847DFB26D387AC00AF0E60 /* LWVideoOptions.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
......@@ -49,12 +51,17 @@
A2847D8526CFB6BC00AF0E60 /* LWCheckBoxView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LWCheckBoxView.m; sourceTree = "<group>"; };
A2847DB526D0BDF400AF0E60 /* LWCheckBoxButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LWCheckBoxButton.h; sourceTree = "<group>"; };
A2847DB626D0BE1100AF0E60 /* LWCheckBoxButton.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LWCheckBoxButton.m; sourceTree = "<group>"; };
A2847DBA26D0C7C500AF0E60 /* LWEncoderConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LWEncoderConfig.h; sourceTree = "<group>"; };
A2847DBB26D0C7DA00AF0E60 /* LWEncoderConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LWEncoderConfig.m; sourceTree = "<group>"; };
A2847DBA26D0C7C500AF0E60 /* LWVideoEncoderConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LWVideoEncoderConfig.h; sourceTree = "<group>"; };
A2847DBB26D0C7DA00AF0E60 /* LWVideoEncoderConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LWVideoEncoderConfig.m; sourceTree = "<group>"; };
A2847DC126D1F83600AF0E60 /* LWVideoCaptureSession.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LWVideoCaptureSession.h; sourceTree = "<group>"; };
A2847DC226D1FC2800AF0E60 /* LWVideoCaptureSession.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LWVideoCaptureSession.m; sourceTree = "<group>"; };
A2847DC626D1FCE400AF0E60 /* LWVideoCaptureConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LWVideoCaptureConfig.h; sourceTree = "<group>"; };
A2847DC726D1FCF000AF0E60 /* LWVideoCaptureConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LWVideoCaptureConfig.m; sourceTree = "<group>"; };
A2847DF426D3848A00AF0E60 /* LWVideoEncoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LWVideoEncoder.h; sourceTree = "<group>"; };
A2847DF526D3849500AF0E60 /* LWVideoEncoder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LWVideoEncoder.m; sourceTree = "<group>"; };
A2847DFA26D3879E00AF0E60 /* LWVideoOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LWVideoOptions.h; sourceTree = "<group>"; };
A2847DFB26D387AC00AF0E60 /* LWVideoOptions.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LWVideoOptions.m; sourceTree = "<group>"; };
A2847E0026D38BF200AF0E60 /* LWAVConstValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LWAVConstValue.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -123,10 +130,12 @@
children = (
A2847D7926CF9E5900AF0E60 /* Author.h */,
A2847D7A26CF9E6500AF0E60 /* Author.m */,
A2847DBA26D0C7C500AF0E60 /* LWEncoderConfig.h */,
A2847DBB26D0C7DA00AF0E60 /* LWEncoderConfig.m */,
A2847DBA26D0C7C500AF0E60 /* LWVideoEncoderConfig.h */,
A2847DBB26D0C7DA00AF0E60 /* LWVideoEncoderConfig.m */,
A2847DC626D1FCE400AF0E60 /* LWVideoCaptureConfig.h */,
A2847DC726D1FCF000AF0E60 /* LWVideoCaptureConfig.m */,
A2847DFA26D3879E00AF0E60 /* LWVideoOptions.h */,
A2847DFB26D387AC00AF0E60 /* LWVideoOptions.m */,
);
path = Model;
sourceTree = "<group>";
......@@ -147,6 +156,9 @@
children = (
A2847DC126D1F83600AF0E60 /* LWVideoCaptureSession.h */,
A2847DC226D1FC2800AF0E60 /* LWVideoCaptureSession.m */,
A2847DF426D3848A00AF0E60 /* LWVideoEncoder.h */,
A2847DF526D3849500AF0E60 /* LWVideoEncoder.m */,
A2847E0026D38BF200AF0E60 /* LWAVConstValue.h */,
);
path = AVFoundation;
sourceTree = "<group>";
......@@ -223,6 +235,7 @@
files = (
A2847D8626CFB6BC00AF0E60 /* LWCheckBoxView.m in Sources */,
A2847DC326D1FC2800AF0E60 /* LWVideoCaptureSession.m in Sources */,
A2847DFC26D387AC00AF0E60 /* LWVideoOptions.m in Sources */,
A2847B9626CE7B1D00AF0E60 /* ViewController.m in Sources */,
A2847B9026CE7B1D00AF0E60 /* AppDelegate.m in Sources */,
A2847D7B26CF9E6500AF0E60 /* Author.m in Sources */,
......@@ -230,9 +243,10 @@
A2847BA126CE7B1F00AF0E60 /* main.m in Sources */,
A2847D7026CF5B3700AF0E60 /* HomeViewController.m in Sources */,
A2847B9326CE7B1D00AF0E60 /* SceneDelegate.m in Sources */,
A2847DBC26D0C7DA00AF0E60 /* LWEncoderConfig.m in Sources */,
A2847DBC26D0C7DA00AF0E60 /* LWVideoEncoderConfig.m in Sources */,
A2847DB726D0BE1100AF0E60 /* LWCheckBoxButton.m in Sources */,
A2847D7526CF9DD700AF0E60 /* CaptureViewController.m in Sources */,
A2847DF626D3849600AF0E60 /* LWVideoEncoder.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
#ifndef LWAVConstValue_h
#define LWAVConstValue_h
typedef NS_ENUM(NSUInteger, AVPixelBufferType) {
kAVCaptureOutputPixelBufferType_420v = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
kAVCaptureOutputPixelBufferType_420f = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
kAVCaptureOutputPixelBufferType_bgra = kCVPixelFormatType_32BGRA,
};
#endif /* LWAVConstValue_h */
#ifndef LWVideoEncoder_h
#define LWVideoEncoder_h
#import <AVFoundation/AVFoundation.h>
#import <VideoToolbox/VideoToolbox.h>
#import "LWVideoEncoderConfig.h"
typedef NS_ENUM(NSUInteger, LWVideoEncodeStatus) {
kLWVideoEncodeStatus_Success,
kLWVideoEncodeStatus_Err_Create,
kLWVideoEncodeStatus_Err_Config,
kLWVideoEncodeStatus_Err_Encode,
kLWVideoEncodeStatus_Err_NO_Support,
kLWVideoEncodeStatus_Err_NO_Initialized,
kLWVideoEncodeStatus_Err_Invalid_Input,
};
@protocol LWVideoEncoderDelegate <NSObject>
@required
- (void)onDidEncoded:(OSStatus)status
sourceFrameRef:(void*)sourceFrameRef
info:(VTEncodeInfoFlags)infoFlags
sampleBuffer:(CMSampleBufferRef)sampleBuffer;
@end
@interface LWVideoEncoder : NSObject
@property (strong, readonly, nonatomic) LWVideoEncoderConfig* config;
@property (weak, nonatomic) id<LWVideoEncoderDelegate> delegate;
+ (instancetype)newVideoEncoder:(LWVideoEncoderConfig*)config;
- (instancetype)initWithConfig:(LWVideoEncoderConfig*)config;
- (LWVideoEncodeStatus)encode:(CMSampleBufferRef)sampleBuffer sourceFrameRef:(void*)sourceFrameRef;
- (LWVideoEncodeStatus)reconfig:(LWVideoEncoderConfig*)config;
- (LWVideoEncodeStatus)setOptionWithInt32:(NSString*)key value:(int32_t)value;
- (LWVideoEncodeStatus)getOptionWithInt32:(NSString*)key value:(int32_t*)value;
@end
#endif /* LWVideoEncoder_h */
#import <Foundation/Foundation.h>
#import "LWVideoEncoder.h"
@interface LWVideoEncoder ()
{
VTCompressionSessionRef _encoderSession;
}
@end
@implementation LWVideoEncoder
void compressSessionOutputCallback(void *opaque,
void *sourceFrameRef,
OSStatus compressStatus,
VTEncodeInfoFlags infoFlags,
CMSampleBufferRef sampleBuf) {
LWVideoEncoder* encoder = (__bridge LWVideoEncoder*)opaque;
if (encoder && [encoder respondsToSelector:@selector(compressOutptuCallBack:status:info:sampleBuffer:)]) {
[encoder compressOutptuCallBack:sourceFrameRef status:compressStatus info:infoFlags sampleBuffer:sampleBuf];
}
}
+ (instancetype)newVideoEncoder:(LWVideoEncoderConfig*)config {
return [[LWVideoEncoder alloc] initWithConfig:config];
}
- (instancetype)initWithConfig:(LWVideoEncoderConfig*)config {
if (self = [super init]) {
if ([self createSession:config] != kLWVideoEncodeStatus_Success) {
return nil;
}
}
NSLog(@"%s:%d %@", __func__, __LINE__, self.config);
return self;
}
- (LWVideoEncodeStatus)encode:(CMSampleBufferRef)sampleBuffer sourceFrameRef:(void*)sourceFrameRef {
if (!sampleBuffer) {
return kLWVideoEncodeStatus_Err_Invalid_Input;
}
if (!_encoderSession) {
return kLWVideoEncodeStatus_Err_NO_Initialized;
}
CMTime pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
CMTime duration = CMSampleBufferGetDuration(sampleBuffer);
CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
VTEncodeInfoFlags infoFlags = 0;
OSStatus status = VTCompressionSessionEncodeFrame(_encoderSession, pixelBuffer, pts, duration, nil, sourceFrameRef, &infoFlags);
if (status != kCVReturnSuccess) {
if (status == kVTInvalidSessionErr) {
[self destroySession];
[self createSession:self.config];
}
return kLWVideoEncodeStatus_Err_Encode;
}
return kLWVideoEncodeStatus_Success;
}
- (void)dealloc {
[self destroySession];
}
#pragma mark private
- (LWVideoEncodeStatus)createSession:(LWVideoEncoderConfig*)config {
_config = config;
OSStatus status = 0;
// 生成相对应的sourceAttributes,用于配置编码器的ioSurface属性和输入文件格式。
long pixelBufferType = self.config.pixelBufferType;
CFDictionaryRef ioSurfaceValue = CFDictionaryCreate(kCFAllocatorDefault,
nil,
nil,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFTypeRef pixelBufferFormatValue = (__bridge CFTypeRef)@(pixelBufferType);
CFTypeRef keys[3] = {
kCVPixelBufferOpenGLESCompatibilityKey, kCVPixelBufferIOSurfacePropertiesKey, kCVPixelBufferPixelFormatTypeKey
};
CFTypeRef values[3] = {
kCFBooleanTrue, ioSurfaceValue, pixelBufferFormatValue
};
CFDictionaryRef sourceAttributes = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (ioSurfaceValue) {
CFRelease(ioSurfaceValue);
ioSurfaceValue = nil;
}
status = VTCompressionSessionCreate(nil,
self.config.width,
self.config.height,
self.config.codecType,
0,
sourceAttributes,
0,
compressSessionOutputCallback,
(__bridge void * _Nullable)(self),
&_encoderSession);
if (sourceAttributes) {
CFRelease(sourceAttributes);
sourceAttributes = nil;
}
if (status != kCVReturnSuccess) {
return kLWVideoEncodeStatus_Err_Create;
}
LWVideoEncodeStatus result = [self configEncoder];
return result;
}
- (void)destroySession {
if (_encoderSession) {
VTCompressionSessionCompleteFrames(_encoderSession, kCMTimeInvalid);
VTCompressionSessionInvalidate(_encoderSession);
CFRelease(_encoderSession);
_encoderSession = nil;
}
NSLog(@"%s:%d", __func__, __LINE__);
}
- (LWVideoEncodeStatus)configEncoder {
LWVideoEncodeStatus status = kLWVideoEncodeStatus_Success;
if ((status = [self chooseProfileToEncoder]) != kLWVideoEncodeStatus_Success) {
return status;
}
// 设置实时编码,打开,编码在低码率的情况下会有画质的亏损,严重情况下会出现马赛克,
// 不开启,编码在低码率的情况下依旧能保持一部分良好画质,但是会影响延时。
VTSessionSetProperty(_encoderSession, kVTCompressionPropertyKey_RealTime, self.config.useRealTime ? kCFBooleanTrue : kCFBooleanFalse);
// 是否使用B帧编码,打开,则使用,关闭,则不使用。
VTSessionSetProperty(_encoderSession, kVTCompressionPropertyKey_AllowFrameReordering, self.config.allowFrameReordering ? kCFBooleanTrue : kCFBooleanFalse);
// 只允许I帧编码,打开,则只会编码I帧,关闭,则会根据情况编码P帧和B帧。
VTSessionSetProperty(_encoderSession, kVTCompressionPropertyKey_AllowTemporalCompression, self.config.allowTemporalCompression ? kCFBooleanTrue : kCFBooleanFalse);
// 设置编码GOP大小
int value = self.config.keyFrameInterval * self.config.framePerSecond;
VTSessionSetProperty(_encoderSession, kVTCompressionPropertyKey_MaxKeyFrameInterval, (__bridge CFTypeRef)@(value));
// 设置I帧的最大间隔,则value秒后必有一个I帧
value = self.config.keyFrameInterval;
VTSessionSetProperty(_encoderSession, kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, (__bridge CFTypeRef)@(value));
[self setBitrate:self.config.bitrate];
return kLWVideoEncodeStatus_Success;
}
- (LWVideoEncodeStatus)chooseProfileToEncoder {
CFStringRef profileStr = NULL;
OSStatus status = noErr;
if (self.config.codecType == kCMVideoCodecType_H264) {
profileStr = kVTProfileLevel_H264_Baseline_AutoLevel;
} else if (self.config.codecType == kCMVideoCodecType_HEVC) {
if (@available(iOS 11.0, *)) {
profileStr = kVTProfileLevel_HEVC_Main_AutoLevel;
}
}
if (profileStr == nil) {
return kLWVideoEncodeStatus_Err_NO_Support;
}
status = VTSessionSetProperty(_encoderSession, kVTCompressionPropertyKey_ProfileLevel, profileStr);
if (status != kCVReturnSuccess) {
return kLWVideoEncodeStatus_Err_Config;
}
NSLog(@"%s:%d choose encoder with profile(%s)", __func__, __LINE__, CFStringGetCStringPtr(profileStr, kCFStringEncodingUTF8));
return kLWVideoEncodeStatus_Success;
}
- (void)setBitrate:(int)bitrate {
bitrate = bitrate * 1024;
VTSessionSetProperty(_encoderSession, kVTCompressionPropertyKey_AverageBitRate, (__bridge CFTypeRef)@(bitrate));
}
#pragma mark callback
- (void)compressOutptuCallBack:(void*)sourceFrameRef status:(OSStatus)status info:(VTEncodeInfoFlags)info sampleBuffer:(CMSampleBufferRef)sampleBuffer {
if (self.delegate && [self.delegate respondsToSelector:@selector(onDidEncoded:sourceFrameRef:info:sampleBuffer:)]) {
[self.delegate onDidEncoded:status sourceFrameRef:sourceFrameRef info:info sampleBuffer:sampleBuffer];
}
}
@end
......@@ -2,12 +2,7 @@
#define LWCaptureConfig_h
#import <AVFoundation/AVFoundation.h>
typedef NS_ENUM(NSUInteger, AVCaptureOutputPixelBufferType) {
kAVCaptureOutputPixelBufferType_420v = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
kAVCaptureOutputPixelBufferType_420f = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
kAVCaptureOutputPixelBufferType_bgra = kCVPixelFormatType_32BGRA,
};
#import "LWAVConstValue.h"
@interface LWVideoCaptureConfig : NSObject
......@@ -18,7 +13,7 @@ typedef NS_ENUM(NSUInteger, AVCaptureOutputPixelBufferType) {
@property (assign, nonatomic) AVCaptureDevicePosition position;
// 指定输出的编码格式,有可能不支持
@property (assign, nonatomic) AVCaptureOutputPixelBufferType pixelBufferType;
@property (assign, nonatomic) AVPixelBufferType pixelBufferType;
// 视频的方向
@property (assign, nonatomic) AVCaptureVideoOrientation orientation;
......
#ifndef LWEncoderConfig_h
#define LWEncoderConfig_h
@interface LWEncoderConfig : NSObject
#import <VideoToolbox/VideoToolbox.h>
#import "LWAVConstValue.h"
@interface LWVideoEncoderConfig : NSObject
// 启用相关编码,例如kCMVideoCodecType_H264或者kCMVideoCodecType_HEVC
@property (assign, nonatomic) CMVideoCodecType codecType;
// 视频的宽
@property (assign, nonatomic) int width;
......@@ -27,6 +33,9 @@
// 是否开启P帧
@property (assign, nonatomic) BOOL allowTemporalCompression;
// 指定编码器的输入格式,必须与输入保持一致
@property (assign, nonatomic) AVPixelBufferType pixelBufferType;
+ (instancetype)defaultConfig;
- (instancetype)init;
......
#import <Foundation/Foundation.h>
#import "LWEncoderConfig.h"
#import "LWVideoEncoderConfig.h"
@interface LWEncoderConfig ()
@interface LWVideoEncoderConfig ()
@end
@implementation LWEncoderConfig
@implementation LWVideoEncoderConfig
+ (instancetype)defaultConfig {
LWEncoderConfig* config = [LWEncoderConfig new];
LWVideoEncoderConfig* config = [LWVideoEncoderConfig new];
config.allowFrameReordering = YES;
config.allowTemporalCompression = YES;
config.useRealTime = NO;
config.keyFrameInterval = 3;
config.codecType = kCMVideoCodecType_H264;
return config;
}
- (instancetype)init {
if (self = [super init]) {
}
return self;
}
- (NSString*)description {
return [NSString stringWithFormat:@"config{width:%d,height:%d,fps:%d,bitrate:%d,keyFrameInterval:%d,useRealTime:%d,allowFrameReordering:%d,allowTemporalCompression:%d}", self.width, self.height, self.framePerSecond, self.bitrate, self.keyFrameInterval, self.useRealTime, self.allowFrameReordering, self.allowTemporalCompression];;
}
@end
#ifndef LWVideoOptions_h
#define LWVideoOptions_h
extern const NSString* kLWVideoOptions_Width;
extern const NSString* kLWVideoOptions_Height;
extern const NSString* kLWVideoOptions_Bitrate;
extern const NSString* kLWVideoOptions_FramePerSecond;
extern const NSString* kLWVideoEncoderOptions_ForceKeyFrame;
#endif /* LWVideoEncoderOptions_h */
#import <Foundation/Foundation.h>
#import "LWVideoOptions.h"
const NSString* kLWVideoOptions_Width = @"kLWVideoOptions_Width";
const NSString* kLWVideoOptions_Height = @"kLWVideoOptions_Height";
const NSString* kLWVideoOptions_Bitrate = @"kLWVideoOptions_Bitrate";
const NSString* kLWVideoOptions_FramePerSecond = @"kLWVideoOptions_FramePerSecond";
const NSString* kLWVideoEncoderOptions_ForceKeyFrame = @"kLWVideoEncoderOptions_ForceKeyFrame";
......@@ -3,8 +3,9 @@
#import "CaptureViewController.h"
#import "LWCheckBoxView.h"
#import "LWVideoCaptureSession.h"
#import "LWVideoEncoder.h"
@interface CaptureViewController () <LWVideoCaptureSessionDelegate, LWCheckBoxViewDelegate>
@interface CaptureViewController () <LWVideoCaptureSessionDelegate, LWCheckBoxViewDelegate, LWVideoEncoderDelegate>
@property (strong, nonatomic) UIView* displayView;
@property (strong, nonatomic) LWCheckBoxView* checkBoxView;
@property (strong, nonatomic) UILabel* captureTypeLabel;
......@@ -13,6 +14,11 @@
@property (strong, nonatomic) LWVideoCaptureConfig* captureSessionConfig;
@property (strong, nonatomic) LWVideoCaptureSession* captureSession;
@property (strong, nonatomic) LWVideoEncoderConfig* encoderConfig;
@property (strong, nonatomic) LWVideoEncoder* encoder;
@property (strong, nonatomic) UIColor* hatsuneMiKuColor;
@end
@implementation CaptureViewController
......@@ -22,6 +28,7 @@
int displayViewY = 20;
int displayViewW = [UIScreen mainScreen].bounds.size.width;
int displayViewH = displayViewW / 16 * 9;
self.hatsuneMiKuColor = [UIColor colorWithRed:(0x39 * 1.0 / 0xff) green:(0xc5 * 1.0 / 0xff) blue:(0xbb * 1.0 / 0xff) alpha:1.0];
self.displayView = [[UIView alloc] initWithFrame:CGRectMake(displayViewX, displayViewY, displayViewW, displayViewH)];
self.displayView.backgroundColor = [UIColor blackColor];
[self.view addSubview:self.displayView];
......@@ -49,17 +56,27 @@
// self.startBtn.enabled = YES;
[self.startBtn setTitle:@"start" forState:UIControlStateNormal];
[self.startBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.startBtn setBackgroundColor:[UIColor whiteColor]];
[self.startBtn setBackgroundColor:self.hatsuneMiKuColor];
[self.startBtn addTarget:self action:@selector(startSender:) forControlEvents:UIControlEventTouchUpInside];
[self.startBtn.layer setMasksToBounds:YES];
[self.startBtn.layer setCornerRadius:4.0];
[self.startBtn.layer setBorderWidth:1.0];
[self.startBtn.layer setBorderColor:[UIColor blackColor].CGColor];
[self.view addSubview:self.startBtn];
self.stopBtn = [[UIButton alloc] initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width / 2, checkBoxViewY + checkBoxViewH + 10, [UIScreen mainScreen].bounds.size.width / 2, 30)];
// self.startBtn.enabled = YES;
[self.stopBtn setTitle:@"stop" forState:UIControlStateNormal];
[self.stopBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[self.stopBtn setBackgroundColor:[UIColor whiteColor]];
[self.stopBtn setBackgroundColor:self.hatsuneMiKuColor];
[self.stopBtn addTarget:self action:@selector(stopSender:) forControlEvents:UIControlEventTouchUpInside];
[self.stopBtn.layer setMasksToBounds:YES];
[self.stopBtn.layer setCornerRadius:4.0];
[self.stopBtn.layer setBorderWidth:1.0];
[self.stopBtn.layer setBorderColor:[UIColor blackColor].CGColor];
[self.view addSubview:self.stopBtn];
self.captureSessionConfig = [[LWVideoCaptureConfig alloc] init];
}
- (void)viewDidDisappear:(BOOL)animated {
......@@ -67,8 +84,8 @@
}
- (IBAction)startSender:(id)sender {
self.captureSessionConfig = [[LWVideoCaptureConfig alloc] init];
self.captureSession = [[LWVideoCaptureSession alloc] initWithConfig:self.captureSessionConfig];
self.captureSession.delegate = self;
[self.captureSession startCapture];
......@@ -76,6 +93,14 @@
layer.frame = CGRectMake(0, 0, self.displayView.frame.size.width, self.displayView.frame.size.height);
layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.displayView.layer addSublayer:layer];
self.encoderConfig = [LWVideoEncoderConfig defaultConfig];
self.encoderConfig.width = 1280;
self.encoderConfig.height = 720;
self.encoderConfig.framePerSecond = 30;
self.encoderConfig.bitrate = 2000;
self.encoder = [LWVideoEncoder newVideoEncoder:self.encoderConfig];
self.encoder.delegate = self;
}
- (IBAction)stopSender:(id)sender {
......@@ -86,11 +111,14 @@
[self.captureSession stopCapture];
self.captureSession = nil;
self.encoder = nil;
}
#pragma mark LWVideoCaptureSessionDelegate
- (void)onVideoWithSampleBuffer:(CMSampleBufferRef)sampleBuffer {
if (self.encoder) {
[self.encoder encode:sampleBuffer sourceFrameRef:nil];
}
}
#pragma mark LWCheckBoxViewDelegate
......@@ -102,4 +130,11 @@
}
}
#pragma mark LWVideoEncoderDelegate
- (void)onDidEncoded:(OSStatus)status
sourceFrameRef:(void*)sourceFrameRef
info:(VTEncodeInfoFlags)infoFlags
sampleBuffer:(CMSampleBufferRef)sampleBuffer {
}
@end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册