├── README.md ├── Share ├── Info.plist ├── SampleHandler.h ├── SampleHandler.m ├── Socket │ ├── GCDAsyncSocket.h │ ├── GCDAsyncSocket.m │ ├── NTESSocket.h │ ├── NTESSocket.m │ ├── NTESSocketPacket.h │ ├── NTESSocketPacket.m │ ├── NTESTPCircularBuffer.c │ └── NTESTPCircularBuffer.h ├── Vendors │ ├── libyuv.a │ ├── libyuv.h │ └── libyuv │ │ ├── basic_types.h │ │ ├── compare.h │ │ ├── compare_row.h │ │ ├── convert.h │ │ ├── convert_argb.h │ │ ├── convert_from.h │ │ ├── convert_from_argb.h │ │ ├── cpu_id.h │ │ ├── macros_msa.h │ │ ├── mjpeg_decoder.h │ │ ├── planar_functions.h │ │ ├── rotate.h │ │ ├── rotate_argb.h │ │ ├── rotate_row.h │ │ ├── row.h │ │ ├── scale.h │ │ ├── scale_argb.h │ │ ├── scale_row.h │ │ ├── version.h │ │ └── video_common.h └── Video │ ├── NTESI420Frame.h │ ├── NTESI420Frame.m │ ├── NTESVideoUtil.h │ ├── NTESVideoUtil.m │ ├── NTESYUVConverter.h │ └── NTESYUVConverter.mm ├── ShareScreen.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── ampleskyimac.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── ampleskyimac.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── ShareScreen ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m ├── ShareScreenTests ├── Info.plist └── ShareScreenTests.m ├── ShareScreenUITests ├── Info.plist └── ShareScreenUITests.m └── ShareSetupUI ├── BroadcastSetupViewController.h ├── BroadcastSetupViewController.m └── Info.plist /README.md: -------------------------------------------------------------------------------- 1 | # ScreenShare 2 | -------------------------------------------------------------------------------- /Share/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | CQScreen 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | NSExtension 24 | 25 | NSExtensionPointIdentifier 26 | com.apple.broadcast-services-upload 27 | NSExtensionPrincipalClass 28 | SampleHandler 29 | RPBroadcastProcessMode 30 | RPBroadcastProcessModeSampleBuffer 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Share/SampleHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // SampleHandler.h 3 | // Share 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SampleHandler : RPBroadcastSampleHandler 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Share/SampleHandler.m: -------------------------------------------------------------------------------- 1 | // 2 | // SampleHandler.m 3 | // Share 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | 10 | #import "SampleHandler.h" 11 | #import "NTESYUVConverter.h" 12 | #import "NTESI420Frame.h" 13 | #import "GCDAsyncSocket.h" 14 | #import "NTESSocketPacket.h" 15 | #import "NTESTPCircularBuffer.h" 16 | @interface SampleHandler () 17 | 18 | @property (nonatomic, assign) CGFloat cropRate; 19 | @property (nonatomic, assign) CGSize targetSize; 20 | @property (nonatomic, assign) NTESVideoPackOrientation orientation; 21 | 22 | @property (nonatomic, copy) NSString *ip; 23 | @property (nonatomic, copy) NSString *clientPort; 24 | @property (nonatomic, copy) NSString *serverPort; 25 | @property (nonatomic, strong) dispatch_queue_t videoQueue; 26 | @property (nonatomic, assign) NSUInteger frameCount; 27 | @property (nonatomic, assign) BOOL connected; 28 | @property (nonatomic, strong) dispatch_source_t timer; 29 | 30 | @property (nonatomic, strong) GCDAsyncSocket *socket; 31 | @property (nonatomic, strong) dispatch_queue_t queue; 32 | @property (nonatomic, assign) NTESTPCircularBuffer *recvBuffer; 33 | 34 | @end 35 | 36 | 37 | @implementation SampleHandler 38 | static void Callback(CFNotificationCenterRef center, 39 | void *observer, 40 | CFStringRef name, 41 | const void *object, 42 | CFDictionaryRef userInfo) 43 | { 44 | 45 | } 46 | - (void)dealloc { 47 | _connected = NO; 48 | 49 | if (_socket) { 50 | [_socket disconnect]; 51 | _socket = nil; 52 | NTESTPCircularBufferCleanup(_recvBuffer); 53 | } 54 | 55 | if(_timer) { 56 | _timer = nil; 57 | } 58 | } 59 | 60 | - (instancetype)init { 61 | if(self = [super init]) { 62 | _targetSize = CGSizeMake(540, 960); 63 | _cropRate = 9.0/16; 64 | _orientation = NTESVideoPackOrientationPortrait; 65 | 66 | _ip = @"127.0.0.1"; 67 | _serverPort = @"8999"; 68 | _clientPort = [NSString stringWithFormat:@"%d", arc4random()%9999]; 69 | _videoQueue = dispatch_queue_create("com.netease.edu.rp.videoprocess", DISPATCH_QUEUE_SERIAL); 70 | 71 | CFStringRef name = CFSTR("customName"); 72 | CFNotificationCenterRef center = CFNotificationCenterGetDarwinNotifyCenter(); 73 | CFNotificationCenterAddObserver(center, 74 | (const void *)self, 75 | Callback, 76 | name, 77 | NULL, 78 | kCFNotificationDeliverImmediately); 79 | [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(didChangeRotate:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil]; 80 | } 81 | return self; 82 | } 83 | 84 | 85 | - (void)didChangeRotate:(NSNotification*)notice { 86 | if ([[UIDevice currentDevice] orientation] == UIInterfaceOrientationPortrait 87 | || [[UIDevice currentDevice] orientation] == UIInterfaceOrientationPortraitUpsideDown) { 88 | self.orientation = 0; 89 | //竖屏 90 | } else if([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight) { 91 | self.orientation = 1; 92 | //横屏 93 | }else if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft){ 94 | self.orientation = 1; 95 | } 96 | } 97 | 98 | 99 | - (void)broadcastStartedWithSetupInfo:(NSDictionary *)setupInfo { 100 | [self.socket disconnect]; 101 | if (!self.socket.isConnected) { 102 | [self setupSocket]; 103 | } 104 | if (self.connected) { 105 | NSString * str =@"Start"; 106 | NSData *data =[str dataUsingEncoding:NSUTF8StringEncoding]; 107 | [self.socket writeData:data withTimeout:5 tag:0]; 108 | } 109 | } 110 | 111 | - (void)broadcastPaused { 112 | if (self.connected) { 113 | NSString * str =@"Paused"; 114 | NSData *data =[str dataUsingEncoding:NSUTF8StringEncoding]; 115 | [self.socket writeData:data withTimeout:5 tag:0]; 116 | } 117 | } 118 | 119 | - (void)broadcastResumed { 120 | if (self.connected) { 121 | NSString * str =@"Resumed"; 122 | NSData *data =[str dataUsingEncoding:NSUTF8StringEncoding]; 123 | [self.socket writeData:data withTimeout:5 tag:0]; 124 | } 125 | } 126 | 127 | - (void)broadcastFinished { 128 | if (self.connected) { 129 | NSString * str =@"Finish"; 130 | NSData *data =[str dataUsingEncoding:NSUTF8StringEncoding]; 131 | [self.socket writeData:data withTimeout:5 tag:0]; 132 | } 133 | // [self.socket disconnect]; 134 | } 135 | 136 | - (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType { 137 | switch (sampleBufferType) { 138 | case RPSampleBufferTypeVideo: 139 | { 140 | if (!self.connected) 141 | { 142 | return; 143 | } 144 | 145 | [self sendVideoBufferToHostApp:sampleBuffer]; 146 | } 147 | break; 148 | case RPSampleBufferTypeAudioApp: 149 | // Handle audio sample buffer for app audio 150 | break; 151 | case RPSampleBufferTypeAudioMic: 152 | // Handle audio sample buffer for mic audio 153 | break; 154 | 155 | default: 156 | break; 157 | } 158 | } 159 | #pragma mark - 处理分辨率切换等 160 | - (void)onRecvData:(NSData *)data head:(NTESPacketHead *)head 161 | { 162 | if (!data) 163 | { 164 | return; 165 | } 166 | 167 | switch (head->command_id) 168 | { 169 | case 1: 170 | { 171 | NSString *qualityStr = [NSString stringWithUTF8String:[data bytes]]; 172 | int qualit = [qualityStr intValue]; 173 | switch (qualit) { 174 | case 0: 175 | self.targetSize = CGSizeMake(480, 640); 176 | break; 177 | case 1: 178 | self.targetSize = CGSizeMake(144, 177); 179 | break; 180 | case 2: 181 | self.targetSize = CGSizeMake(288, 352); 182 | break; 183 | case 3: 184 | self.targetSize = CGSizeMake(320, 480); 185 | break; 186 | case 4: 187 | self.targetSize = CGSizeMake(480, 640); 188 | break; 189 | case 5: 190 | self.targetSize = CGSizeMake(540, 960); 191 | break; 192 | case 6: 193 | self.targetSize = CGSizeMake(720, 1280); 194 | break; 195 | default: 196 | break; 197 | } 198 | NSLog(@"change target size %@", @(self.targetSize)); 199 | } 200 | break; 201 | case 2: 202 | break; 203 | case 3: 204 | { 205 | NSString *orientationStr = [NSString stringWithUTF8String:[data bytes]]; 206 | int orient = [orientationStr intValue]; 207 | switch (orient) { 208 | case 0: 209 | self.orientation = NTESVideoPackOrientationPortrait; 210 | break; 211 | case 1: 212 | self.orientation = NTESVideoPackOrientationLandscapeLeft; 213 | break; 214 | case 2: 215 | self.orientation = NTESVideoPackOrientationPortraitUpsideDown; 216 | break; 217 | case 3: 218 | self.orientation = NTESVideoPackOrientationLandscapeRight; 219 | break; 220 | default: 221 | break; 222 | }; 223 | NSLog(@"change orientation %@", @(self.orientation)); 224 | 225 | } 226 | break; 227 | default: 228 | break; 229 | } 230 | } 231 | 232 | #pragma mark - Process 233 | - (void)sendVideoBufferToHostApp:(CMSampleBufferRef)sampleBuffer { 234 | if (!self.socket) 235 | { 236 | return; 237 | } 238 | CFRetain(sampleBuffer); 239 | 240 | // NSLog(@"=======%@",sampleBuffer); 241 | dispatch_async(self.videoQueue, ^{ // queue optimal 242 | @autoreleasepool { 243 | 244 | if (self.frameCount > 1000) 245 | { 246 | CFRelease(sampleBuffer); 247 | return; 248 | } 249 | self.frameCount ++ ; 250 | CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 251 | 252 | //从数据中获取屏幕方向 253 | CFStringRef RPVideoSampleOrientationKeyRef = (__bridge CFStringRef)RPVideoSampleOrientationKey; 254 | NSNumber *orientation = (NSNumber *)CMGetAttachment(sampleBuffer, RPVideoSampleOrientationKeyRef,NULL); 255 | 256 | switch ([orientation integerValue]) { 257 | case 1: 258 | self.orientation = NTESVideoPackOrientationPortrait; 259 | break; 260 | case 6: 261 | self.orientation = NTESVideoPackOrientationLandscapeRight; 262 | break; 263 | 264 | case 8: 265 | self.orientation = NTESVideoPackOrientationLandscapeLeft; 266 | break; 267 | default: 268 | break; 269 | } 270 | 271 | 272 | 273 | // To data 274 | NTESI420Frame *videoFrame = nil; 275 | videoFrame = [NTESYUVConverter pixelBufferToI420:pixelBuffer 276 | withCrop:self.cropRate 277 | targetSize:self.targetSize 278 | andOrientation:self.orientation]; 279 | CFRelease(sampleBuffer); 280 | 281 | // To Host App 282 | // if (videoFrame) 283 | // { 284 | NSData *raw = [videoFrame bytes]; 285 | // NSData *data = [NTESSocketPacket packetWithBuffer:raw]; 286 | NSData *headerData = [NTESSocketPacket packetWithBuffer:raw]; 287 | [self.socket writeData:headerData withTimeout:5 tag:0]; 288 | [self.socket writeData:raw withTimeout:5 tag:0]; 289 | 290 | // } 291 | self.frameCount --; 292 | }; 293 | }); 294 | } 295 | 296 | - (NSData *)packetWithBuffer:(NSData *)rawData 297 | { 298 | NSMutableData *mutableData = [NSMutableData data]; 299 | @autoreleasepool { 300 | if (rawData.length == 0) 301 | { 302 | return NULL; 303 | } 304 | 305 | size_t size = rawData.length; 306 | void *data = malloc(sizeof(NTESPacketHead)); 307 | NTESPacketHead *head = (NTESPacketHead *)malloc(sizeof(NTESPacketHead)); 308 | head->version = 1; 309 | head->command_id = 0; 310 | head->service_id = 0; 311 | head->serial_id = 0; 312 | head->data_len = (uint32_t)size; 313 | 314 | size_t headSize = sizeof(NTESPacketHead); 315 | memcpy(data, head, headSize); 316 | NSData *headData = [NSData dataWithBytes:data length:headSize]; 317 | [mutableData appendData:headData]; 318 | [mutableData appendData:rawData]; 319 | 320 | free(data); 321 | free(head); 322 | } 323 | return [mutableData copy]; 324 | } 325 | 326 | - (NSData *)packetWithBuffer:(const void *)buffer 327 | size:(size_t)size 328 | packetSize:(size_t *)packetSize 329 | { 330 | if (0 == size) 331 | { 332 | return NULL; 333 | } 334 | 335 | void *data = malloc(sizeof(NTESPacketHead) + size); 336 | NTESPacketHead *head = (NTESPacketHead *)malloc(sizeof(NTESPacketHead)); 337 | head->version = 1; 338 | head->command_id = 0; 339 | head->service_id = 0; 340 | head->serial_id = 0; 341 | head->data_len = (uint32_t)size; 342 | 343 | size_t headSize = sizeof(NTESPacketHead); 344 | *packetSize = size + headSize; 345 | memcpy(data, head, headSize); 346 | memcpy(data + headSize, buffer, size); 347 | 348 | 349 | NSData *result = [NSData dataWithBytes:data length:*packetSize]; 350 | 351 | free(head); 352 | free(data); 353 | return result; 354 | } 355 | 356 | #pragma mark - Socket 357 | 358 | - (void)setupSocket 359 | { 360 | _recvBuffer = (NTESTPCircularBuffer *)malloc(sizeof(NTESTPCircularBuffer)); // 需要释放 361 | NTESTPCircularBufferInit(_recvBuffer, kRecvBufferMaxSize); 362 | self.queue = dispatch_queue_create("com.netease.edu.rp.client", DISPATCH_QUEUE_SERIAL); 363 | self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:self.queue]; 364 | // self.socket.IPv6Enabled = NO; 365 | // [self.socket connectToUrl:[NSURL fileURLWithPath:serverURL] withTimeout:5 error:nil]; 366 | NSError *error; 367 | [self.socket connectToHost:_ip onPort:8999 error:&error]; 368 | [self.socket readDataWithTimeout:-1 tag:0]; 369 | NSLog(@"setupSocket:%@",error); 370 | if (error == nil) 371 | { 372 | NSLog(@"====开启成功"); 373 | } 374 | else 375 | { 376 | NSLog(@"=====开启失败"); 377 | } 378 | } 379 | 380 | - (void)socket:(GCDAsyncSocket *)sock didConnectToUrl:(NSURL *)url 381 | { 382 | [self.socket readDataWithTimeout:-1 tag:0]; 383 | } 384 | 385 | - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port 386 | { 387 | [self.socket readDataWithTimeout:-1 tag:0]; 388 | self.connected = YES; 389 | } 390 | 391 | - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag 392 | { 393 | 394 | } 395 | 396 | - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 397 | { 398 | NTESTPCircularBufferProduceBytes(self.recvBuffer, data.bytes, (int32_t)data.length); 399 | [self handleRecvBuffer]; 400 | [sock readDataWithTimeout:-1 tag:0]; 401 | } 402 | 403 | - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err 404 | { 405 | self.connected = NO; 406 | [self.socket disconnect]; 407 | self.socket = nil; 408 | [self setupSocket]; 409 | [self.socket readDataWithTimeout:-1 tag:0]; 410 | } 411 | 412 | - (void)handleRecvBuffer { 413 | if (!self.socket) 414 | { 415 | return; 416 | } 417 | 418 | int32_t availableBytes = 0; 419 | void * buffer = NTESTPCircularBufferTail(self.recvBuffer, &availableBytes); 420 | int32_t headSize = sizeof(NTESPacketHead); 421 | 422 | if (availableBytes <= headSize) 423 | { 424 | return; 425 | } 426 | 427 | NTESPacketHead head; 428 | memset(&head, 0, sizeof(head)); 429 | memcpy(&head, buffer, headSize); 430 | uint64_t dataLen = head.data_len; 431 | 432 | if(dataLen > availableBytes - headSize && dataLen >0) { 433 | return; 434 | } 435 | 436 | void *data = malloc(dataLen); 437 | memset(data, 0, dataLen); 438 | memcpy(data, buffer + headSize, dataLen); 439 | NTESTPCircularBufferConsume(self.recvBuffer, (int32_t)(headSize+dataLen)); 440 | 441 | 442 | if([self respondsToSelector:@selector(onRecvData:head:)]) { 443 | @autoreleasepool { 444 | [self onRecvData:[NSData dataWithBytes:data length:dataLen] head:&head]; 445 | }; 446 | } 447 | 448 | free(data); 449 | 450 | if (availableBytes - headSize - dataLen >= headSize) 451 | { 452 | [self handleRecvBuffer]; 453 | } 454 | } 455 | 456 | @end 457 | -------------------------------------------------------------------------------- /Share/Socket/NTESSocket.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESSocket.h 3 | // DailyProj 4 | // 5 | // Created by He on 2019/1/30. 6 | // Copyright © 2019 He. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef struct { 12 | uint8_t version; 13 | uint8_t service_id; 14 | uint8_t command_id; 15 | uint8_t serial_id; 16 | uint64_t data_len; 17 | } NTESPacketHead; 18 | 19 | #define kRecvBufferMaxSize 1024 * 1024 *15 20 | #define kRecvBufferPerSize 1024 21 | 22 | NS_ASSUME_NONNULL_BEGIN 23 | 24 | @protocol NTESSocketDelegate 25 | 26 | @optional 27 | - (void)onRecvData:(NSData *)data; 28 | - (void)onRecvData:(NSData *)data head:(NTESPacketHead *)head; 29 | - (void)didDisconnected; 30 | @end 31 | 32 | @interface NTESSocket : NSObject 33 | @property(nonatomic, copy) NSString *ip; 34 | @property(nonatomic, copy) NSString *port; 35 | @property(nonatomic, weak) id delegate; 36 | 37 | - (instancetype)initWithPort:(NSString *)port IP:(NSString *)IP; 38 | 39 | // Server 40 | - (BOOL)startAcceptClient; 41 | 42 | // Client 43 | - (BOOL)connectToServerWithPort:(NSString *)port IP:(NSString *)IP; 44 | - (void)startRecv; 45 | 46 | // Common 47 | - (void)stop; 48 | - (void)sendData:(NSData *)data; 49 | - (void)sendData:(NSData *)data head:(NTESPacketHead *)head; 50 | 51 | @end 52 | 53 | NS_ASSUME_NONNULL_END 54 | -------------------------------------------------------------------------------- /Share/Socket/NTESSocket.m: -------------------------------------------------------------------------------- 1 | // 2 | // NTESSocket.m 3 | // DailyProj 4 | // 5 | // Created by He on 2019/1/30. 6 | // Copyright © 2019 He. All rights reserved. 7 | // 8 | 9 | #import "NTESSocket.h" 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import "NTESTPCircularBuffer.h" 15 | 16 | @interface NTESSocket() 17 | @property (nonatomic, assign) int socket; 18 | @property (nonatomic, assign) int serverSocket; 19 | @property (nonatomic, assign) int clientSocket; 20 | @property (nonatomic, assign) BOOL isServerSocket; 21 | @property (nonatomic, strong) dispatch_queue_t queue; 22 | @property (atomic, assign) BOOL isWork; 23 | @property (nonatomic, assign) NTESTPCircularBuffer *recvBuffer; 24 | @end 25 | 26 | @implementation NTESSocket 27 | 28 | #pragma mark - API 29 | 30 | - (void)dealloc { 31 | _isWork = NO; 32 | if(_socket != -1) { 33 | close(_socket); 34 | } 35 | if(_serverSocket != -1) { 36 | close(_serverSocket); 37 | } 38 | if(_clientSocket != -1) { 39 | close(_clientSocket); 40 | } 41 | } 42 | 43 | - (instancetype)initWithPort:(NSString *)port IP:(NSString *)IP 44 | { 45 | if(self = [super init]) { 46 | _socket = -1; 47 | _serverSocket = -1; 48 | _clientSocket = -1; 49 | _port = port; 50 | _ip = IP; 51 | _queue = dispatch_queue_create("com.netease.ddddaily.send", DISPATCH_QUEUE_SERIAL); 52 | if(![self setupSocket]) { 53 | return nil; 54 | } 55 | 56 | if(![self bindSocket]) { 57 | return nil; 58 | } 59 | } 60 | return self; 61 | } 62 | 63 | // Server 64 | - (BOOL)startAcceptClient { 65 | return [self listenAndAccept]; 66 | } 67 | 68 | - (void)stop { 69 | NSLog(@" >> 停止"); 70 | _isWork = NO; 71 | 72 | if(_socket != -1) { 73 | close(_socket); 74 | _socket = -1; 75 | } 76 | if(_serverSocket != -1) { 77 | close(_serverSocket); 78 | _serverSocket = -1; 79 | } 80 | if(_clientSocket != -1) { 81 | close(_clientSocket); 82 | _clientSocket = -1; 83 | } 84 | if(_delegate && [_delegate respondsToSelector:@selector(didDisconnected)]) { 85 | [_delegate didDisconnected]; 86 | } 87 | } 88 | 89 | // Client 90 | - (BOOL)connectToServerWithPort:(NSString *)port IP:(NSString *)IP { 91 | struct sockaddr_in addr_in; 92 | addr_in.sin_family = AF_INET; 93 | addr_in.sin_addr.s_addr = inet_addr([IP UTF8String]); 94 | addr_in.sin_port = htons([port intValue]); 95 | 96 | int success = connect(self.socket, (const struct sockaddr *)&addr_in, sizeof(struct sockaddr_in)); 97 | if(-1 == success) { 98 | NSLog(@" > 连接到服务端失败 port:%@ IP:%@", port, IP); 99 | return NO; 100 | } 101 | self.isServerSocket = NO; 102 | return YES; 103 | } 104 | 105 | // Common 106 | - (void)startRecv { 107 | if(self.isServerSocket) { 108 | [self receiveDataFromSocket:self.clientSocket]; 109 | }else { 110 | [self receiveDataFromSocket:self.socket]; 111 | } 112 | } 113 | 114 | - (void)sendData:(NSData *)data { 115 | if(self.isServerSocket) { 116 | [self sendDataToSocket:self.clientSocket buffer:[data bytes] size:data.length]; 117 | }else { 118 | [self sendDataToSocket:self.socket buffer:[data bytes] size:data.length]; 119 | } 120 | } 121 | 122 | - (void)sendData:(NSData *)data head:(NTESPacketHead *)head { 123 | if(self.isServerSocket) { 124 | [self sendDataToSocket:self.clientSocket 125 | buffer:[data bytes] 126 | size:data.length 127 | head:head]; 128 | } 129 | 130 | } 131 | 132 | #pragma mark - Internal 133 | 134 | - (BOOL)setupSocket { 135 | _socket = socket(AF_INET, SOCK_STREAM, 0); 136 | int opt = 1; 137 | setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 138 | if(_socket == -1) { 139 | NSLog(@" > 创建socket失败"); 140 | return NO; 141 | } 142 | return YES; 143 | } 144 | 145 | - (BOOL)bindSocket { 146 | if(_socket <= 0) { 147 | NSLog(@" > socket创建失败"); 148 | return NO; 149 | } 150 | struct sockaddr_in addr_in; 151 | addr_in.sin_family = AF_INET; 152 | addr_in.sin_addr.s_addr = inet_addr([self.ip UTF8String]); 153 | addr_in.sin_port = htons([self.port intValue]); 154 | 155 | int bd = bind(_socket, (const struct sockaddr *)&addr_in, sizeof(struct sockaddr_in)); 156 | if(-1 == bd) { 157 | NSLog(@" > Bind socket失败"); 158 | return NO; 159 | } 160 | return YES; 161 | } 162 | 163 | - (BOOL)listenAndAccept { 164 | int success = listen(_socket, 10); 165 | if(-1 == success) { 166 | NSLog(@" > Listen socket失败"); 167 | return NO; 168 | } 169 | self.isServerSocket = YES; 170 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 171 | do { 172 | struct sockaddr_in recvAddr; 173 | socklen_t recv_size = sizeof(struct sockaddr_in); 174 | NSLog(@" > 开始监听 %@ %@", self.ip, self.port); 175 | int client = accept(self.socket, (struct sockaddr *)&recvAddr, &recv_size); 176 | if(-1 == client) { 177 | NSLog(@" > 连接 客户端socket失败, 结束 %@", @(self.isWork)); 178 | }else { 179 | if (self.clientSocket != -1) 180 | close(self.clientSocket); 181 | self.clientSocket = client; 182 | [self receiveDataFromSocket:self.clientSocket]; 183 | } 184 | }while(self.isWork); 185 | 186 | }); 187 | return YES; 188 | } 189 | 190 | - (void)receiveDataFromSocket:(int)socket 191 | { 192 | if(-1 == socket) { 193 | NSLog(@" > 接收 目标socket为空"); 194 | return; 195 | } 196 | self.isWork = YES; 197 | if(_recvBuffer == NULL) { 198 | _recvBuffer = (NTESTPCircularBuffer *)malloc(sizeof(NTESTPCircularBuffer)); 199 | NTESTPCircularBufferInit(_recvBuffer, kRecvBufferMaxSize); 200 | } 201 | 202 | dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); 203 | dispatch_async(queue, ^{ 204 | char *buffer = malloc(kRecvBufferPerSize); 205 | ssize_t size = -1; 206 | bool connected = true; 207 | while (self.isWork && connected) { 208 | memset(buffer, 0, kRecvBufferPerSize); 209 | size = recv(socket, buffer, kRecvBufferPerSize, 0); 210 | if(size == 0) { 211 | NSLog(@" > 断开"); 212 | connected = false; 213 | break; 214 | }else if(size > 0){ 215 | NTESTPCircularBufferProduceBytes(self.recvBuffer, buffer, (int32_t)size); 216 | [self handleRecvBuffer]; 217 | } 218 | }; 219 | free(buffer); 220 | if(!self.isServerSocket) { 221 | [self stop]; 222 | }else { 223 | self.clientSocket = -1; 224 | } 225 | }); 226 | 227 | } 228 | -(void)sendDataToSocket:(int)socket 229 | buffer:(const void *)buffer 230 | size:(size_t)size 231 | head:(NTESPacketHead *)head 232 | { 233 | size_t packetSize = 0; 234 | void *packetBuffer = [self packetWithBuffer:buffer size:size packetSize:&packetSize head:head]; 235 | 236 | if(socket <= 0 ||packetBuffer == NULL || 0 == packetSize) { 237 | // NSLog(@" >> 异常数据"); 238 | free(packetBuffer); 239 | return; 240 | } 241 | dispatch_async(self.queue, ^{ 242 | size_t length = send(socket, packetBuffer, packetSize, 0); 243 | free(packetBuffer); 244 | if(length == -1) { 245 | if(!self.isServerSocket) { 246 | [self stop]; 247 | } 248 | } 249 | }); 250 | } 251 | - (void)sendDataToSocket:(int)socket 252 | buffer:(const void *)buffer 253 | size:(size_t)size { 254 | if(socket == -1) { 255 | return; 256 | } 257 | 258 | size_t packetSize = 0; 259 | void *packetBuffer = [self packetWithBuffer:buffer size:size packetSize:&packetSize]; 260 | 261 | if(socket <= 0 ||packetBuffer == NULL || 0 == packetSize) { 262 | if(packetBuffer) { 263 | free(packetBuffer); 264 | } 265 | return; 266 | } 267 | dispatch_async(self.queue, ^{ 268 | size_t length = send(socket, packetBuffer, packetSize, 0); 269 | free(packetBuffer); 270 | if(length == -1) { 271 | if(!self.serverSocket) { 272 | [self stop]; 273 | }else { 274 | self.clientSocket = -1; 275 | } 276 | } 277 | }); 278 | 279 | } 280 | 281 | - (void)handleRecvBuffer { 282 | int32_t availableBytes = 0; 283 | void * buffer = NTESTPCircularBufferTail(self.recvBuffer, &availableBytes); 284 | int32_t headSize = sizeof(NTESPacketHead); 285 | 286 | if(availableBytes <= headSize) { 287 | // NSLog(@" > 不够文件头"); 288 | return; 289 | } 290 | 291 | NTESPacketHead head; 292 | memset(&head, 0, sizeof(head)); 293 | memcpy(&head, buffer, headSize); 294 | uint64_t dataLen = head.data_len; 295 | 296 | if(dataLen > availableBytes - headSize && dataLen >0) { 297 | // NSLog(@" > 不够数据体"); 298 | return; 299 | } 300 | 301 | void *data = malloc(dataLen); 302 | memset(data, 0, dataLen); 303 | memcpy(data, buffer + headSize, dataLen); 304 | NTESTPCircularBufferConsume(self.recvBuffer, (int32_t)(headSize+dataLen)); 305 | 306 | if(self.delegate && [self.delegate respondsToSelector:@selector(onRecvData:head:)]) { 307 | @autoreleasepool { 308 | [self.delegate onRecvData:[NSData dataWithBytes:data length:dataLen] head:&head]; 309 | }; 310 | } 311 | if(self.delegate && [self.delegate respondsToSelector:@selector(onRecvData:)]) { 312 | @autoreleasepool { 313 | [self.delegate onRecvData:[NSData dataWithBytes:data length:dataLen]]; 314 | }; 315 | } 316 | 317 | free(data); 318 | 319 | if (availableBytes - headSize - dataLen >= headSize) 320 | { 321 | [self handleRecvBuffer]; 322 | } 323 | } 324 | 325 | #pragma mark - Packet 326 | - (void *)packetWithBuffer:(const void *)buffer 327 | size:(size_t)size 328 | packetSize:(size_t *)packetSize 329 | { 330 | if (0 == size) 331 | { 332 | return NULL; 333 | } 334 | 335 | void *data = malloc(sizeof(NTESPacketHead) + size); 336 | NTESPacketHead * head = (NTESPacketHead *)malloc(sizeof(NTESPacketHead)); 337 | head->version = 1; 338 | head->command_id = 0; 339 | head->service_id = 0; 340 | head->serial_id = 0; 341 | head->data_len = (uint32_t)size; 342 | 343 | size_t headSize = sizeof(NTESPacketHead); 344 | *packetSize = size + headSize; 345 | memcpy(data, head, headSize); 346 | memcpy(data + headSize, buffer, size); 347 | 348 | free(head); 349 | 350 | return data; 351 | } 352 | 353 | - (void *)packetWithBuffer:(const void *)buffer 354 | size:(size_t)size 355 | packetSize:(size_t *)packetSize 356 | head:(NTESPacketHead *)head 357 | { 358 | if(0 == size) { 359 | return NULL; 360 | } 361 | void *data = malloc(sizeof(NTESPacketHead) + size); 362 | 363 | head->data_len = (uint32_t)size; 364 | 365 | size_t headSize = sizeof(NTESPacketHead); 366 | *packetSize = size + headSize; 367 | memcpy(data, head, headSize); 368 | memcpy(data + headSize, buffer, size); 369 | 370 | return data; 371 | } 372 | 373 | @end 374 | -------------------------------------------------------------------------------- /Share/Socket/NTESSocketPacket.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESSocketPacket.h 3 | // NIMEducationDemo 4 | // 5 | // Created by He on 2019/5/6. 6 | // Copyright © 2019 Netease. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef struct { 12 | uint8_t version; 13 | uint8_t service_id; 14 | uint8_t command_id; 15 | uint8_t serial_id; 16 | uint64_t data_len; 17 | } NTESPacketHead; 18 | 19 | #define kRecvBufferMaxSize 1024 * 1024 *15 20 | #define kRecvBufferPerSize 1024 21 | 22 | NS_ASSUME_NONNULL_BEGIN 23 | 24 | @interface NTESSocketPacket : NSObject 25 | 26 | + (NSData *)packetWithBuffer:(NSData *)rawData; 27 | + (NSData *)packetWithBuffer:(NSData *)rawData head:(NTESPacketHead *)head; 28 | 29 | @end 30 | 31 | NS_ASSUME_NONNULL_END 32 | -------------------------------------------------------------------------------- /Share/Socket/NTESSocketPacket.m: -------------------------------------------------------------------------------- 1 | // 2 | // NTESSocketPacket.m 3 | // NIMEducationDemo 4 | // 5 | // Created by He on 2019/5/6. 6 | // Copyright © 2019 Netease. All rights reserved. 7 | // 8 | 9 | #import "NTESSocketPacket.h" 10 | 11 | @implementation NTESSocketPacket 12 | 13 | + (NSData *)packetWithBuffer:(NSData *)rawData 14 | { 15 | NSMutableData *mutableData = [NSMutableData data]; 16 | @autoreleasepool { 17 | if (rawData.length == 0) 18 | { 19 | return NULL; 20 | } 21 | static uint64_t serial_id = 0; 22 | size_t size = rawData.length; 23 | void *data = malloc(sizeof(NTESPacketHead)); 24 | NTESPacketHead *head = (NTESPacketHead *)malloc(sizeof(NTESPacketHead)); 25 | head->version = 1; 26 | head->command_id = 1; 27 | head->service_id = 1; 28 | head->serial_id = serial_id++; 29 | head->data_len = (uint32_t)size; 30 | 31 | size_t headSize = sizeof(NTESPacketHead); 32 | memcpy(data, head, headSize); 33 | NSData *headData = [NSData dataWithBytes:data length:headSize]; 34 | [mutableData appendData:headData]; 35 | // [mutableData appendData:rawData]; 36 | 37 | free(data); 38 | free(head); 39 | } 40 | return [mutableData copy]; 41 | } 42 | 43 | + (NSData *)packetWithBuffer:(NSData *)rawData head:(NTESPacketHead *)head 44 | { 45 | if (rawData) 46 | { 47 | head->data_len = rawData.length; 48 | } 49 | 50 | NSMutableData *mutableData = [NSMutableData data]; 51 | NSData *headData = [NSData dataWithBytes:head length:sizeof(NTESPacketHead)]; 52 | [mutableData appendData:headData]; 53 | 54 | if (rawData) 55 | { 56 | [mutableData appendData:rawData]; 57 | } 58 | return mutableData.copy; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Share/Socket/NTESTPCircularBuffer.c: -------------------------------------------------------------------------------- 1 | // 2 | // NTESTPCircularBuffer.c 3 | // Circular/Ring buffer implementation 4 | // 5 | // https://github.com/michaeltyson/TPCircularBuffer 6 | // 7 | // Created by Michael Tyson on 10/12/2011. 8 | // 9 | // Copyright (C) 2012-2013 A Tasty Pixel 10 | // 11 | // This software is provided 'as-is', without any express or implied 12 | // warranty. In no event will the authors be held liable for any damages 13 | // arising from the use of this software. 14 | // 15 | // Permission is granted to anyone to use this software for any purpose, 16 | // including commercial applications, and to alter it and redistribute it 17 | // freely, subject to the following restrictions: 18 | // 19 | // 1. The origin of this software must not be misrepresented; you must not 20 | // claim that you wrote the original software. If you use this software 21 | // in a product, an acknowledgment in the product documentation would be 22 | // appreciated but is not required. 23 | // 24 | // 2. Altered source versions must be plainly marked as such, and must not be 25 | // misrepresented as being the original software. 26 | // 27 | // 3. This notice may not be removed or altered from any source distribution. 28 | // 29 | 30 | #include "NTESTPCircularBuffer.h" 31 | #include 32 | #include 33 | #include 34 | 35 | #define reportNTESResult(result,operation) (_reportNTESResult((result),(operation),strrchr(__FILE__, '/')+1,__LINE__)) 36 | static inline bool _reportNTESResult(kern_return_t result, const char *operation, const char* file, int line) { 37 | if ( result != ERR_SUCCESS ) { 38 | printf("%s:%d: %s: %s\n", file, line, operation, mach_error_string(result)); 39 | return false; 40 | } 41 | return true; 42 | } 43 | 44 | bool _NTESTPCircularBufferInit(NTESTPCircularBuffer *buffer, int32_t length, size_t structSize) { 45 | 46 | assert(length > 0); 47 | 48 | if ( structSize != sizeof(NTESTPCircularBuffer) ) { 49 | fprintf(stderr, "NTESTPCircularBuffer: Header version mismatch. Check for old versions of NTESTPCircularBuffer in your project\n"); 50 | abort(); 51 | } 52 | 53 | // Keep trying until we get our buffer, needed to handle race conditions 54 | int retries = 3; 55 | while ( true ) { 56 | 57 | buffer->length = (int32_t)round_page(length); // We need whole page sizes 58 | 59 | // Temporarily allocate twice the length, so we have the contiguous address space to 60 | // support a second instance of the buffer directly after 61 | vm_address_t bufferAddress; 62 | kern_return_t result = vm_allocate(mach_task_self(), 63 | &bufferAddress, 64 | buffer->length * 2, 65 | VM_FLAGS_ANYWHERE); // allocate anywhere it'll fit 66 | if ( result != ERR_SUCCESS ) { 67 | if ( retries-- == 0 ) { 68 | reportNTESResult(result, "Buffer allocation"); 69 | return false; 70 | } 71 | // Try again if we fail 72 | continue; 73 | } 74 | 75 | // Now replace the second half of the allocation with a virtual copy of the first half. Deallocate the second half... 76 | result = vm_deallocate(mach_task_self(), 77 | bufferAddress + buffer->length, 78 | buffer->length); 79 | if ( result != ERR_SUCCESS ) { 80 | if ( retries-- == 0 ) { 81 | reportNTESResult(result, "Buffer deallocation"); 82 | return false; 83 | } 84 | // If this fails somehow, deallocate the whole region and try again 85 | vm_deallocate(mach_task_self(), bufferAddress, buffer->length); 86 | continue; 87 | } 88 | 89 | // Re-map the buffer to the address space immediately after the buffer 90 | vm_address_t virtualAddress = bufferAddress + buffer->length; 91 | vm_prot_t cur_prot, max_prot; 92 | result = vm_remap(mach_task_self(), 93 | &virtualAddress, // mirror target 94 | buffer->length, // size of mirror 95 | 0, // auto alignment 96 | 0, // force remapping to virtualAddress 97 | mach_task_self(), // same task 98 | bufferAddress, // mirror source 99 | 0, // MAP READ-WRITE, NOT COPY 100 | &cur_prot, // unused protection struct 101 | &max_prot, // unused protection struct 102 | VM_INHERIT_DEFAULT); 103 | if ( result != ERR_SUCCESS ) { 104 | if ( retries-- == 0 ) { 105 | reportNTESResult(result, "Remap buffer memory"); 106 | return false; 107 | } 108 | // If this remap failed, we hit a race condition, so deallocate and try again 109 | vm_deallocate(mach_task_self(), bufferAddress, buffer->length); 110 | continue; 111 | } 112 | 113 | if ( virtualAddress != bufferAddress+buffer->length ) { 114 | // If the memory is not contiguous, clean up both allocated buffers and try again 115 | if ( retries-- == 0 ) { 116 | printf("Couldn't map buffer memory to end of buffer\n"); 117 | return false; 118 | } 119 | 120 | vm_deallocate(mach_task_self(), virtualAddress, buffer->length); 121 | vm_deallocate(mach_task_self(), bufferAddress, buffer->length); 122 | continue; 123 | } 124 | 125 | buffer->buffer = (void*)bufferAddress; 126 | buffer->fillCount = 0; 127 | buffer->head = buffer->tail = 0; 128 | buffer->atomic = true; 129 | 130 | return true; 131 | } 132 | return false; 133 | } 134 | 135 | void NTESTPCircularBufferCleanup(NTESTPCircularBuffer *buffer) { 136 | vm_deallocate(mach_task_self(), (vm_address_t)buffer->buffer, buffer->length * 2); 137 | memset(buffer, 0, sizeof(NTESTPCircularBuffer)); 138 | } 139 | 140 | void NTESTPCircularBufferClear(NTESTPCircularBuffer *buffer) { 141 | int32_t fillCount; 142 | if ( NTESTPCircularBufferTail(buffer, &fillCount) ) { 143 | NTESTPCircularBufferConsume(buffer, fillCount); 144 | } 145 | } 146 | 147 | void NTESTPCircularBufferSetAtomic(NTESTPCircularBuffer *buffer, bool atomic) { 148 | buffer->atomic = atomic; 149 | } 150 | -------------------------------------------------------------------------------- /Share/Socket/NTESTPCircularBuffer.h: -------------------------------------------------------------------------------- 1 | // 2 | // NTESTPCircularBuffer.h 3 | // Circular/Ring buffer implementation 4 | // 5 | // https://github.com/michaeltyson/TPCircularBuffer 6 | // 7 | // Created by Michael Tyson on 10/12/2011. 8 | // 9 | // 10 | // This implementation makes use of a virtual memory mapping technique that inserts a virtual copy 11 | // of the buffer memory directly after the buffer's end, negating the need for any buffer wrap-around 12 | // logic. Clients can simply use the returned memory address as if it were contiguous space. 13 | // 14 | // The implementation is thread-safe in the case of a single producer and single consumer. 15 | // 16 | // Virtual memory technique originally proposed by Philip Howard (http://vrb.slashusr.org/), and 17 | // adapted to Darwin by Kurt Revis (http://www.snoize.com, 18 | // http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz) 19 | // 20 | // 21 | // Copyright (C) 2012-2013 A Tasty Pixel 22 | // 23 | // This software is provided 'as-is', without any express or implied 24 | // warranty. In no event will the authors be held liable for any damages 25 | // arising from the use of this software. 26 | // 27 | // Permission is granted to anyone to use this software for any purpose, 28 | // including commercial applications, and to alter it and redistribute it 29 | // freely, subject to the following restrictions: 30 | // 31 | // 1. The origin of this software must not be misrepresented; you must not 32 | // claim that you wrote the original software. If you use this software 33 | // in a product, an acknowledgment in the product documentation would be 34 | // appreciated but is not required. 35 | // 36 | // 2. Altered source versions must be plainly marked as such, and must not be 37 | // misrepresented as being the original software. 38 | // 39 | // 3. This notice may not be removed or altered from any source distribution. 40 | // 41 | 42 | #ifndef NTESTPCircularBuffer_h 43 | #define NTESTPCircularBuffer_h 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | #ifdef __cplusplus 51 | extern "C" { 52 | #endif 53 | 54 | typedef struct { 55 | void *buffer; 56 | int32_t length; 57 | int32_t tail; 58 | int32_t head; 59 | volatile int32_t fillCount; 60 | bool atomic; 61 | } NTESTPCircularBuffer; 62 | 63 | /*! 64 | * Initialise buffer 65 | * 66 | * Note that the length is advisory only: Because of the way the 67 | * memory mirroring technique works, the true buffer length will 68 | * be multiples of the device page size (e.g. 4096 bytes) 69 | * 70 | * If you intend to use the AudioBufferList utilities, you should 71 | * always allocate a bit more space than you need for pure audio 72 | * data, so there's room for the metadata. How much extra is required 73 | * depends on how many AudioBufferList structures are used, which is 74 | * a function of how many audio frames each buffer holds. A good rule 75 | * of thumb is to add 15%, or at least another 2048 bytes or so. 76 | * 77 | * @param buffer Circular buffer 78 | * @param length Length of buffer 79 | */ 80 | #define NTESTPCircularBufferInit(buffer, length) \ 81 | _NTESTPCircularBufferInit(buffer, length, sizeof(*buffer)) 82 | bool _NTESTPCircularBufferInit(NTESTPCircularBuffer *buffer, int32_t length, size_t structSize); 83 | 84 | /*! 85 | * Cleanup buffer 86 | * 87 | * Releases buffer resources. 88 | */ 89 | void NTESTPCircularBufferCleanup(NTESTPCircularBuffer *buffer); 90 | 91 | /*! 92 | * Clear buffer 93 | * 94 | * Resets buffer to original, empty state. 95 | * 96 | * This is safe for use by consumer while producer is accessing 97 | * buffer. 98 | */ 99 | void NTESTPCircularBufferClear(NTESTPCircularBuffer *buffer); 100 | 101 | /*! 102 | * Set the atomicity 103 | * 104 | * If you set the atomiticy to false using this method, the buffer will 105 | * not use atomic operations. This can be used to give the compiler a little 106 | * more optimisation opportunities when the buffer is only used on one thread. 107 | * 108 | * Important note: Only set this to false if you know what you're doing! 109 | * 110 | * The default value is true (the buffer will use atomic operations) 111 | * 112 | * @param buffer Circular buffer 113 | * @param atomic Whether the buffer is atomic (default true) 114 | */ 115 | void NTESTPCircularBufferSetAtomic(NTESTPCircularBuffer *buffer, bool atomic); 116 | 117 | // Reading (consuming) 118 | 119 | /*! 120 | * Access end of buffer 121 | * 122 | * This gives you a pointer to the end of the buffer, ready 123 | * for reading, and the number of available bytes to read. 124 | * 125 | * @param buffer Circular buffer 126 | * @param availableBytes On output, the number of bytes ready for reading 127 | * @return Pointer to the first bytes ready for reading, or NULL if buffer is empty 128 | */ 129 | static __inline__ __attribute__((always_inline)) void* NTESTPCircularBufferTail(NTESTPCircularBuffer *buffer, int32_t* availableBytes) { 130 | *availableBytes = buffer->fillCount; 131 | if ( *availableBytes == 0 ) return NULL; 132 | return (void*)((char*)buffer->buffer + buffer->tail); 133 | } 134 | 135 | /*! 136 | * Consume bytes in buffer 137 | * 138 | * This frees up the just-read bytes, ready for writing again. 139 | * 140 | * @param buffer Circular buffer 141 | * @param amount Number of bytes to consume 142 | */ 143 | static __inline__ __attribute__((always_inline)) void NTESTPCircularBufferConsume(NTESTPCircularBuffer *buffer, int32_t amount) { 144 | buffer->tail = (buffer->tail + amount) % buffer->length; 145 | 146 | if ( buffer->atomic ) { 147 | OSAtomicAdd32Barrier(-amount, &buffer->fillCount); 148 | } else { 149 | buffer->fillCount -= amount; 150 | } 151 | 152 | assert(buffer->fillCount >= 0); 153 | } 154 | 155 | /*! 156 | * Access front of buffer 157 | * 158 | * This gives you a pointer to the front of the buffer, ready 159 | * for writing, and the number of available bytes to write. 160 | * 161 | * @param buffer Circular buffer 162 | * @param availableBytes On output, the number of bytes ready for writing 163 | * @return Pointer to the first bytes ready for writing, or NULL if buffer is full 164 | */ 165 | static __inline__ __attribute__((always_inline)) void* NTESTPCircularBufferHead(NTESTPCircularBuffer *buffer, int32_t* availableBytes) { 166 | *availableBytes = (buffer->length - buffer->fillCount); 167 | if ( *availableBytes == 0 ) return NULL; 168 | return (void*)((char*)buffer->buffer + buffer->head); 169 | } 170 | 171 | // Writing (producing) 172 | 173 | /*! 174 | * Produce bytes in buffer 175 | * 176 | * This marks the given section of the buffer ready for reading. 177 | * 178 | * @param buffer Circular buffer 179 | * @param amount Number of bytes to produce 180 | */ 181 | static __inline__ __attribute__((always_inline)) void NTESTPCircularBufferProduce(NTESTPCircularBuffer *buffer, int32_t amount) { 182 | buffer->head = (buffer->head + amount) % buffer->length; 183 | if ( buffer->atomic ) { 184 | OSAtomicAdd32Barrier(amount, &buffer->fillCount); 185 | } else { 186 | buffer->fillCount += amount; 187 | } 188 | assert(buffer->fillCount <= buffer->length); 189 | } 190 | 191 | /*! 192 | * Helper routine to copy bytes to buffer 193 | * 194 | * This copies the given bytes to the buffer, and marks them ready for reading. 195 | * 196 | * @param buffer Circular buffer 197 | * @param src Source buffer 198 | * @param len Number of bytes in source buffer 199 | * @return true if bytes copied, false if there was insufficient space 200 | */ 201 | static __inline__ __attribute__((always_inline)) bool NTESTPCircularBufferProduceBytes(NTESTPCircularBuffer *buffer, const void* src, int32_t len) { 202 | int32_t space; 203 | void *ptr = NTESTPCircularBufferHead(buffer, &space); 204 | if ( space < len ) return false; 205 | memcpy(ptr, src, len); 206 | NTESTPCircularBufferProduce(buffer, len); 207 | return true; 208 | } 209 | 210 | /*! 211 | * Deprecated method 212 | */ 213 | static __inline__ __attribute__((always_inline)) __deprecated_msg("use NTESTPCircularBufferSetAtomic(false) and NTESTPCircularBufferConsume instead") 214 | void NTESTPCircularBufferConsumeNoBarrier(NTESTPCircularBuffer *buffer, int32_t amount) { 215 | buffer->tail = (buffer->tail + amount) % buffer->length; 216 | buffer->fillCount -= amount; 217 | assert(buffer->fillCount >= 0); 218 | } 219 | 220 | /*! 221 | * Deprecated method 222 | */ 223 | static __inline__ __attribute__((always_inline)) __deprecated_msg("use NTESTPCircularBufferSetAtomic(false) and NTESTPCircularBufferProduce instead") 224 | void NTESTPCircularBufferProduceNoBarrier(NTESTPCircularBuffer *buffer, int32_t amount) { 225 | buffer->head = (buffer->head + amount) % buffer->length; 226 | buffer->fillCount += amount; 227 | assert(buffer->fillCount <= buffer->length); 228 | } 229 | 230 | #ifdef __cplusplus 231 | } 232 | #endif 233 | 234 | #endif 235 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/githupchenqiang/ScreenShare/0e31ac757736bf321f0adab6dc0fbf825c553561/Share/Vendors/libyuv.a -------------------------------------------------------------------------------- /Share/Vendors/libyuv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_H_ 12 | #define INCLUDE_LIBYUV_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | #include "libyuv/compare.h" 16 | #include "libyuv/convert.h" 17 | #include "libyuv/convert_argb.h" 18 | #include "libyuv/convert_from.h" 19 | #include "libyuv/convert_from_argb.h" 20 | #include "libyuv/cpu_id.h" 21 | #include "libyuv/mjpeg_decoder.h" 22 | #include "libyuv/planar_functions.h" 23 | #include "libyuv/rotate.h" 24 | #include "libyuv/rotate_argb.h" 25 | #include "libyuv/row.h" 26 | #include "libyuv/scale.h" 27 | #include "libyuv/scale_argb.h" 28 | #include "libyuv/scale_row.h" 29 | #include "libyuv/version.h" 30 | #include "libyuv/video_common.h" 31 | 32 | #endif // INCLUDE_LIBYUV_H_ 33 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/basic_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_BASIC_TYPES_H_ 12 | #define INCLUDE_LIBYUV_BASIC_TYPES_H_ 13 | 14 | #include // for NULL, size_t 15 | 16 | #if defined(_MSC_VER) && (_MSC_VER < 1600) 17 | #include // for uintptr_t on x86 18 | #else 19 | #include // for uintptr_t 20 | #endif 21 | 22 | #ifndef GG_LONGLONG 23 | #ifndef INT_TYPES_DEFINED 24 | #define INT_TYPES_DEFINED 25 | #ifdef COMPILER_MSVC 26 | typedef unsigned __int64 uint64; 27 | typedef __int64 int64; 28 | #ifndef INT64_C 29 | #define INT64_C(x) x ## I64 30 | #endif 31 | #ifndef UINT64_C 32 | #define UINT64_C(x) x ## UI64 33 | #endif 34 | #define INT64_F "I64" 35 | #else // COMPILER_MSVC 36 | #if defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__) 37 | typedef unsigned long uint64; // NOLINT 38 | typedef long int64; // NOLINT 39 | #ifndef INT64_C 40 | #define INT64_C(x) x ## L 41 | #endif 42 | #ifndef UINT64_C 43 | #define UINT64_C(x) x ## UL 44 | #endif 45 | #define INT64_F "l" 46 | #else // defined(__LP64__) && !defined(__OpenBSD__) && !defined(__APPLE__) 47 | typedef unsigned long long uint64; // NOLINT 48 | typedef long long int64; // NOLINT 49 | #ifndef INT64_C 50 | #define INT64_C(x) x ## LL 51 | #endif 52 | #ifndef UINT64_C 53 | #define UINT64_C(x) x ## ULL 54 | #endif 55 | #define INT64_F "ll" 56 | #endif // __LP64__ 57 | #endif // COMPILER_MSVC 58 | typedef unsigned int uint32; 59 | typedef int int32; 60 | typedef unsigned short uint16; // NOLINT 61 | typedef short int16; // NOLINT 62 | typedef unsigned char uint8; 63 | typedef signed char int8; 64 | #endif // INT_TYPES_DEFINED 65 | #endif // GG_LONGLONG 66 | 67 | // Detect compiler is for x86 or x64. 68 | #if defined(__x86_64__) || defined(_M_X64) || \ 69 | defined(__i386__) || defined(_M_IX86) 70 | #define CPU_X86 1 71 | #endif 72 | // Detect compiler is for ARM. 73 | #if defined(__arm__) || defined(_M_ARM) 74 | #define CPU_ARM 1 75 | #endif 76 | 77 | #ifndef ALIGNP 78 | #ifdef __cplusplus 79 | #define ALIGNP(p, t) \ 80 | (reinterpret_cast(((reinterpret_cast(p) + \ 81 | ((t) - 1)) & ~((t) - 1)))) 82 | #else 83 | #define ALIGNP(p, t) \ 84 | ((uint8*)((((uintptr_t)(p) + ((t) - 1)) & ~((t) - 1)))) /* NOLINT */ 85 | #endif 86 | #endif 87 | 88 | #if !defined(LIBYUV_API) 89 | #if defined(_WIN32) || defined(__CYGWIN__) 90 | #if defined(LIBYUV_BUILDING_SHARED_LIBRARY) 91 | #define LIBYUV_API __declspec(dllexport) 92 | #elif defined(LIBYUV_USING_SHARED_LIBRARY) 93 | #define LIBYUV_API __declspec(dllimport) 94 | #else 95 | #define LIBYUV_API 96 | #endif // LIBYUV_BUILDING_SHARED_LIBRARY 97 | #elif defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__APPLE__) && \ 98 | (defined(LIBYUV_BUILDING_SHARED_LIBRARY) || \ 99 | defined(LIBYUV_USING_SHARED_LIBRARY)) 100 | #define LIBYUV_API __attribute__ ((visibility ("default"))) 101 | #else 102 | #define LIBYUV_API 103 | #endif // __GNUC__ 104 | #endif // LIBYUV_API 105 | 106 | #define LIBYUV_BOOL int 107 | #define LIBYUV_FALSE 0 108 | #define LIBYUV_TRUE 1 109 | 110 | // Visual C x86 or GCC little endian. 111 | #if defined(__x86_64__) || defined(_M_X64) || \ 112 | defined(__i386__) || defined(_M_IX86) || \ 113 | defined(__arm__) || defined(_M_ARM) || \ 114 | (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 115 | #define LIBYUV_LITTLE_ENDIAN 116 | #endif 117 | 118 | #endif // INCLUDE_LIBYUV_BASIC_TYPES_H_ 119 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/compare.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_COMPARE_H_ 12 | #define INCLUDE_LIBYUV_COMPARE_H_ 13 | 14 | #include "basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Compute a hash for specified memory. Seed of 5381 recommended. 22 | LIBYUV_API 23 | uint32 HashDjb2(const uint8* src, uint64 count, uint32 seed); 24 | 25 | // Scan an opaque argb image and return fourcc based on alpha offset. 26 | // Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown. 27 | LIBYUV_API 28 | uint32 ARGBDetect(const uint8* argb, int stride_argb, int width, int height); 29 | 30 | // Sum Square Error - used to compute Mean Square Error or PSNR. 31 | LIBYUV_API 32 | uint64 ComputeSumSquareError(const uint8* src_a, 33 | const uint8* src_b, int count); 34 | 35 | LIBYUV_API 36 | uint64 ComputeSumSquareErrorPlane(const uint8* src_a, int stride_a, 37 | const uint8* src_b, int stride_b, 38 | int width, int height); 39 | 40 | static const int kMaxPsnr = 128; 41 | 42 | LIBYUV_API 43 | double SumSquareErrorToPsnr(uint64 sse, uint64 count); 44 | 45 | LIBYUV_API 46 | double CalcFramePsnr(const uint8* src_a, int stride_a, 47 | const uint8* src_b, int stride_b, 48 | int width, int height); 49 | 50 | LIBYUV_API 51 | double I420Psnr(const uint8* src_y_a, int stride_y_a, 52 | const uint8* src_u_a, int stride_u_a, 53 | const uint8* src_v_a, int stride_v_a, 54 | const uint8* src_y_b, int stride_y_b, 55 | const uint8* src_u_b, int stride_u_b, 56 | const uint8* src_v_b, int stride_v_b, 57 | int width, int height); 58 | 59 | LIBYUV_API 60 | double CalcFrameSsim(const uint8* src_a, int stride_a, 61 | const uint8* src_b, int stride_b, 62 | int width, int height); 63 | 64 | LIBYUV_API 65 | double I420Ssim(const uint8* src_y_a, int stride_y_a, 66 | const uint8* src_u_a, int stride_u_a, 67 | const uint8* src_v_a, int stride_v_a, 68 | const uint8* src_y_b, int stride_y_b, 69 | const uint8* src_u_b, int stride_u_b, 70 | const uint8* src_v_b, int stride_v_b, 71 | int width, int height); 72 | 73 | #ifdef __cplusplus 74 | } // extern "C" 75 | } // namespace libyuv 76 | #endif 77 | 78 | #endif // INCLUDE_LIBYUV_COMPARE_H_ 79 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/compare_row.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_COMPARE_ROW_H_ 12 | #define INCLUDE_LIBYUV_COMPARE_ROW_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | #if defined(__pnacl__) || defined(__CLR_VER) || \ 22 | (defined(__i386__) && !defined(__SSE2__)) 23 | #define LIBYUV_DISABLE_X86 24 | #endif 25 | // MemorySanitizer does not support assembly code yet. http://crbug.com/344505 26 | #if defined(__has_feature) 27 | #if __has_feature(memory_sanitizer) 28 | #define LIBYUV_DISABLE_X86 29 | #endif 30 | #endif 31 | 32 | // Visual C 2012 required for AVX2. 33 | #if defined(_M_IX86) && !defined(__clang__) && \ 34 | defined(_MSC_VER) && _MSC_VER >= 1700 35 | #define VISUALC_HAS_AVX2 1 36 | #endif // VisualStudio >= 2012 37 | 38 | // clang >= 3.4.0 required for AVX2. 39 | #if defined(__clang__) && (defined(__x86_64__) || defined(__i386__)) 40 | #if (__clang_major__ > 3) || (__clang_major__ == 3 && (__clang_minor__ >= 4)) 41 | #define CLANG_HAS_AVX2 1 42 | #endif // clang >= 3.4 43 | #endif // __clang__ 44 | 45 | #if !defined(LIBYUV_DISABLE_X86) && \ 46 | defined(_M_IX86) && (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2)) 47 | #define HAS_HASHDJB2_AVX2 48 | #endif 49 | 50 | // The following are available for Visual C and GCC: 51 | #if !defined(LIBYUV_DISABLE_X86) && \ 52 | (defined(__x86_64__) || (defined(__i386__) || defined(_M_IX86))) 53 | #define HAS_HASHDJB2_SSE41 54 | #define HAS_SUMSQUAREERROR_SSE2 55 | #endif 56 | 57 | // The following are available for Visual C and clangcl 32 bit: 58 | #if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) && \ 59 | (defined(VISUALC_HAS_AVX2) || defined(CLANG_HAS_AVX2)) 60 | #define HAS_HASHDJB2_AVX2 61 | #define HAS_SUMSQUAREERROR_AVX2 62 | #endif 63 | 64 | // The following are available for Neon: 65 | #if !defined(LIBYUV_DISABLE_NEON) && \ 66 | (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) 67 | #define HAS_SUMSQUAREERROR_NEON 68 | #endif 69 | 70 | uint32 SumSquareError_C(const uint8* src_a, const uint8* src_b, int count); 71 | uint32 SumSquareError_SSE2(const uint8* src_a, const uint8* src_b, int count); 72 | uint32 SumSquareError_AVX2(const uint8* src_a, const uint8* src_b, int count); 73 | uint32 SumSquareError_NEON(const uint8* src_a, const uint8* src_b, int count); 74 | 75 | uint32 HashDjb2_C(const uint8* src, int count, uint32 seed); 76 | uint32 HashDjb2_SSE41(const uint8* src, int count, uint32 seed); 77 | uint32 HashDjb2_AVX2(const uint8* src, int count, uint32 seed); 78 | 79 | #ifdef __cplusplus 80 | } // extern "C" 81 | } // namespace libyuv 82 | #endif 83 | 84 | #endif // INCLUDE_LIBYUV_COMPARE_ROW_H_ 85 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/convert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_CONVERT_H_ 12 | #define INCLUDE_LIBYUV_CONVERT_H_ 13 | 14 | #include "basic_types.h" 15 | 16 | #include "rotate.h" // For enum RotationMode. 17 | 18 | // TODO(fbarchard): fix WebRTC source to include following libyuv headers: 19 | #include "convert_argb.h" // For WebRTC I420ToARGB. b/620 20 | #include "convert_from.h" // For WebRTC ConvertFromI420. b/620 21 | #include "planar_functions.h" // For WebRTC I420Rect, CopyPlane. b/618 22 | 23 | #ifdef __cplusplus 24 | namespace libyuv { 25 | extern "C" { 26 | #endif 27 | 28 | // Convert I444 to I420. 29 | LIBYUV_API 30 | int I444ToI420(const uint8* src_y, int src_stride_y, 31 | const uint8* src_u, int src_stride_u, 32 | const uint8* src_v, int src_stride_v, 33 | uint8* dst_y, int dst_stride_y, 34 | uint8* dst_u, int dst_stride_u, 35 | uint8* dst_v, int dst_stride_v, 36 | int width, int height); 37 | 38 | // Convert I422 to I420. 39 | LIBYUV_API 40 | int I422ToI420(const uint8* src_y, int src_stride_y, 41 | const uint8* src_u, int src_stride_u, 42 | const uint8* src_v, int src_stride_v, 43 | uint8* dst_y, int dst_stride_y, 44 | uint8* dst_u, int dst_stride_u, 45 | uint8* dst_v, int dst_stride_v, 46 | int width, int height); 47 | 48 | // Copy I420 to I420. 49 | #define I420ToI420 I420Copy 50 | LIBYUV_API 51 | int I420Copy(const uint8* src_y, int src_stride_y, 52 | const uint8* src_u, int src_stride_u, 53 | const uint8* src_v, int src_stride_v, 54 | uint8* dst_y, int dst_stride_y, 55 | uint8* dst_u, int dst_stride_u, 56 | uint8* dst_v, int dst_stride_v, 57 | int width, int height); 58 | 59 | // Convert I400 (grey) to I420. 60 | LIBYUV_API 61 | int I400ToI420(const uint8* src_y, int src_stride_y, 62 | uint8* dst_y, int dst_stride_y, 63 | uint8* dst_u, int dst_stride_u, 64 | uint8* dst_v, int dst_stride_v, 65 | int width, int height); 66 | 67 | #define J400ToJ420 I400ToI420 68 | 69 | // Convert NV12 to I420. 70 | LIBYUV_API 71 | int NV12ToI420(const uint8* src_y, int src_stride_y, 72 | const uint8* src_uv, int src_stride_uv, 73 | uint8* dst_y, int dst_stride_y, 74 | uint8* dst_u, int dst_stride_u, 75 | uint8* dst_v, int dst_stride_v, 76 | int width, int height); 77 | 78 | // Convert NV21 to I420. 79 | LIBYUV_API 80 | int NV21ToI420(const uint8* src_y, int src_stride_y, 81 | const uint8* src_vu, int src_stride_vu, 82 | uint8* dst_y, int dst_stride_y, 83 | uint8* dst_u, int dst_stride_u, 84 | uint8* dst_v, int dst_stride_v, 85 | int width, int height); 86 | 87 | // Convert YUY2 to I420. 88 | LIBYUV_API 89 | int YUY2ToI420(const uint8* src_yuy2, int src_stride_yuy2, 90 | uint8* dst_y, int dst_stride_y, 91 | uint8* dst_u, int dst_stride_u, 92 | uint8* dst_v, int dst_stride_v, 93 | int width, int height); 94 | 95 | // Convert UYVY to I420. 96 | LIBYUV_API 97 | int UYVYToI420(const uint8* src_uyvy, int src_stride_uyvy, 98 | uint8* dst_y, int dst_stride_y, 99 | uint8* dst_u, int dst_stride_u, 100 | uint8* dst_v, int dst_stride_v, 101 | int width, int height); 102 | 103 | // Convert M420 to I420. 104 | LIBYUV_API 105 | int M420ToI420(const uint8* src_m420, int src_stride_m420, 106 | uint8* dst_y, int dst_stride_y, 107 | uint8* dst_u, int dst_stride_u, 108 | uint8* dst_v, int dst_stride_v, 109 | int width, int height); 110 | 111 | // Convert Android420 to I420. 112 | LIBYUV_API 113 | int Android420ToI420(const uint8* src_y, int src_stride_y, 114 | const uint8* src_u, int src_stride_u, 115 | const uint8* src_v, int src_stride_v, 116 | int pixel_stride_uv, 117 | uint8* dst_y, int dst_stride_y, 118 | uint8* dst_u, int dst_stride_u, 119 | uint8* dst_v, int dst_stride_v, 120 | int width, int height); 121 | 122 | // ARGB little endian (bgra in memory) to I420. 123 | LIBYUV_API 124 | int ARGBToI420(const uint8* src_frame, int src_stride_frame, 125 | uint8* dst_y, int dst_stride_y, 126 | uint8* dst_u, int dst_stride_u, 127 | uint8* dst_v, int dst_stride_v, 128 | int width, int height); 129 | 130 | // BGRA little endian (argb in memory) to I420. 131 | LIBYUV_API 132 | int BGRAToI420(const uint8* src_frame, int src_stride_frame, 133 | uint8* dst_y, int dst_stride_y, 134 | uint8* dst_u, int dst_stride_u, 135 | uint8* dst_v, int dst_stride_v, 136 | int width, int height); 137 | 138 | // ABGR little endian (rgba in memory) to I420. 139 | LIBYUV_API 140 | int ABGRToI420(const uint8* src_frame, int src_stride_frame, 141 | uint8* dst_y, int dst_stride_y, 142 | uint8* dst_u, int dst_stride_u, 143 | uint8* dst_v, int dst_stride_v, 144 | int width, int height); 145 | 146 | // RGBA little endian (abgr in memory) to I420. 147 | LIBYUV_API 148 | int RGBAToI420(const uint8* src_frame, int src_stride_frame, 149 | uint8* dst_y, int dst_stride_y, 150 | uint8* dst_u, int dst_stride_u, 151 | uint8* dst_v, int dst_stride_v, 152 | int width, int height); 153 | 154 | // RGB little endian (bgr in memory) to I420. 155 | LIBYUV_API 156 | int RGB24ToI420(const uint8* src_frame, int src_stride_frame, 157 | uint8* dst_y, int dst_stride_y, 158 | uint8* dst_u, int dst_stride_u, 159 | uint8* dst_v, int dst_stride_v, 160 | int width, int height); 161 | 162 | // RGB big endian (rgb in memory) to I420. 163 | LIBYUV_API 164 | int RAWToI420(const uint8* src_frame, int src_stride_frame, 165 | uint8* dst_y, int dst_stride_y, 166 | uint8* dst_u, int dst_stride_u, 167 | uint8* dst_v, int dst_stride_v, 168 | int width, int height); 169 | 170 | // RGB16 (RGBP fourcc) little endian to I420. 171 | LIBYUV_API 172 | int RGB565ToI420(const uint8* src_frame, int src_stride_frame, 173 | uint8* dst_y, int dst_stride_y, 174 | uint8* dst_u, int dst_stride_u, 175 | uint8* dst_v, int dst_stride_v, 176 | int width, int height); 177 | 178 | // RGB15 (RGBO fourcc) little endian to I420. 179 | LIBYUV_API 180 | int ARGB1555ToI420(const uint8* src_frame, int src_stride_frame, 181 | uint8* dst_y, int dst_stride_y, 182 | uint8* dst_u, int dst_stride_u, 183 | uint8* dst_v, int dst_stride_v, 184 | int width, int height); 185 | 186 | // RGB12 (R444 fourcc) little endian to I420. 187 | LIBYUV_API 188 | int ARGB4444ToI420(const uint8* src_frame, int src_stride_frame, 189 | uint8* dst_y, int dst_stride_y, 190 | uint8* dst_u, int dst_stride_u, 191 | uint8* dst_v, int dst_stride_v, 192 | int width, int height); 193 | 194 | #ifdef HAVE_JPEG 195 | // src_width/height provided by capture. 196 | // dst_width/height for clipping determine final size. 197 | LIBYUV_API 198 | int MJPGToI420(const uint8* sample, size_t sample_size, 199 | uint8* dst_y, int dst_stride_y, 200 | uint8* dst_u, int dst_stride_u, 201 | uint8* dst_v, int dst_stride_v, 202 | int src_width, int src_height, 203 | int dst_width, int dst_height); 204 | 205 | // Query size of MJPG in pixels. 206 | LIBYUV_API 207 | int MJPGSize(const uint8* sample, size_t sample_size, 208 | int* width, int* height); 209 | #endif 210 | 211 | // Convert camera sample to I420 with cropping, rotation and vertical flip. 212 | // "src_size" is needed to parse MJPG. 213 | // "dst_stride_y" number of bytes in a row of the dst_y plane. 214 | // Normally this would be the same as dst_width, with recommended alignment 215 | // to 16 bytes for better efficiency. 216 | // If rotation of 90 or 270 is used, stride is affected. The caller should 217 | // allocate the I420 buffer according to rotation. 218 | // "dst_stride_u" number of bytes in a row of the dst_u plane. 219 | // Normally this would be the same as (dst_width + 1) / 2, with 220 | // recommended alignment to 16 bytes for better efficiency. 221 | // If rotation of 90 or 270 is used, stride is affected. 222 | // "crop_x" and "crop_y" are starting position for cropping. 223 | // To center, crop_x = (src_width - dst_width) / 2 224 | // crop_y = (src_height - dst_height) / 2 225 | // "src_width" / "src_height" is size of src_frame in pixels. 226 | // "src_height" can be negative indicating a vertically flipped image source. 227 | // "crop_width" / "crop_height" is the size to crop the src to. 228 | // Must be less than or equal to src_width/src_height 229 | // Cropping parameters are pre-rotation. 230 | // "rotation" can be 0, 90, 180 or 270. 231 | // "format" is a fourcc. ie 'I420', 'YUY2' 232 | // Returns 0 for successful; -1 for invalid parameter. Non-zero for failure. 233 | LIBYUV_API 234 | int ConvertToI420(const uint8* src_frame, size_t src_size, 235 | uint8* dst_y, int dst_stride_y, 236 | uint8* dst_u, int dst_stride_u, 237 | uint8* dst_v, int dst_stride_v, 238 | int crop_x, int crop_y, 239 | int src_width, int src_height, 240 | int crop_width, int crop_height, 241 | enum RotationMode rotation, 242 | uint32 format); 243 | 244 | #ifdef __cplusplus 245 | } // extern "C" 246 | } // namespace libyuv 247 | #endif 248 | 249 | #endif // INCLUDE_LIBYUV_CONVERT_H_ 250 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/convert_argb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_CONVERT_ARGB_H_ 12 | #define INCLUDE_LIBYUV_CONVERT_ARGB_H_ 13 | 14 | #include "basic_types.h" 15 | 16 | #include "rotate.h" // For enum RotationMode. 17 | 18 | // TODO(fbarchard): This set of functions should exactly match convert.h 19 | // TODO(fbarchard): Add tests. Create random content of right size and convert 20 | // with C vs Opt and or to I420 and compare. 21 | // TODO(fbarchard): Some of these functions lack parameter setting. 22 | 23 | #ifdef __cplusplus 24 | namespace libyuv { 25 | extern "C" { 26 | #endif 27 | 28 | // Alias. 29 | #define ARGBToARGB ARGBCopy 30 | 31 | // Copy ARGB to ARGB. 32 | LIBYUV_API 33 | int ARGBCopy(const uint8* src_argb, int src_stride_argb, 34 | uint8* dst_argb, int dst_stride_argb, 35 | int width, int height); 36 | 37 | // Convert I420 to ARGB. 38 | LIBYUV_API 39 | int I420ToARGB(const uint8* src_y, int src_stride_y, 40 | const uint8* src_u, int src_stride_u, 41 | const uint8* src_v, int src_stride_v, 42 | uint8* dst_argb, int dst_stride_argb, 43 | int width, int height); 44 | 45 | // Duplicate prototype for function in convert_from.h for remoting. 46 | LIBYUV_API 47 | int I420ToABGR(const uint8* src_y, int src_stride_y, 48 | const uint8* src_u, int src_stride_u, 49 | const uint8* src_v, int src_stride_v, 50 | uint8* dst_argb, int dst_stride_argb, 51 | int width, int height); 52 | 53 | // Convert I422 to ARGB. 54 | LIBYUV_API 55 | int I422ToARGB(const uint8* src_y, int src_stride_y, 56 | const uint8* src_u, int src_stride_u, 57 | const uint8* src_v, int src_stride_v, 58 | uint8* dst_argb, int dst_stride_argb, 59 | int width, int height); 60 | 61 | // Convert I444 to ARGB. 62 | LIBYUV_API 63 | int I444ToARGB(const uint8* src_y, int src_stride_y, 64 | const uint8* src_u, int src_stride_u, 65 | const uint8* src_v, int src_stride_v, 66 | uint8* dst_argb, int dst_stride_argb, 67 | int width, int height); 68 | 69 | // Convert J444 to ARGB. 70 | LIBYUV_API 71 | int J444ToARGB(const uint8* src_y, int src_stride_y, 72 | const uint8* src_u, int src_stride_u, 73 | const uint8* src_v, int src_stride_v, 74 | uint8* dst_argb, int dst_stride_argb, 75 | int width, int height); 76 | 77 | // Convert I444 to ABGR. 78 | LIBYUV_API 79 | int I444ToABGR(const uint8* src_y, int src_stride_y, 80 | const uint8* src_u, int src_stride_u, 81 | const uint8* src_v, int src_stride_v, 82 | uint8* dst_abgr, int dst_stride_abgr, 83 | int width, int height); 84 | 85 | // Convert I420 with Alpha to preattenuated ARGB. 86 | LIBYUV_API 87 | int I420AlphaToARGB(const uint8* src_y, int src_stride_y, 88 | const uint8* src_u, int src_stride_u, 89 | const uint8* src_v, int src_stride_v, 90 | const uint8* src_a, int src_stride_a, 91 | uint8* dst_argb, int dst_stride_argb, 92 | int width, int height, int attenuate); 93 | 94 | // Convert I420 with Alpha to preattenuated ABGR. 95 | LIBYUV_API 96 | int I420AlphaToABGR(const uint8* src_y, int src_stride_y, 97 | const uint8* src_u, int src_stride_u, 98 | const uint8* src_v, int src_stride_v, 99 | const uint8* src_a, int src_stride_a, 100 | uint8* dst_abgr, int dst_stride_abgr, 101 | int width, int height, int attenuate); 102 | 103 | // Convert I400 (grey) to ARGB. Reverse of ARGBToI400. 104 | LIBYUV_API 105 | int I400ToARGB(const uint8* src_y, int src_stride_y, 106 | uint8* dst_argb, int dst_stride_argb, 107 | int width, int height); 108 | 109 | // Convert J400 (jpeg grey) to ARGB. 110 | LIBYUV_API 111 | int J400ToARGB(const uint8* src_y, int src_stride_y, 112 | uint8* dst_argb, int dst_stride_argb, 113 | int width, int height); 114 | 115 | // Alias. 116 | #define YToARGB I400ToARGB 117 | 118 | // Convert NV12 to ARGB. 119 | LIBYUV_API 120 | int NV12ToARGB(const uint8* src_y, int src_stride_y, 121 | const uint8* src_uv, int src_stride_uv, 122 | uint8* dst_argb, int dst_stride_argb, 123 | int width, int height); 124 | 125 | // Convert NV21 to ARGB. 126 | LIBYUV_API 127 | int NV21ToARGB(const uint8* src_y, int src_stride_y, 128 | const uint8* src_vu, int src_stride_vu, 129 | uint8* dst_argb, int dst_stride_argb, 130 | int width, int height); 131 | 132 | // Convert M420 to ARGB. 133 | LIBYUV_API 134 | int M420ToARGB(const uint8* src_m420, int src_stride_m420, 135 | uint8* dst_argb, int dst_stride_argb, 136 | int width, int height); 137 | 138 | // Convert YUY2 to ARGB. 139 | LIBYUV_API 140 | int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2, 141 | uint8* dst_argb, int dst_stride_argb, 142 | int width, int height); 143 | 144 | // Convert UYVY to ARGB. 145 | LIBYUV_API 146 | int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy, 147 | uint8* dst_argb, int dst_stride_argb, 148 | int width, int height); 149 | 150 | // Convert J420 to ARGB. 151 | LIBYUV_API 152 | int J420ToARGB(const uint8* src_y, int src_stride_y, 153 | const uint8* src_u, int src_stride_u, 154 | const uint8* src_v, int src_stride_v, 155 | uint8* dst_argb, int dst_stride_argb, 156 | int width, int height); 157 | 158 | // Convert J422 to ARGB. 159 | LIBYUV_API 160 | int J422ToARGB(const uint8* src_y, int src_stride_y, 161 | const uint8* src_u, int src_stride_u, 162 | const uint8* src_v, int src_stride_v, 163 | uint8* dst_argb, int dst_stride_argb, 164 | int width, int height); 165 | 166 | // Convert J420 to ABGR. 167 | LIBYUV_API 168 | int J420ToABGR(const uint8* src_y, int src_stride_y, 169 | const uint8* src_u, int src_stride_u, 170 | const uint8* src_v, int src_stride_v, 171 | uint8* dst_abgr, int dst_stride_abgr, 172 | int width, int height); 173 | 174 | // Convert J422 to ABGR. 175 | LIBYUV_API 176 | int J422ToABGR(const uint8* src_y, int src_stride_y, 177 | const uint8* src_u, int src_stride_u, 178 | const uint8* src_v, int src_stride_v, 179 | uint8* dst_abgr, int dst_stride_abgr, 180 | int width, int height); 181 | 182 | // Convert H420 to ARGB. 183 | LIBYUV_API 184 | int H420ToARGB(const uint8* src_y, int src_stride_y, 185 | const uint8* src_u, int src_stride_u, 186 | const uint8* src_v, int src_stride_v, 187 | uint8* dst_argb, int dst_stride_argb, 188 | int width, int height); 189 | 190 | // Convert H422 to ARGB. 191 | LIBYUV_API 192 | int H422ToARGB(const uint8* src_y, int src_stride_y, 193 | const uint8* src_u, int src_stride_u, 194 | const uint8* src_v, int src_stride_v, 195 | uint8* dst_argb, int dst_stride_argb, 196 | int width, int height); 197 | 198 | // Convert H420 to ABGR. 199 | LIBYUV_API 200 | int H420ToABGR(const uint8* src_y, int src_stride_y, 201 | const uint8* src_u, int src_stride_u, 202 | const uint8* src_v, int src_stride_v, 203 | uint8* dst_abgr, int dst_stride_abgr, 204 | int width, int height); 205 | 206 | // Convert H422 to ABGR. 207 | LIBYUV_API 208 | int H422ToABGR(const uint8* src_y, int src_stride_y, 209 | const uint8* src_u, int src_stride_u, 210 | const uint8* src_v, int src_stride_v, 211 | uint8* dst_abgr, int dst_stride_abgr, 212 | int width, int height); 213 | 214 | // BGRA little endian (argb in memory) to ARGB. 215 | LIBYUV_API 216 | int BGRAToARGB(const uint8* src_frame, int src_stride_frame, 217 | uint8* dst_argb, int dst_stride_argb, 218 | int width, int height); 219 | 220 | // ABGR little endian (rgba in memory) to ARGB. 221 | LIBYUV_API 222 | int ABGRToARGB(const uint8* src_frame, int src_stride_frame, 223 | uint8* dst_argb, int dst_stride_argb, 224 | int width, int height); 225 | 226 | // RGBA little endian (abgr in memory) to ARGB. 227 | LIBYUV_API 228 | int RGBAToARGB(const uint8* src_frame, int src_stride_frame, 229 | uint8* dst_argb, int dst_stride_argb, 230 | int width, int height); 231 | 232 | // Deprecated function name. 233 | #define BG24ToARGB RGB24ToARGB 234 | 235 | // RGB little endian (bgr in memory) to ARGB. 236 | LIBYUV_API 237 | int RGB24ToARGB(const uint8* src_frame, int src_stride_frame, 238 | uint8* dst_argb, int dst_stride_argb, 239 | int width, int height); 240 | 241 | // RGB big endian (rgb in memory) to ARGB. 242 | LIBYUV_API 243 | int RAWToARGB(const uint8* src_frame, int src_stride_frame, 244 | uint8* dst_argb, int dst_stride_argb, 245 | int width, int height); 246 | 247 | // RGB16 (RGBP fourcc) little endian to ARGB. 248 | LIBYUV_API 249 | int RGB565ToARGB(const uint8* src_frame, int src_stride_frame, 250 | uint8* dst_argb, int dst_stride_argb, 251 | int width, int height); 252 | 253 | // RGB15 (RGBO fourcc) little endian to ARGB. 254 | LIBYUV_API 255 | int ARGB1555ToARGB(const uint8* src_frame, int src_stride_frame, 256 | uint8* dst_argb, int dst_stride_argb, 257 | int width, int height); 258 | 259 | // RGB12 (R444 fourcc) little endian to ARGB. 260 | LIBYUV_API 261 | int ARGB4444ToARGB(const uint8* src_frame, int src_stride_frame, 262 | uint8* dst_argb, int dst_stride_argb, 263 | int width, int height); 264 | 265 | #ifdef HAVE_JPEG 266 | // src_width/height provided by capture 267 | // dst_width/height for clipping determine final size. 268 | LIBYUV_API 269 | int MJPGToARGB(const uint8* sample, size_t sample_size, 270 | uint8* dst_argb, int dst_stride_argb, 271 | int src_width, int src_height, 272 | int dst_width, int dst_height); 273 | #endif 274 | 275 | // Convert camera sample to ARGB with cropping, rotation and vertical flip. 276 | // "src_size" is needed to parse MJPG. 277 | // "dst_stride_argb" number of bytes in a row of the dst_argb plane. 278 | // Normally this would be the same as dst_width, with recommended alignment 279 | // to 16 bytes for better efficiency. 280 | // If rotation of 90 or 270 is used, stride is affected. The caller should 281 | // allocate the I420 buffer according to rotation. 282 | // "dst_stride_u" number of bytes in a row of the dst_u plane. 283 | // Normally this would be the same as (dst_width + 1) / 2, with 284 | // recommended alignment to 16 bytes for better efficiency. 285 | // If rotation of 90 or 270 is used, stride is affected. 286 | // "crop_x" and "crop_y" are starting position for cropping. 287 | // To center, crop_x = (src_width - dst_width) / 2 288 | // crop_y = (src_height - dst_height) / 2 289 | // "src_width" / "src_height" is size of src_frame in pixels. 290 | // "src_height" can be negative indicating a vertically flipped image source. 291 | // "crop_width" / "crop_height" is the size to crop the src to. 292 | // Must be less than or equal to src_width/src_height 293 | // Cropping parameters are pre-rotation. 294 | // "rotation" can be 0, 90, 180 or 270. 295 | // "format" is a fourcc. ie 'I420', 'YUY2' 296 | // Returns 0 for successful; -1 for invalid parameter. Non-zero for failure. 297 | LIBYUV_API 298 | int ConvertToARGB(const uint8* src_frame, size_t src_size, 299 | uint8* dst_argb, int dst_stride_argb, 300 | int crop_x, int crop_y, 301 | int src_width, int src_height, 302 | int crop_width, int crop_height, 303 | enum RotationMode rotation, 304 | uint32 format); 305 | 306 | #ifdef __cplusplus 307 | } // extern "C" 308 | } // namespace libyuv 309 | #endif 310 | 311 | #endif // INCLUDE_LIBYUV_CONVERT_ARGB_H_ 312 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/convert_from.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_CONVERT_FROM_H_ 12 | #define INCLUDE_LIBYUV_CONVERT_FROM_H_ 13 | 14 | #include "basic_types.h" 15 | #include "rotate.h" 16 | 17 | #ifdef __cplusplus 18 | namespace libyuv { 19 | extern "C" { 20 | #endif 21 | 22 | // See Also convert.h for conversions from formats to I420. 23 | 24 | // I420Copy in convert to I420ToI420. 25 | 26 | LIBYUV_API 27 | int I420ToI422(const uint8* src_y, int src_stride_y, 28 | const uint8* src_u, int src_stride_u, 29 | const uint8* src_v, int src_stride_v, 30 | uint8* dst_y, int dst_stride_y, 31 | uint8* dst_u, int dst_stride_u, 32 | uint8* dst_v, int dst_stride_v, 33 | int width, int height); 34 | 35 | LIBYUV_API 36 | int I420ToI444(const uint8* src_y, int src_stride_y, 37 | const uint8* src_u, int src_stride_u, 38 | const uint8* src_v, int src_stride_v, 39 | uint8* dst_y, int dst_stride_y, 40 | uint8* dst_u, int dst_stride_u, 41 | uint8* dst_v, int dst_stride_v, 42 | int width, int height); 43 | 44 | // Copy to I400. Source can be I420, I422, I444, I400, NV12 or NV21. 45 | LIBYUV_API 46 | int I400Copy(const uint8* src_y, int src_stride_y, 47 | uint8* dst_y, int dst_stride_y, 48 | int width, int height); 49 | 50 | LIBYUV_API 51 | int I420ToNV12(const uint8* src_y, int src_stride_y, 52 | const uint8* src_u, int src_stride_u, 53 | const uint8* src_v, int src_stride_v, 54 | uint8* dst_y, int dst_stride_y, 55 | uint8* dst_uv, int dst_stride_uv, 56 | int width, int height); 57 | 58 | LIBYUV_API 59 | int I420ToNV21(const uint8* src_y, int src_stride_y, 60 | const uint8* src_u, int src_stride_u, 61 | const uint8* src_v, int src_stride_v, 62 | uint8* dst_y, int dst_stride_y, 63 | uint8* dst_vu, int dst_stride_vu, 64 | int width, int height); 65 | 66 | LIBYUV_API 67 | int I420ToYUY2(const uint8* src_y, int src_stride_y, 68 | const uint8* src_u, int src_stride_u, 69 | const uint8* src_v, int src_stride_v, 70 | uint8* dst_frame, int dst_stride_frame, 71 | int width, int height); 72 | 73 | LIBYUV_API 74 | int I420ToUYVY(const uint8* src_y, int src_stride_y, 75 | const uint8* src_u, int src_stride_u, 76 | const uint8* src_v, int src_stride_v, 77 | uint8* dst_frame, int dst_stride_frame, 78 | int width, int height); 79 | 80 | LIBYUV_API 81 | int I420ToARGB(const uint8* src_y, int src_stride_y, 82 | const uint8* src_u, int src_stride_u, 83 | const uint8* src_v, int src_stride_v, 84 | uint8* dst_argb, int dst_stride_argb, 85 | int width, int height); 86 | 87 | LIBYUV_API 88 | int I420ToBGRA(const uint8* src_y, int src_stride_y, 89 | const uint8* src_u, int src_stride_u, 90 | const uint8* src_v, int src_stride_v, 91 | uint8* dst_argb, int dst_stride_argb, 92 | int width, int height); 93 | 94 | LIBYUV_API 95 | int I420ToABGR(const uint8* src_y, int src_stride_y, 96 | const uint8* src_u, int src_stride_u, 97 | const uint8* src_v, int src_stride_v, 98 | uint8* dst_argb, int dst_stride_argb, 99 | int width, int height); 100 | 101 | LIBYUV_API 102 | int I420ToRGBA(const uint8* src_y, int src_stride_y, 103 | const uint8* src_u, int src_stride_u, 104 | const uint8* src_v, int src_stride_v, 105 | uint8* dst_rgba, int dst_stride_rgba, 106 | int width, int height); 107 | 108 | LIBYUV_API 109 | int I420ToRGB24(const uint8* src_y, int src_stride_y, 110 | const uint8* src_u, int src_stride_u, 111 | const uint8* src_v, int src_stride_v, 112 | uint8* dst_frame, int dst_stride_frame, 113 | int width, int height); 114 | 115 | LIBYUV_API 116 | int I420ToRAW(const uint8* src_y, int src_stride_y, 117 | const uint8* src_u, int src_stride_u, 118 | const uint8* src_v, int src_stride_v, 119 | uint8* dst_frame, int dst_stride_frame, 120 | int width, int height); 121 | 122 | LIBYUV_API 123 | int I420ToRGB565(const uint8* src_y, int src_stride_y, 124 | const uint8* src_u, int src_stride_u, 125 | const uint8* src_v, int src_stride_v, 126 | uint8* dst_frame, int dst_stride_frame, 127 | int width, int height); 128 | 129 | // Convert I420 To RGB565 with 4x4 dither matrix (16 bytes). 130 | // Values in dither matrix from 0 to 7 recommended. 131 | // The order of the dither matrix is first byte is upper left. 132 | 133 | LIBYUV_API 134 | int I420ToRGB565Dither(const uint8* src_y, int src_stride_y, 135 | const uint8* src_u, int src_stride_u, 136 | const uint8* src_v, int src_stride_v, 137 | uint8* dst_frame, int dst_stride_frame, 138 | const uint8* dither4x4, int width, int height); 139 | 140 | LIBYUV_API 141 | int I420ToARGB1555(const uint8* src_y, int src_stride_y, 142 | const uint8* src_u, int src_stride_u, 143 | const uint8* src_v, int src_stride_v, 144 | uint8* dst_frame, int dst_stride_frame, 145 | int width, int height); 146 | 147 | LIBYUV_API 148 | int I420ToARGB4444(const uint8* src_y, int src_stride_y, 149 | const uint8* src_u, int src_stride_u, 150 | const uint8* src_v, int src_stride_v, 151 | uint8* dst_frame, int dst_stride_frame, 152 | int width, int height); 153 | 154 | // Convert I420 to specified format. 155 | // "dst_sample_stride" is bytes in a row for the destination. Pass 0 if the 156 | // buffer has contiguous rows. Can be negative. A multiple of 16 is optimal. 157 | LIBYUV_API 158 | int ConvertFromI420(const uint8* y, int y_stride, 159 | const uint8* u, int u_stride, 160 | const uint8* v, int v_stride, 161 | uint8* dst_sample, int dst_sample_stride, 162 | int width, int height, 163 | uint32 format); 164 | 165 | #ifdef __cplusplus 166 | } // extern "C" 167 | } // namespace libyuv 168 | #endif 169 | 170 | #endif // INCLUDE_LIBYUV_CONVERT_FROM_H_ 171 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/convert_from_argb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_ 12 | #define INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_ 13 | 14 | #include "basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Copy ARGB to ARGB. 22 | #define ARGBToARGB ARGBCopy 23 | LIBYUV_API 24 | int ARGBCopy(const uint8* src_argb, int src_stride_argb, 25 | uint8* dst_argb, int dst_stride_argb, 26 | int width, int height); 27 | 28 | // Convert ARGB To BGRA. 29 | LIBYUV_API 30 | int ARGBToBGRA(const uint8* src_argb, int src_stride_argb, 31 | uint8* dst_bgra, int dst_stride_bgra, 32 | int width, int height); 33 | 34 | // Convert ARGB To ABGR. 35 | LIBYUV_API 36 | int ARGBToABGR(const uint8* src_argb, int src_stride_argb, 37 | uint8* dst_abgr, int dst_stride_abgr, 38 | int width, int height); 39 | 40 | // Convert ARGB To RGBA. 41 | LIBYUV_API 42 | int ARGBToRGBA(const uint8* src_argb, int src_stride_argb, 43 | uint8* dst_rgba, int dst_stride_rgba, 44 | int width, int height); 45 | 46 | // Convert ARGB To RGB24. 47 | LIBYUV_API 48 | int ARGBToRGB24(const uint8* src_argb, int src_stride_argb, 49 | uint8* dst_rgb24, int dst_stride_rgb24, 50 | int width, int height); 51 | 52 | // Convert ARGB To RAW. 53 | LIBYUV_API 54 | int ARGBToRAW(const uint8* src_argb, int src_stride_argb, 55 | uint8* dst_rgb, int dst_stride_rgb, 56 | int width, int height); 57 | 58 | // Convert ARGB To RGB565. 59 | LIBYUV_API 60 | int ARGBToRGB565(const uint8* src_argb, int src_stride_argb, 61 | uint8* dst_rgb565, int dst_stride_rgb565, 62 | int width, int height); 63 | 64 | // Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes). 65 | // Values in dither matrix from 0 to 7 recommended. 66 | // The order of the dither matrix is first byte is upper left. 67 | // TODO(fbarchard): Consider pointer to 2d array for dither4x4. 68 | // const uint8(*dither)[4][4]; 69 | LIBYUV_API 70 | int ARGBToRGB565Dither(const uint8* src_argb, int src_stride_argb, 71 | uint8* dst_rgb565, int dst_stride_rgb565, 72 | const uint8* dither4x4, int width, int height); 73 | 74 | // Convert ARGB To ARGB1555. 75 | LIBYUV_API 76 | int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb, 77 | uint8* dst_argb1555, int dst_stride_argb1555, 78 | int width, int height); 79 | 80 | // Convert ARGB To ARGB4444. 81 | LIBYUV_API 82 | int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb, 83 | uint8* dst_argb4444, int dst_stride_argb4444, 84 | int width, int height); 85 | 86 | // Convert ARGB To I444. 87 | LIBYUV_API 88 | int ARGBToI444(const uint8* src_argb, int src_stride_argb, 89 | uint8* dst_y, int dst_stride_y, 90 | uint8* dst_u, int dst_stride_u, 91 | uint8* dst_v, int dst_stride_v, 92 | int width, int height); 93 | 94 | // Convert ARGB To I422. 95 | LIBYUV_API 96 | int ARGBToI422(const uint8* src_argb, int src_stride_argb, 97 | uint8* dst_y, int dst_stride_y, 98 | uint8* dst_u, int dst_stride_u, 99 | uint8* dst_v, int dst_stride_v, 100 | int width, int height); 101 | 102 | // Convert ARGB To I420. (also in convert.h) 103 | LIBYUV_API 104 | int ARGBToI420(const uint8* src_argb, int src_stride_argb, 105 | uint8* dst_y, int dst_stride_y, 106 | uint8* dst_u, int dst_stride_u, 107 | uint8* dst_v, int dst_stride_v, 108 | int width, int height); 109 | 110 | // Convert ARGB to J420. (JPeg full range I420). 111 | LIBYUV_API 112 | int ARGBToJ420(const uint8* src_argb, int src_stride_argb, 113 | uint8* dst_yj, int dst_stride_yj, 114 | uint8* dst_u, int dst_stride_u, 115 | uint8* dst_v, int dst_stride_v, 116 | int width, int height); 117 | 118 | // Convert ARGB to J422. 119 | LIBYUV_API 120 | int ARGBToJ422(const uint8* src_argb, int src_stride_argb, 121 | uint8* dst_yj, int dst_stride_yj, 122 | uint8* dst_u, int dst_stride_u, 123 | uint8* dst_v, int dst_stride_v, 124 | int width, int height); 125 | 126 | // Convert ARGB to J400. (JPeg full range). 127 | LIBYUV_API 128 | int ARGBToJ400(const uint8* src_argb, int src_stride_argb, 129 | uint8* dst_yj, int dst_stride_yj, 130 | int width, int height); 131 | 132 | // Convert ARGB to I400. 133 | LIBYUV_API 134 | int ARGBToI400(const uint8* src_argb, int src_stride_argb, 135 | uint8* dst_y, int dst_stride_y, 136 | int width, int height); 137 | 138 | // Convert ARGB to G. (Reverse of J400toARGB, which replicates G back to ARGB) 139 | LIBYUV_API 140 | int ARGBToG(const uint8* src_argb, int src_stride_argb, 141 | uint8* dst_g, int dst_stride_g, 142 | int width, int height); 143 | 144 | // Convert ARGB To NV12. 145 | LIBYUV_API 146 | int ARGBToNV12(const uint8* src_argb, int src_stride_argb, 147 | uint8* dst_y, int dst_stride_y, 148 | uint8* dst_uv, int dst_stride_uv, 149 | int width, int height); 150 | 151 | // Convert ARGB To NV21. 152 | LIBYUV_API 153 | int ARGBToNV21(const uint8* src_argb, int src_stride_argb, 154 | uint8* dst_y, int dst_stride_y, 155 | uint8* dst_vu, int dst_stride_vu, 156 | int width, int height); 157 | 158 | // Convert ARGB To NV21. 159 | LIBYUV_API 160 | int ARGBToNV21(const uint8* src_argb, int src_stride_argb, 161 | uint8* dst_y, int dst_stride_y, 162 | uint8* dst_vu, int dst_stride_vu, 163 | int width, int height); 164 | 165 | // Convert ARGB To YUY2. 166 | LIBYUV_API 167 | int ARGBToYUY2(const uint8* src_argb, int src_stride_argb, 168 | uint8* dst_yuy2, int dst_stride_yuy2, 169 | int width, int height); 170 | 171 | // Convert ARGB To UYVY. 172 | LIBYUV_API 173 | int ARGBToUYVY(const uint8* src_argb, int src_stride_argb, 174 | uint8* dst_uyvy, int dst_stride_uyvy, 175 | int width, int height); 176 | 177 | #ifdef __cplusplus 178 | } // extern "C" 179 | } // namespace libyuv 180 | #endif 181 | 182 | #endif // INCLUDE_LIBYUV_CONVERT_FROM_ARGB_H_ 183 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/cpu_id.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_CPU_ID_H_ 12 | #define INCLUDE_LIBYUV_CPU_ID_H_ 13 | 14 | #include "basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Internal flag to indicate cpuid requires initialization. 22 | static const int kCpuInitialized = 0x1; 23 | 24 | // These flags are only valid on ARM processors. 25 | static const int kCpuHasARM = 0x2; 26 | static const int kCpuHasNEON = 0x4; 27 | // 0x8 reserved for future ARM flag. 28 | 29 | // These flags are only valid on x86 processors. 30 | static const int kCpuHasX86 = 0x10; 31 | static const int kCpuHasSSE2 = 0x20; 32 | static const int kCpuHasSSSE3 = 0x40; 33 | static const int kCpuHasSSE41 = 0x80; 34 | static const int kCpuHasSSE42 = 0x100; // unused at this time. 35 | static const int kCpuHasAVX = 0x200; 36 | static const int kCpuHasAVX2 = 0x400; 37 | static const int kCpuHasERMS = 0x800; 38 | static const int kCpuHasFMA3 = 0x1000; 39 | static const int kCpuHasAVX3 = 0x2000; 40 | static const int kCpuHasF16C = 0x4000; 41 | 42 | // 0x8000 reserved for future X86 flags. 43 | 44 | // These flags are only valid on MIPS processors. 45 | static const int kCpuHasMIPS = 0x10000; 46 | static const int kCpuHasDSPR2 = 0x20000; 47 | static const int kCpuHasMSA = 0x40000; 48 | 49 | // Internal function used to auto-init. 50 | LIBYUV_API 51 | int InitCpuFlags(void); 52 | 53 | // Internal function for parsing /proc/cpuinfo. 54 | LIBYUV_API 55 | int ArmCpuCaps(const char* cpuinfo_name); 56 | 57 | // Detect CPU has SSE2 etc. 58 | // Test_flag parameter should be one of kCpuHas constants above. 59 | // returns non-zero if instruction set is detected 60 | static __inline int TestCpuFlag(int test_flag) { 61 | LIBYUV_API extern int cpu_info_; 62 | return (!cpu_info_ ? InitCpuFlags() : cpu_info_) & test_flag; 63 | } 64 | 65 | // For testing, allow CPU flags to be disabled. 66 | // ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3. 67 | // MaskCpuFlags(-1) to enable all cpu specific optimizations. 68 | // MaskCpuFlags(1) to disable all cpu specific optimizations. 69 | LIBYUV_API 70 | void MaskCpuFlags(int enable_flags); 71 | 72 | // Low level cpuid for X86. Returns zeros on other CPUs. 73 | // eax is the info type that you want. 74 | // ecx is typically the cpu number, and should normally be zero. 75 | LIBYUV_API 76 | void CpuId(uint32 eax, uint32 ecx, uint32* cpu_info); 77 | 78 | #ifdef __cplusplus 79 | } // extern "C" 80 | } // namespace libyuv 81 | #endif 82 | 83 | #endif // INCLUDE_LIBYUV_CPU_ID_H_ 84 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/macros_msa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_MACROS_MSA_H_ 12 | #define INCLUDE_LIBYUV_MACROS_MSA_H_ 13 | 14 | #if !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) 15 | #include 16 | #include 17 | 18 | #if (__mips_isa_rev >= 6) 19 | #define LW(psrc) ({ \ 20 | uint8* psrc_lw_m = (uint8*) (psrc); /* NOLINT */ \ 21 | uint32 val_m; \ 22 | asm volatile ( \ 23 | "lw %[val_m], %[psrc_lw_m] \n\t" \ 24 | : [val_m] "=r" (val_m) \ 25 | : [psrc_lw_m] "m" (*psrc_lw_m) \ 26 | ); \ 27 | val_m; \ 28 | }) 29 | 30 | #if (__mips == 64) 31 | #define LD(psrc) ({ \ 32 | uint8* psrc_ld_m = (uint8*) (psrc); /* NOLINT */ \ 33 | uint64 val_m = 0; \ 34 | asm volatile ( \ 35 | "ld %[val_m], %[psrc_ld_m] \n\t" \ 36 | : [val_m] "=r" (val_m) \ 37 | : [psrc_ld_m] "m" (*psrc_ld_m) \ 38 | ); \ 39 | val_m; \ 40 | }) 41 | #else // !(__mips == 64) 42 | #define LD(psrc) ({ \ 43 | uint8* psrc_ld_m = (uint8*) (psrc); /* NOLINT */ \ 44 | uint32 val0_m, val1_m; \ 45 | uint64 val_m = 0; \ 46 | val0_m = LW(psrc_ld_m); \ 47 | val1_m = LW(psrc_ld_m + 4); \ 48 | val_m = (uint64) (val1_m); /* NOLINT */ \ 49 | val_m = (uint64) ((val_m << 32) & 0xFFFFFFFF00000000); /* NOLINT */ \ 50 | val_m = (uint64) (val_m | (uint64) val0_m); /* NOLINT */ \ 51 | val_m; \ 52 | }) 53 | #endif // (__mips == 64) 54 | #else // !(__mips_isa_rev >= 6) 55 | #define LW(psrc) ({ \ 56 | uint8* psrc_lw_m = (uint8*) (psrc); /* NOLINT */ \ 57 | uint32 val_m; \ 58 | asm volatile ( \ 59 | "ulw %[val_m], %[psrc_lw_m] \n\t" \ 60 | : [val_m] "=r" (val_m) \ 61 | : [psrc_lw_m] "m" (*psrc_lw_m) \ 62 | ); \ 63 | val_m; \ 64 | }) 65 | 66 | #if (__mips == 64) 67 | #define LD(psrc) ({ \ 68 | uint8* psrc_ld_m = (uint8*) (psrc); /* NOLINT */ \ 69 | uint64 val_m = 0; \ 70 | asm volatile ( \ 71 | "uld %[val_m], %[psrc_ld_m] \n\t" \ 72 | : [val_m] "=r" (val_m) \ 73 | : [psrc_ld_m] "m" (*psrc_ld_m) \ 74 | ); \ 75 | val_m; \ 76 | }) 77 | #else // !(__mips == 64) 78 | #define LD(psrc) ({ \ 79 | uint8* psrc_ld_m = (uint8*) (psrc); /* NOLINT */ \ 80 | uint32 val0_m, val1_m; \ 81 | uint64 val_m = 0; \ 82 | val0_m = LW(psrc_ld_m); \ 83 | val1_m = LW(psrc_ld_m + 4); \ 84 | val_m = (uint64) (val1_m); /* NOLINT */ \ 85 | val_m = (uint64) ((val_m << 32) & 0xFFFFFFFF00000000); /* NOLINT */ \ 86 | val_m = (uint64) (val_m | (uint64) val0_m); /* NOLINT */ \ 87 | val_m; \ 88 | }) 89 | #endif // (__mips == 64) 90 | #endif // (__mips_isa_rev >= 6) 91 | 92 | // TODO(fbarchard): Consider removing __VAR_ARGS versions. 93 | #define LD_B(RTYPE, psrc) *((RTYPE*)(psrc)) /* NOLINT */ 94 | #define LD_UB(...) LD_B(v16u8, __VA_ARGS__) 95 | 96 | #define ST_B(RTYPE, in, pdst) *((RTYPE*)(pdst)) = (in) /* NOLINT */ 97 | #define ST_UB(...) ST_B(v16u8, __VA_ARGS__) 98 | 99 | /* Description : Load two vectors with 16 'byte' sized elements 100 | Arguments : Inputs - psrc, stride 101 | Outputs - out0, out1 102 | Return Type - as per RTYPE 103 | Details : Load 16 byte elements in 'out0' from (psrc) 104 | Load 16 byte elements in 'out1' from (psrc + stride) 105 | */ 106 | #define LD_B2(RTYPE, psrc, stride, out0, out1) { \ 107 | out0 = LD_B(RTYPE, (psrc)); \ 108 | out1 = LD_B(RTYPE, (psrc) + stride); \ 109 | } 110 | #define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__) 111 | 112 | #define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) { \ 113 | LD_B2(RTYPE, (psrc), stride, out0, out1); \ 114 | LD_B2(RTYPE, (psrc) + 2 * stride , stride, out2, out3); \ 115 | } 116 | #define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__) 117 | 118 | /* Description : Store two vectors with stride each having 16 'byte' sized 119 | elements 120 | Arguments : Inputs - in0, in1, pdst, stride 121 | Details : Store 16 byte elements from 'in0' to (pdst) 122 | Store 16 byte elements from 'in1' to (pdst + stride) 123 | */ 124 | #define ST_B2(RTYPE, in0, in1, pdst, stride) { \ 125 | ST_B(RTYPE, in0, (pdst)); \ 126 | ST_B(RTYPE, in1, (pdst) + stride); \ 127 | } 128 | #define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__) 129 | 130 | #define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride) { \ 131 | ST_B2(RTYPE, in0, in1, (pdst), stride); \ 132 | ST_B2(RTYPE, in2, in3, (pdst) + 2 * stride, stride); \ 133 | } 134 | #define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__) 135 | 136 | // TODO(fbarchard): Consider using __msa_vshf_b and __msa_ilvr_b directly. 137 | /* Description : Shuffle byte vector elements as per mask vector 138 | Arguments : Inputs - in0, in1, in2, in3, mask0, mask1 139 | Outputs - out0, out1 140 | Return Type - as per RTYPE 141 | Details : Byte elements from 'in0' & 'in1' are copied selectively to 142 | 'out0' as per control vector 'mask0' 143 | */ 144 | #define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) { \ 145 | out0 = (RTYPE) __msa_vshf_b((v16i8) mask0, (v16i8) in1, (v16i8) in0); \ 146 | out1 = (RTYPE) __msa_vshf_b((v16i8) mask1, (v16i8) in3, (v16i8) in2); \ 147 | } 148 | #define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__) 149 | 150 | /* Description : Interleave both left and right half of input vectors 151 | Arguments : Inputs - in0, in1 152 | Outputs - out0, out1 153 | Return Type - as per RTYPE 154 | Details : Right half of byte elements from 'in0' and 'in1' are 155 | interleaved and written to 'out0' 156 | */ 157 | #define ILVRL_B2(RTYPE, in0, in1, out0, out1) { \ 158 | out0 = (RTYPE) __msa_ilvr_b((v16i8) in0, (v16i8) in1); \ 159 | out1 = (RTYPE) __msa_ilvl_b((v16i8) in0, (v16i8) in1); \ 160 | } 161 | #define ILVRL_B2_UB(...) ILVRL_B2(v16u8, __VA_ARGS__) 162 | 163 | #endif /* !defined(LIBYUV_DISABLE_MSA) && defined(__mips_msa) */ 164 | 165 | #endif // INCLUDE_LIBYUV_MACROS_MSA_H_ 166 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/mjpeg_decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_MJPEG_DECODER_H_ 12 | #define INCLUDE_LIBYUV_MJPEG_DECODER_H_ 13 | 14 | #include "basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | // NOTE: For a simplified public API use convert.h MJPGToI420(). 18 | 19 | struct jpeg_common_struct; 20 | struct jpeg_decompress_struct; 21 | struct jpeg_source_mgr; 22 | 23 | namespace libyuv { 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | LIBYUV_BOOL ValidateJpeg(const uint8* sample, size_t sample_size); 30 | 31 | #ifdef __cplusplus 32 | } // extern "C" 33 | #endif 34 | 35 | static const uint32 kUnknownDataSize = 0xFFFFFFFF; 36 | 37 | enum JpegSubsamplingType { 38 | kJpegYuv420, 39 | kJpegYuv422, 40 | kJpegYuv444, 41 | kJpegYuv400, 42 | kJpegUnknown 43 | }; 44 | 45 | struct Buffer { 46 | const uint8* data; 47 | int len; 48 | }; 49 | 50 | struct BufferVector { 51 | Buffer* buffers; 52 | int len; 53 | int pos; 54 | }; 55 | 56 | struct SetJmpErrorMgr; 57 | 58 | // MJPEG ("Motion JPEG") is a pseudo-standard video codec where the frames are 59 | // simply independent JPEG images with a fixed huffman table (which is omitted). 60 | // It is rarely used in video transmission, but is common as a camera capture 61 | // format, especially in Logitech devices. This class implements a decoder for 62 | // MJPEG frames. 63 | // 64 | // See http://tools.ietf.org/html/rfc2435 65 | class LIBYUV_API MJpegDecoder { 66 | public: 67 | typedef void (*CallbackFunction)(void* opaque, 68 | const uint8* const* data, 69 | const int* strides, 70 | int rows); 71 | 72 | static const int kColorSpaceUnknown; 73 | static const int kColorSpaceGrayscale; 74 | static const int kColorSpaceRgb; 75 | static const int kColorSpaceYCbCr; 76 | static const int kColorSpaceCMYK; 77 | static const int kColorSpaceYCCK; 78 | 79 | MJpegDecoder(); 80 | ~MJpegDecoder(); 81 | 82 | // Loads a new frame, reads its headers, and determines the uncompressed 83 | // image format. 84 | // Returns LIBYUV_TRUE if image looks valid and format is supported. 85 | // If return value is LIBYUV_TRUE, then the values for all the following 86 | // getters are populated. 87 | // src_len is the size of the compressed mjpeg frame in bytes. 88 | LIBYUV_BOOL LoadFrame(const uint8* src, size_t src_len); 89 | 90 | // Returns width of the last loaded frame in pixels. 91 | int GetWidth(); 92 | 93 | // Returns height of the last loaded frame in pixels. 94 | int GetHeight(); 95 | 96 | // Returns format of the last loaded frame. The return value is one of the 97 | // kColorSpace* constants. 98 | int GetColorSpace(); 99 | 100 | // Number of color components in the color space. 101 | int GetNumComponents(); 102 | 103 | // Sample factors of the n-th component. 104 | int GetHorizSampFactor(int component); 105 | 106 | int GetVertSampFactor(int component); 107 | 108 | int GetHorizSubSampFactor(int component); 109 | 110 | int GetVertSubSampFactor(int component); 111 | 112 | // Public for testability. 113 | int GetImageScanlinesPerImcuRow(); 114 | 115 | // Public for testability. 116 | int GetComponentScanlinesPerImcuRow(int component); 117 | 118 | // Width of a component in bytes. 119 | int GetComponentWidth(int component); 120 | 121 | // Height of a component. 122 | int GetComponentHeight(int component); 123 | 124 | // Width of a component in bytes with padding for DCTSIZE. Public for testing. 125 | int GetComponentStride(int component); 126 | 127 | // Size of a component in bytes. 128 | int GetComponentSize(int component); 129 | 130 | // Call this after LoadFrame() if you decide you don't want to decode it 131 | // after all. 132 | LIBYUV_BOOL UnloadFrame(); 133 | 134 | // Decodes the entire image into a one-buffer-per-color-component format. 135 | // dst_width must match exactly. dst_height must be <= to image height; if 136 | // less, the image is cropped. "planes" must have size equal to at least 137 | // GetNumComponents() and they must point to non-overlapping buffers of size 138 | // at least GetComponentSize(i). The pointers in planes are incremented 139 | // to point to after the end of the written data. 140 | // TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded. 141 | LIBYUV_BOOL DecodeToBuffers(uint8** planes, int dst_width, int dst_height); 142 | 143 | // Decodes the entire image and passes the data via repeated calls to a 144 | // callback function. Each call will get the data for a whole number of 145 | // image scanlines. 146 | // TODO(fbarchard): Add dst_x, dst_y to allow specific rect to be decoded. 147 | LIBYUV_BOOL DecodeToCallback(CallbackFunction fn, void* opaque, 148 | int dst_width, int dst_height); 149 | 150 | // The helper function which recognizes the jpeg sub-sampling type. 151 | static JpegSubsamplingType JpegSubsamplingTypeHelper( 152 | int* subsample_x, int* subsample_y, int number_of_components); 153 | 154 | private: 155 | void AllocOutputBuffers(int num_outbufs); 156 | void DestroyOutputBuffers(); 157 | 158 | LIBYUV_BOOL StartDecode(); 159 | LIBYUV_BOOL FinishDecode(); 160 | 161 | void SetScanlinePointers(uint8** data); 162 | LIBYUV_BOOL DecodeImcuRow(); 163 | 164 | int GetComponentScanlinePadding(int component); 165 | 166 | // A buffer holding the input data for a frame. 167 | Buffer buf_; 168 | BufferVector buf_vec_; 169 | 170 | jpeg_decompress_struct* decompress_struct_; 171 | jpeg_source_mgr* source_mgr_; 172 | SetJmpErrorMgr* error_mgr_; 173 | 174 | // LIBYUV_TRUE iff at least one component has scanline padding. (i.e., 175 | // GetComponentScanlinePadding() != 0.) 176 | LIBYUV_BOOL has_scanline_padding_; 177 | 178 | // Temporaries used to point to scanline outputs. 179 | int num_outbufs_; // Outermost size of all arrays below. 180 | uint8*** scanlines_; 181 | int* scanlines_sizes_; 182 | // Temporary buffer used for decoding when we can't decode directly to the 183 | // output buffers. Large enough for just one iMCU row. 184 | uint8** databuf_; 185 | int* databuf_strides_; 186 | }; 187 | 188 | } // namespace libyuv 189 | 190 | #endif // __cplusplus 191 | #endif // INCLUDE_LIBYUV_MJPEG_DECODER_H_ 192 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/planar_functions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_PLANAR_FUNCTIONS_H_ 12 | #define INCLUDE_LIBYUV_PLANAR_FUNCTIONS_H_ 13 | 14 | #include "basic_types.h" 15 | 16 | // TODO(fbarchard): Remove the following headers includes. 17 | #include "convert.h" 18 | #include "convert_argb.h" 19 | 20 | #ifdef __cplusplus 21 | namespace libyuv { 22 | extern "C" { 23 | #endif 24 | 25 | // Copy a plane of data. 26 | LIBYUV_API 27 | void CopyPlane(const uint8* src_y, int src_stride_y, 28 | uint8* dst_y, int dst_stride_y, 29 | int width, int height); 30 | 31 | LIBYUV_API 32 | void CopyPlane_16(const uint16* src_y, int src_stride_y, 33 | uint16* dst_y, int dst_stride_y, 34 | int width, int height); 35 | 36 | // Set a plane of data to a 32 bit value. 37 | LIBYUV_API 38 | void SetPlane(uint8* dst_y, int dst_stride_y, 39 | int width, int height, 40 | uint32 value); 41 | 42 | // Split interleaved UV plane into separate U and V planes. 43 | LIBYUV_API 44 | void SplitUVPlane(const uint8* src_uv, int src_stride_uv, 45 | uint8* dst_u, int dst_stride_u, 46 | uint8* dst_v, int dst_stride_v, 47 | int width, int height); 48 | 49 | // Merge separate U and V planes into one interleaved UV plane. 50 | LIBYUV_API 51 | void MergeUVPlane(const uint8* src_u, int src_stride_u, 52 | const uint8* src_v, int src_stride_v, 53 | uint8* dst_uv, int dst_stride_uv, 54 | int width, int height); 55 | 56 | // Copy I400. Supports inverting. 57 | LIBYUV_API 58 | int I400ToI400(const uint8* src_y, int src_stride_y, 59 | uint8* dst_y, int dst_stride_y, 60 | int width, int height); 61 | 62 | #define J400ToJ400 I400ToI400 63 | 64 | // Copy I422 to I422. 65 | #define I422ToI422 I422Copy 66 | LIBYUV_API 67 | int I422Copy(const uint8* src_y, int src_stride_y, 68 | const uint8* src_u, int src_stride_u, 69 | const uint8* src_v, int src_stride_v, 70 | uint8* dst_y, int dst_stride_y, 71 | uint8* dst_u, int dst_stride_u, 72 | uint8* dst_v, int dst_stride_v, 73 | int width, int height); 74 | 75 | // Copy I444 to I444. 76 | #define I444ToI444 I444Copy 77 | LIBYUV_API 78 | int I444Copy(const uint8* src_y, int src_stride_y, 79 | const uint8* src_u, int src_stride_u, 80 | const uint8* src_v, int src_stride_v, 81 | uint8* dst_y, int dst_stride_y, 82 | uint8* dst_u, int dst_stride_u, 83 | uint8* dst_v, int dst_stride_v, 84 | int width, int height); 85 | 86 | // Convert YUY2 to I422. 87 | LIBYUV_API 88 | int YUY2ToI422(const uint8* src_yuy2, int src_stride_yuy2, 89 | uint8* dst_y, int dst_stride_y, 90 | uint8* dst_u, int dst_stride_u, 91 | uint8* dst_v, int dst_stride_v, 92 | int width, int height); 93 | 94 | // Convert UYVY to I422. 95 | LIBYUV_API 96 | int UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy, 97 | uint8* dst_y, int dst_stride_y, 98 | uint8* dst_u, int dst_stride_u, 99 | uint8* dst_v, int dst_stride_v, 100 | int width, int height); 101 | 102 | LIBYUV_API 103 | int YUY2ToNV12(const uint8* src_yuy2, int src_stride_yuy2, 104 | uint8* dst_y, int dst_stride_y, 105 | uint8* dst_uv, int dst_stride_uv, 106 | int width, int height); 107 | 108 | LIBYUV_API 109 | int UYVYToNV12(const uint8* src_uyvy, int src_stride_uyvy, 110 | uint8* dst_y, int dst_stride_y, 111 | uint8* dst_uv, int dst_stride_uv, 112 | int width, int height); 113 | 114 | LIBYUV_API 115 | int YUY2ToY(const uint8* src_yuy2, int src_stride_yuy2, 116 | uint8* dst_y, int dst_stride_y, 117 | int width, int height); 118 | 119 | // Convert I420 to I400. (calls CopyPlane ignoring u/v). 120 | LIBYUV_API 121 | int I420ToI400(const uint8* src_y, int src_stride_y, 122 | const uint8* src_u, int src_stride_u, 123 | const uint8* src_v, int src_stride_v, 124 | uint8* dst_y, int dst_stride_y, 125 | int width, int height); 126 | 127 | // Alias 128 | #define J420ToJ400 I420ToI400 129 | #define I420ToI420Mirror I420Mirror 130 | 131 | // I420 mirror. 132 | LIBYUV_API 133 | int I420Mirror(const uint8* src_y, int src_stride_y, 134 | const uint8* src_u, int src_stride_u, 135 | const uint8* src_v, int src_stride_v, 136 | uint8* dst_y, int dst_stride_y, 137 | uint8* dst_u, int dst_stride_u, 138 | uint8* dst_v, int dst_stride_v, 139 | int width, int height); 140 | 141 | // Alias 142 | #define I400ToI400Mirror I400Mirror 143 | 144 | // I400 mirror. A single plane is mirrored horizontally. 145 | // Pass negative height to achieve 180 degree rotation. 146 | LIBYUV_API 147 | int I400Mirror(const uint8* src_y, int src_stride_y, 148 | uint8* dst_y, int dst_stride_y, 149 | int width, int height); 150 | 151 | // Alias 152 | #define ARGBToARGBMirror ARGBMirror 153 | 154 | // ARGB mirror. 155 | LIBYUV_API 156 | int ARGBMirror(const uint8* src_argb, int src_stride_argb, 157 | uint8* dst_argb, int dst_stride_argb, 158 | int width, int height); 159 | 160 | // Convert NV12 to RGB565. 161 | LIBYUV_API 162 | int NV12ToRGB565(const uint8* src_y, int src_stride_y, 163 | const uint8* src_uv, int src_stride_uv, 164 | uint8* dst_rgb565, int dst_stride_rgb565, 165 | int width, int height); 166 | 167 | // I422ToARGB is in convert_argb.h 168 | // Convert I422 to BGRA. 169 | LIBYUV_API 170 | int I422ToBGRA(const uint8* src_y, int src_stride_y, 171 | const uint8* src_u, int src_stride_u, 172 | const uint8* src_v, int src_stride_v, 173 | uint8* dst_bgra, int dst_stride_bgra, 174 | int width, int height); 175 | 176 | // Convert I422 to ABGR. 177 | LIBYUV_API 178 | int I422ToABGR(const uint8* src_y, int src_stride_y, 179 | const uint8* src_u, int src_stride_u, 180 | const uint8* src_v, int src_stride_v, 181 | uint8* dst_abgr, int dst_stride_abgr, 182 | int width, int height); 183 | 184 | // Convert I422 to RGBA. 185 | LIBYUV_API 186 | int I422ToRGBA(const uint8* src_y, int src_stride_y, 187 | const uint8* src_u, int src_stride_u, 188 | const uint8* src_v, int src_stride_v, 189 | uint8* dst_rgba, int dst_stride_rgba, 190 | int width, int height); 191 | 192 | // Alias 193 | #define RGB24ToRAW RAWToRGB24 194 | 195 | LIBYUV_API 196 | int RAWToRGB24(const uint8* src_raw, int src_stride_raw, 197 | uint8* dst_rgb24, int dst_stride_rgb24, 198 | int width, int height); 199 | 200 | // Draw a rectangle into I420. 201 | LIBYUV_API 202 | int I420Rect(uint8* dst_y, int dst_stride_y, 203 | uint8* dst_u, int dst_stride_u, 204 | uint8* dst_v, int dst_stride_v, 205 | int x, int y, int width, int height, 206 | int value_y, int value_u, int value_v); 207 | 208 | // Draw a rectangle into ARGB. 209 | LIBYUV_API 210 | int ARGBRect(uint8* dst_argb, int dst_stride_argb, 211 | int x, int y, int width, int height, uint32 value); 212 | 213 | // Convert ARGB to gray scale ARGB. 214 | LIBYUV_API 215 | int ARGBGrayTo(const uint8* src_argb, int src_stride_argb, 216 | uint8* dst_argb, int dst_stride_argb, 217 | int width, int height); 218 | 219 | // Make a rectangle of ARGB gray scale. 220 | LIBYUV_API 221 | int ARGBGray(uint8* dst_argb, int dst_stride_argb, 222 | int x, int y, int width, int height); 223 | 224 | // Make a rectangle of ARGB Sepia tone. 225 | LIBYUV_API 226 | int ARGBSepia(uint8* dst_argb, int dst_stride_argb, 227 | int x, int y, int width, int height); 228 | 229 | // Apply a matrix rotation to each ARGB pixel. 230 | // matrix_argb is 4 signed ARGB values. -128 to 127 representing -2 to 2. 231 | // The first 4 coefficients apply to B, G, R, A and produce B of the output. 232 | // The next 4 coefficients apply to B, G, R, A and produce G of the output. 233 | // The next 4 coefficients apply to B, G, R, A and produce R of the output. 234 | // The last 4 coefficients apply to B, G, R, A and produce A of the output. 235 | LIBYUV_API 236 | int ARGBColorMatrix(const uint8* src_argb, int src_stride_argb, 237 | uint8* dst_argb, int dst_stride_argb, 238 | const int8* matrix_argb, 239 | int width, int height); 240 | 241 | // Deprecated. Use ARGBColorMatrix instead. 242 | // Apply a matrix rotation to each ARGB pixel. 243 | // matrix_argb is 3 signed ARGB values. -128 to 127 representing -1 to 1. 244 | // The first 4 coefficients apply to B, G, R, A and produce B of the output. 245 | // The next 4 coefficients apply to B, G, R, A and produce G of the output. 246 | // The last 4 coefficients apply to B, G, R, A and produce R of the output. 247 | LIBYUV_API 248 | int RGBColorMatrix(uint8* dst_argb, int dst_stride_argb, 249 | const int8* matrix_rgb, 250 | int x, int y, int width, int height); 251 | 252 | // Apply a color table each ARGB pixel. 253 | // Table contains 256 ARGB values. 254 | LIBYUV_API 255 | int ARGBColorTable(uint8* dst_argb, int dst_stride_argb, 256 | const uint8* table_argb, 257 | int x, int y, int width, int height); 258 | 259 | // Apply a color table each ARGB pixel but preserve destination alpha. 260 | // Table contains 256 ARGB values. 261 | LIBYUV_API 262 | int RGBColorTable(uint8* dst_argb, int dst_stride_argb, 263 | const uint8* table_argb, 264 | int x, int y, int width, int height); 265 | 266 | // Apply a luma/color table each ARGB pixel but preserve destination alpha. 267 | // Table contains 32768 values indexed by [Y][C] where 7 it 7 bit luma from 268 | // RGB (YJ style) and C is an 8 bit color component (R, G or B). 269 | LIBYUV_API 270 | int ARGBLumaColorTable(const uint8* src_argb, int src_stride_argb, 271 | uint8* dst_argb, int dst_stride_argb, 272 | const uint8* luma_rgb_table, 273 | int width, int height); 274 | 275 | // Apply a 3 term polynomial to ARGB values. 276 | // poly points to a 4x4 matrix. The first row is constants. The 2nd row is 277 | // coefficients for b, g, r and a. The 3rd row is coefficients for b squared, 278 | // g squared, r squared and a squared. The 4rd row is coefficients for b to 279 | // the 3, g to the 3, r to the 3 and a to the 3. The values are summed and 280 | // result clamped to 0 to 255. 281 | // A polynomial approximation can be dirived using software such as 'R'. 282 | 283 | LIBYUV_API 284 | int ARGBPolynomial(const uint8* src_argb, int src_stride_argb, 285 | uint8* dst_argb, int dst_stride_argb, 286 | const float* poly, 287 | int width, int height); 288 | 289 | // Convert plane of 16 bit shorts to half floats. 290 | // Source values are multiplied by scale before storing as half float. 291 | LIBYUV_API 292 | int HalfFloatPlane(const uint16* src_y, int src_stride_y, 293 | uint16* dst_y, int dst_stride_y, 294 | float scale, 295 | int width, int height); 296 | 297 | // Quantize a rectangle of ARGB. Alpha unaffected. 298 | // scale is a 16 bit fractional fixed point scaler between 0 and 65535. 299 | // interval_size should be a value between 1 and 255. 300 | // interval_offset should be a value between 0 and 255. 301 | LIBYUV_API 302 | int ARGBQuantize(uint8* dst_argb, int dst_stride_argb, 303 | int scale, int interval_size, int interval_offset, 304 | int x, int y, int width, int height); 305 | 306 | // Copy ARGB to ARGB. 307 | LIBYUV_API 308 | int ARGBCopy(const uint8* src_argb, int src_stride_argb, 309 | uint8* dst_argb, int dst_stride_argb, 310 | int width, int height); 311 | 312 | // Copy Alpha channel of ARGB to alpha of ARGB. 313 | LIBYUV_API 314 | int ARGBCopyAlpha(const uint8* src_argb, int src_stride_argb, 315 | uint8* dst_argb, int dst_stride_argb, 316 | int width, int height); 317 | 318 | // Extract the alpha channel from ARGB. 319 | LIBYUV_API 320 | int ARGBExtractAlpha(const uint8* src_argb, int src_stride_argb, 321 | uint8* dst_a, int dst_stride_a, 322 | int width, int height); 323 | 324 | // Copy Y channel to Alpha of ARGB. 325 | LIBYUV_API 326 | int ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y, 327 | uint8* dst_argb, int dst_stride_argb, 328 | int width, int height); 329 | 330 | typedef void (*ARGBBlendRow)(const uint8* src_argb0, const uint8* src_argb1, 331 | uint8* dst_argb, int width); 332 | 333 | // Get function to Alpha Blend ARGB pixels and store to destination. 334 | LIBYUV_API 335 | ARGBBlendRow GetARGBBlend(); 336 | 337 | // Alpha Blend ARGB images and store to destination. 338 | // Source is pre-multiplied by alpha using ARGBAttenuate. 339 | // Alpha of destination is set to 255. 340 | LIBYUV_API 341 | int ARGBBlend(const uint8* src_argb0, int src_stride_argb0, 342 | const uint8* src_argb1, int src_stride_argb1, 343 | uint8* dst_argb, int dst_stride_argb, 344 | int width, int height); 345 | 346 | // Alpha Blend plane and store to destination. 347 | // Source is not pre-multiplied by alpha. 348 | LIBYUV_API 349 | int BlendPlane(const uint8* src_y0, int src_stride_y0, 350 | const uint8* src_y1, int src_stride_y1, 351 | const uint8* alpha, int alpha_stride, 352 | uint8* dst_y, int dst_stride_y, 353 | int width, int height); 354 | 355 | // Alpha Blend YUV images and store to destination. 356 | // Source is not pre-multiplied by alpha. 357 | // Alpha is full width x height and subsampled to half size to apply to UV. 358 | LIBYUV_API 359 | int I420Blend(const uint8* src_y0, int src_stride_y0, 360 | const uint8* src_u0, int src_stride_u0, 361 | const uint8* src_v0, int src_stride_v0, 362 | const uint8* src_y1, int src_stride_y1, 363 | const uint8* src_u1, int src_stride_u1, 364 | const uint8* src_v1, int src_stride_v1, 365 | const uint8* alpha, int alpha_stride, 366 | uint8* dst_y, int dst_stride_y, 367 | uint8* dst_u, int dst_stride_u, 368 | uint8* dst_v, int dst_stride_v, 369 | int width, int height); 370 | 371 | // Multiply ARGB image by ARGB image. Shifted down by 8. Saturates to 255. 372 | LIBYUV_API 373 | int ARGBMultiply(const uint8* src_argb0, int src_stride_argb0, 374 | const uint8* src_argb1, int src_stride_argb1, 375 | uint8* dst_argb, int dst_stride_argb, 376 | int width, int height); 377 | 378 | // Add ARGB image with ARGB image. Saturates to 255. 379 | LIBYUV_API 380 | int ARGBAdd(const uint8* src_argb0, int src_stride_argb0, 381 | const uint8* src_argb1, int src_stride_argb1, 382 | uint8* dst_argb, int dst_stride_argb, 383 | int width, int height); 384 | 385 | // Subtract ARGB image (argb1) from ARGB image (argb0). Saturates to 0. 386 | LIBYUV_API 387 | int ARGBSubtract(const uint8* src_argb0, int src_stride_argb0, 388 | const uint8* src_argb1, int src_stride_argb1, 389 | uint8* dst_argb, int dst_stride_argb, 390 | int width, int height); 391 | 392 | // Convert I422 to YUY2. 393 | LIBYUV_API 394 | int I422ToYUY2(const uint8* src_y, int src_stride_y, 395 | const uint8* src_u, int src_stride_u, 396 | const uint8* src_v, int src_stride_v, 397 | uint8* dst_frame, int dst_stride_frame, 398 | int width, int height); 399 | 400 | // Convert I422 to UYVY. 401 | LIBYUV_API 402 | int I422ToUYVY(const uint8* src_y, int src_stride_y, 403 | const uint8* src_u, int src_stride_u, 404 | const uint8* src_v, int src_stride_v, 405 | uint8* dst_frame, int dst_stride_frame, 406 | int width, int height); 407 | 408 | // Convert unattentuated ARGB to preattenuated ARGB. 409 | LIBYUV_API 410 | int ARGBAttenuate(const uint8* src_argb, int src_stride_argb, 411 | uint8* dst_argb, int dst_stride_argb, 412 | int width, int height); 413 | 414 | // Convert preattentuated ARGB to unattenuated ARGB. 415 | LIBYUV_API 416 | int ARGBUnattenuate(const uint8* src_argb, int src_stride_argb, 417 | uint8* dst_argb, int dst_stride_argb, 418 | int width, int height); 419 | 420 | // Internal function - do not call directly. 421 | // Computes table of cumulative sum for image where the value is the sum 422 | // of all values above and to the left of the entry. Used by ARGBBlur. 423 | LIBYUV_API 424 | int ARGBComputeCumulativeSum(const uint8* src_argb, int src_stride_argb, 425 | int32* dst_cumsum, int dst_stride32_cumsum, 426 | int width, int height); 427 | 428 | // Blur ARGB image. 429 | // dst_cumsum table of width * (height + 1) * 16 bytes aligned to 430 | // 16 byte boundary. 431 | // dst_stride32_cumsum is number of ints in a row (width * 4). 432 | // radius is number of pixels around the center. e.g. 1 = 3x3. 2=5x5. 433 | // Blur is optimized for radius of 5 (11x11) or less. 434 | LIBYUV_API 435 | int ARGBBlur(const uint8* src_argb, int src_stride_argb, 436 | uint8* dst_argb, int dst_stride_argb, 437 | int32* dst_cumsum, int dst_stride32_cumsum, 438 | int width, int height, int radius); 439 | 440 | // Multiply ARGB image by ARGB value. 441 | LIBYUV_API 442 | int ARGBShade(const uint8* src_argb, int src_stride_argb, 443 | uint8* dst_argb, int dst_stride_argb, 444 | int width, int height, uint32 value); 445 | 446 | // Interpolate between two images using specified amount of interpolation 447 | // (0 to 255) and store to destination. 448 | // 'interpolation' is specified as 8 bit fraction where 0 means 100% src0 449 | // and 255 means 1% src0 and 99% src1. 450 | LIBYUV_API 451 | int InterpolatePlane(const uint8* src0, int src_stride0, 452 | const uint8* src1, int src_stride1, 453 | uint8* dst, int dst_stride, 454 | int width, int height, int interpolation); 455 | 456 | // Interpolate between two ARGB images using specified amount of interpolation 457 | // Internally calls InterpolatePlane with width * 4 (bpp). 458 | LIBYUV_API 459 | int ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0, 460 | const uint8* src_argb1, int src_stride_argb1, 461 | uint8* dst_argb, int dst_stride_argb, 462 | int width, int height, int interpolation); 463 | 464 | // Interpolate between two YUV images using specified amount of interpolation 465 | // Internally calls InterpolatePlane on each plane where the U and V planes 466 | // are half width and half height. 467 | LIBYUV_API 468 | int I420Interpolate(const uint8* src0_y, int src0_stride_y, 469 | const uint8* src0_u, int src0_stride_u, 470 | const uint8* src0_v, int src0_stride_v, 471 | const uint8* src1_y, int src1_stride_y, 472 | const uint8* src1_u, int src1_stride_u, 473 | const uint8* src1_v, int src1_stride_v, 474 | uint8* dst_y, int dst_stride_y, 475 | uint8* dst_u, int dst_stride_u, 476 | uint8* dst_v, int dst_stride_v, 477 | int width, int height, int interpolation); 478 | 479 | #if defined(__pnacl__) || defined(__CLR_VER) || \ 480 | (defined(__i386__) && !defined(__SSE2__)) 481 | #define LIBYUV_DISABLE_X86 482 | #endif 483 | // MemorySanitizer does not support assembly code yet. http://crbug.com/344505 484 | #if defined(__has_feature) 485 | #if __has_feature(memory_sanitizer) 486 | #define LIBYUV_DISABLE_X86 487 | #endif 488 | #endif 489 | // The following are available on all x86 platforms: 490 | #if !defined(LIBYUV_DISABLE_X86) && \ 491 | (defined(_M_IX86) || defined(__x86_64__) || defined(__i386__)) 492 | #define HAS_ARGBAFFINEROW_SSE2 493 | #endif 494 | 495 | // Row function for copying pixels from a source with a slope to a row 496 | // of destination. Useful for scaling, rotation, mirror, texture mapping. 497 | LIBYUV_API 498 | void ARGBAffineRow_C(const uint8* src_argb, int src_argb_stride, 499 | uint8* dst_argb, const float* uv_dudv, int width); 500 | LIBYUV_API 501 | void ARGBAffineRow_SSE2(const uint8* src_argb, int src_argb_stride, 502 | uint8* dst_argb, const float* uv_dudv, int width); 503 | 504 | // Shuffle ARGB channel order. e.g. BGRA to ARGB. 505 | // shuffler is 16 bytes and must be aligned. 506 | LIBYUV_API 507 | int ARGBShuffle(const uint8* src_bgra, int src_stride_bgra, 508 | uint8* dst_argb, int dst_stride_argb, 509 | const uint8* shuffler, int width, int height); 510 | 511 | // Sobel ARGB effect with planar output. 512 | LIBYUV_API 513 | int ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb, 514 | uint8* dst_y, int dst_stride_y, 515 | int width, int height); 516 | 517 | // Sobel ARGB effect. 518 | LIBYUV_API 519 | int ARGBSobel(const uint8* src_argb, int src_stride_argb, 520 | uint8* dst_argb, int dst_stride_argb, 521 | int width, int height); 522 | 523 | // Sobel ARGB effect w/ Sobel X, Sobel, Sobel Y in ARGB. 524 | LIBYUV_API 525 | int ARGBSobelXY(const uint8* src_argb, int src_stride_argb, 526 | uint8* dst_argb, int dst_stride_argb, 527 | int width, int height); 528 | 529 | #ifdef __cplusplus 530 | } // extern "C" 531 | } // namespace libyuv 532 | #endif 533 | 534 | #endif // INCLUDE_LIBYUV_PLANAR_FUNCTIONS_H_ 535 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/rotate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_ROTATE_H_ 12 | #define INCLUDE_LIBYUV_ROTATE_H_ 13 | 14 | #include "basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Supported rotation. 22 | typedef enum RotationMode { 23 | kRotate0 = 0, // No rotation. 24 | kRotate90 = 90, // Rotate 90 degrees clockwise. 25 | kRotate180 = 180, // Rotate 180 degrees. 26 | kRotate270 = 270, // Rotate 270 degrees clockwise. 27 | 28 | // Deprecated. 29 | kRotateNone = 0, 30 | kRotateClockwise = 90, 31 | kRotateCounterClockwise = 270, 32 | } RotationModeEnum; 33 | 34 | // Rotate I420 frame. 35 | LIBYUV_API 36 | int I420Rotate(const uint8* src_y, int src_stride_y, 37 | const uint8* src_u, int src_stride_u, 38 | const uint8* src_v, int src_stride_v, 39 | uint8* dst_y, int dst_stride_y, 40 | uint8* dst_u, int dst_stride_u, 41 | uint8* dst_v, int dst_stride_v, 42 | int src_width, int src_height, enum RotationMode mode); 43 | 44 | // Rotate NV12 input and store in I420. 45 | LIBYUV_API 46 | int NV12ToI420Rotate(const uint8* src_y, int src_stride_y, 47 | const uint8* src_uv, int src_stride_uv, 48 | uint8* dst_y, int dst_stride_y, 49 | uint8* dst_u, int dst_stride_u, 50 | uint8* dst_v, int dst_stride_v, 51 | int src_width, int src_height, enum RotationMode mode); 52 | 53 | // Rotate a plane by 0, 90, 180, or 270. 54 | LIBYUV_API 55 | int RotatePlane(const uint8* src, int src_stride, 56 | uint8* dst, int dst_stride, 57 | int src_width, int src_height, enum RotationMode mode); 58 | 59 | // Rotate planes by 90, 180, 270. Deprecated. 60 | LIBYUV_API 61 | void RotatePlane90(const uint8* src, int src_stride, 62 | uint8* dst, int dst_stride, 63 | int width, int height); 64 | 65 | LIBYUV_API 66 | void RotatePlane180(const uint8* src, int src_stride, 67 | uint8* dst, int dst_stride, 68 | int width, int height); 69 | 70 | LIBYUV_API 71 | void RotatePlane270(const uint8* src, int src_stride, 72 | uint8* dst, int dst_stride, 73 | int width, int height); 74 | 75 | LIBYUV_API 76 | void RotateUV90(const uint8* src, int src_stride, 77 | uint8* dst_a, int dst_stride_a, 78 | uint8* dst_b, int dst_stride_b, 79 | int width, int height); 80 | 81 | // Rotations for when U and V are interleaved. 82 | // These functions take one input pointer and 83 | // split the data into two buffers while 84 | // rotating them. Deprecated. 85 | LIBYUV_API 86 | void RotateUV180(const uint8* src, int src_stride, 87 | uint8* dst_a, int dst_stride_a, 88 | uint8* dst_b, int dst_stride_b, 89 | int width, int height); 90 | 91 | LIBYUV_API 92 | void RotateUV270(const uint8* src, int src_stride, 93 | uint8* dst_a, int dst_stride_a, 94 | uint8* dst_b, int dst_stride_b, 95 | int width, int height); 96 | 97 | // The 90 and 270 functions are based on transposes. 98 | // Doing a transpose with reversing the read/write 99 | // order will result in a rotation by +- 90 degrees. 100 | // Deprecated. 101 | LIBYUV_API 102 | void TransposePlane(const uint8* src, int src_stride, 103 | uint8* dst, int dst_stride, 104 | int width, int height); 105 | 106 | LIBYUV_API 107 | void TransposeUV(const uint8* src, int src_stride, 108 | uint8* dst_a, int dst_stride_a, 109 | uint8* dst_b, int dst_stride_b, 110 | int width, int height); 111 | 112 | #ifdef __cplusplus 113 | } // extern "C" 114 | } // namespace libyuv 115 | #endif 116 | 117 | #endif // INCLUDE_LIBYUV_ROTATE_H_ 118 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/rotate_argb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_ROTATE_ARGB_H_ 12 | #define INCLUDE_LIBYUV_ROTATE_ARGB_H_ 13 | 14 | #include "basic_types.h" 15 | #include "rotate.h" // For RotationMode. 16 | 17 | #ifdef __cplusplus 18 | namespace libyuv { 19 | extern "C" { 20 | #endif 21 | 22 | // Rotate ARGB frame 23 | LIBYUV_API 24 | int ARGBRotate(const uint8* src_argb, int src_stride_argb, 25 | uint8* dst_argb, int dst_stride_argb, 26 | int src_width, int src_height, enum RotationMode mode); 27 | 28 | #ifdef __cplusplus 29 | } // extern "C" 30 | } // namespace libyuv 31 | #endif 32 | 33 | #endif // INCLUDE_LIBYUV_ROTATE_ARGB_H_ 34 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/rotate_row.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_ROTATE_ROW_H_ 12 | #define INCLUDE_LIBYUV_ROTATE_ROW_H_ 13 | 14 | #include "libyuv/basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | #if defined(__pnacl__) || defined(__CLR_VER) || \ 22 | (defined(__i386__) && !defined(__SSE2__)) 23 | #define LIBYUV_DISABLE_X86 24 | #endif 25 | // MemorySanitizer does not support assembly code yet. http://crbug.com/344505 26 | #if defined(__has_feature) 27 | #if __has_feature(memory_sanitizer) 28 | #define LIBYUV_DISABLE_X86 29 | #endif 30 | #endif 31 | // The following are available for Visual C and clangcl 32 bit: 32 | #if !defined(LIBYUV_DISABLE_X86) && defined(_M_IX86) 33 | #define HAS_TRANSPOSEWX8_SSSE3 34 | #define HAS_TRANSPOSEUVWX8_SSE2 35 | #endif 36 | 37 | // The following are available for GCC 32 or 64 bit but not NaCL for 64 bit: 38 | #if !defined(LIBYUV_DISABLE_X86) && \ 39 | (defined(__i386__) || (defined(__x86_64__) && !defined(__native_client__))) 40 | #define HAS_TRANSPOSEWX8_SSSE3 41 | #endif 42 | 43 | // The following are available for 64 bit GCC but not NaCL: 44 | #if !defined(LIBYUV_DISABLE_X86) && !defined(__native_client__) && \ 45 | defined(__x86_64__) 46 | #define HAS_TRANSPOSEWX8_FAST_SSSE3 47 | #define HAS_TRANSPOSEUVWX8_SSE2 48 | #endif 49 | 50 | #if !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \ 51 | (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) 52 | #define HAS_TRANSPOSEWX8_NEON 53 | #define HAS_TRANSPOSEUVWX8_NEON 54 | #endif 55 | 56 | #if !defined(LIBYUV_DISABLE_MIPS) && !defined(__native_client__) && \ 57 | defined(__mips__) && \ 58 | defined(__mips_dsp) && (__mips_dsp_rev >= 2) 59 | #define HAS_TRANSPOSEWX8_DSPR2 60 | #define HAS_TRANSPOSEUVWX8_DSPR2 61 | #endif // defined(__mips__) 62 | 63 | void TransposeWxH_C(const uint8* src, int src_stride, 64 | uint8* dst, int dst_stride, int width, int height); 65 | 66 | void TransposeWx8_C(const uint8* src, int src_stride, 67 | uint8* dst, int dst_stride, int width); 68 | void TransposeWx8_NEON(const uint8* src, int src_stride, 69 | uint8* dst, int dst_stride, int width); 70 | void TransposeWx8_SSSE3(const uint8* src, int src_stride, 71 | uint8* dst, int dst_stride, int width); 72 | void TransposeWx8_Fast_SSSE3(const uint8* src, int src_stride, 73 | uint8* dst, int dst_stride, int width); 74 | void TransposeWx8_DSPR2(const uint8* src, int src_stride, 75 | uint8* dst, int dst_stride, int width); 76 | void TransposeWx8_Fast_DSPR2(const uint8* src, int src_stride, 77 | uint8* dst, int dst_stride, int width); 78 | 79 | void TransposeWx8_Any_NEON(const uint8* src, int src_stride, 80 | uint8* dst, int dst_stride, int width); 81 | void TransposeWx8_Any_SSSE3(const uint8* src, int src_stride, 82 | uint8* dst, int dst_stride, int width); 83 | void TransposeWx8_Fast_Any_SSSE3(const uint8* src, int src_stride, 84 | uint8* dst, int dst_stride, int width); 85 | void TransposeWx8_Any_DSPR2(const uint8* src, int src_stride, 86 | uint8* dst, int dst_stride, int width); 87 | 88 | void TransposeUVWxH_C(const uint8* src, int src_stride, 89 | uint8* dst_a, int dst_stride_a, 90 | uint8* dst_b, int dst_stride_b, 91 | int width, int height); 92 | 93 | void TransposeUVWx8_C(const uint8* src, int src_stride, 94 | uint8* dst_a, int dst_stride_a, 95 | uint8* dst_b, int dst_stride_b, int width); 96 | void TransposeUVWx8_SSE2(const uint8* src, int src_stride, 97 | uint8* dst_a, int dst_stride_a, 98 | uint8* dst_b, int dst_stride_b, int width); 99 | void TransposeUVWx8_NEON(const uint8* src, int src_stride, 100 | uint8* dst_a, int dst_stride_a, 101 | uint8* dst_b, int dst_stride_b, int width); 102 | void TransposeUVWx8_DSPR2(const uint8* src, int src_stride, 103 | uint8* dst_a, int dst_stride_a, 104 | uint8* dst_b, int dst_stride_b, int width); 105 | 106 | void TransposeUVWx8_Any_SSE2(const uint8* src, int src_stride, 107 | uint8* dst_a, int dst_stride_a, 108 | uint8* dst_b, int dst_stride_b, int width); 109 | void TransposeUVWx8_Any_NEON(const uint8* src, int src_stride, 110 | uint8* dst_a, int dst_stride_a, 111 | uint8* dst_b, int dst_stride_b, int width); 112 | void TransposeUVWx8_Any_DSPR2(const uint8* src, int src_stride, 113 | uint8* dst_a, int dst_stride_a, 114 | uint8* dst_b, int dst_stride_b, int width); 115 | 116 | #ifdef __cplusplus 117 | } // extern "C" 118 | } // namespace libyuv 119 | #endif 120 | 121 | #endif // INCLUDE_LIBYUV_ROTATE_ROW_H_ 122 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/scale.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_SCALE_H_ 12 | #define INCLUDE_LIBYUV_SCALE_H_ 13 | 14 | #include "basic_types.h" 15 | 16 | #ifdef __cplusplus 17 | namespace libyuv { 18 | extern "C" { 19 | #endif 20 | 21 | // Supported filtering. 22 | typedef enum FilterMode { 23 | kFilterNone = 0, // Point sample; Fastest. 24 | kFilterLinear = 1, // Filter horizontally only. 25 | kFilterBilinear = 2, // Faster than box, but lower quality scaling down. 26 | kFilterBox = 3 // Highest quality. 27 | } FilterModeEnum; 28 | 29 | // Scale a YUV plane. 30 | LIBYUV_API 31 | void ScalePlane(const uint8* src, int src_stride, 32 | int src_width, int src_height, 33 | uint8* dst, int dst_stride, 34 | int dst_width, int dst_height, 35 | enum FilterMode filtering); 36 | 37 | LIBYUV_API 38 | void ScalePlane_16(const uint16* src, int src_stride, 39 | int src_width, int src_height, 40 | uint16* dst, int dst_stride, 41 | int dst_width, int dst_height, 42 | enum FilterMode filtering); 43 | 44 | // Scales a YUV 4:2:0 image from the src width and height to the 45 | // dst width and height. 46 | // If filtering is kFilterNone, a simple nearest-neighbor algorithm is 47 | // used. This produces basic (blocky) quality at the fastest speed. 48 | // If filtering is kFilterBilinear, interpolation is used to produce a better 49 | // quality image, at the expense of speed. 50 | // If filtering is kFilterBox, averaging is used to produce ever better 51 | // quality image, at further expense of speed. 52 | // Returns 0 if successful. 53 | 54 | LIBYUV_API 55 | int I420Scale(const uint8* src_y, int src_stride_y, 56 | const uint8* src_u, int src_stride_u, 57 | const uint8* src_v, int src_stride_v, 58 | int src_width, int src_height, 59 | uint8* dst_y, int dst_stride_y, 60 | uint8* dst_u, int dst_stride_u, 61 | uint8* dst_v, int dst_stride_v, 62 | int dst_width, int dst_height, 63 | enum FilterMode filtering); 64 | 65 | LIBYUV_API 66 | int I420Scale_16(const uint16* src_y, int src_stride_y, 67 | const uint16* src_u, int src_stride_u, 68 | const uint16* src_v, int src_stride_v, 69 | int src_width, int src_height, 70 | uint16* dst_y, int dst_stride_y, 71 | uint16* dst_u, int dst_stride_u, 72 | uint16* dst_v, int dst_stride_v, 73 | int dst_width, int dst_height, 74 | enum FilterMode filtering); 75 | 76 | #ifdef __cplusplus 77 | // Legacy API. Deprecated. 78 | LIBYUV_API 79 | int Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v, 80 | int src_stride_y, int src_stride_u, int src_stride_v, 81 | int src_width, int src_height, 82 | uint8* dst_y, uint8* dst_u, uint8* dst_v, 83 | int dst_stride_y, int dst_stride_u, int dst_stride_v, 84 | int dst_width, int dst_height, 85 | LIBYUV_BOOL interpolate); 86 | 87 | // Legacy API. Deprecated. 88 | LIBYUV_API 89 | int ScaleOffset(const uint8* src_i420, int src_width, int src_height, 90 | uint8* dst_i420, int dst_width, int dst_height, int dst_yoffset, 91 | LIBYUV_BOOL interpolate); 92 | 93 | // For testing, allow disabling of specialized scalers. 94 | LIBYUV_API 95 | void SetUseReferenceImpl(LIBYUV_BOOL use); 96 | #endif // __cplusplus 97 | 98 | #ifdef __cplusplus 99 | } // extern "C" 100 | } // namespace libyuv 101 | #endif 102 | 103 | #endif // INCLUDE_LIBYUV_SCALE_H_ 104 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/scale_argb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_SCALE_ARGB_H_ 12 | #define INCLUDE_LIBYUV_SCALE_ARGB_H_ 13 | 14 | #include "basic_types.h" 15 | #include "scale.h" // For FilterMode 16 | 17 | #ifdef __cplusplus 18 | namespace libyuv { 19 | extern "C" { 20 | #endif 21 | 22 | LIBYUV_API 23 | int ARGBScale(const uint8* src_argb, int src_stride_argb, 24 | int src_width, int src_height, 25 | uint8* dst_argb, int dst_stride_argb, 26 | int dst_width, int dst_height, 27 | enum FilterMode filtering); 28 | 29 | // Clipped scale takes destination rectangle coordinates for clip values. 30 | LIBYUV_API 31 | int ARGBScaleClip(const uint8* src_argb, int src_stride_argb, 32 | int src_width, int src_height, 33 | uint8* dst_argb, int dst_stride_argb, 34 | int dst_width, int dst_height, 35 | int clip_x, int clip_y, int clip_width, int clip_height, 36 | enum FilterMode filtering); 37 | 38 | // Scale with YUV conversion to ARGB and clipping. 39 | LIBYUV_API 40 | int YUVToARGBScaleClip(const uint8* src_y, int src_stride_y, 41 | const uint8* src_u, int src_stride_u, 42 | const uint8* src_v, int src_stride_v, 43 | uint32 src_fourcc, 44 | int src_width, int src_height, 45 | uint8* dst_argb, int dst_stride_argb, 46 | uint32 dst_fourcc, 47 | int dst_width, int dst_height, 48 | int clip_x, int clip_y, int clip_width, int clip_height, 49 | enum FilterMode filtering); 50 | 51 | #ifdef __cplusplus 52 | } // extern "C" 53 | } // namespace libyuv 54 | #endif 55 | 56 | #endif // INCLUDE_LIBYUV_SCALE_ARGB_H_ 57 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | #ifndef INCLUDE_LIBYUV_VERSION_H_ 12 | #define INCLUDE_LIBYUV_VERSION_H_ 13 | 14 | #define LIBYUV_VERSION 1634 15 | 16 | #endif // INCLUDE_LIBYUV_VERSION_H_ 17 | -------------------------------------------------------------------------------- /Share/Vendors/libyuv/video_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. An additional intellectual property rights grant can be found 7 | * in the file PATENTS. All contributing project authors may 8 | * be found in the AUTHORS file in the root of the source tree. 9 | */ 10 | 11 | // Common definitions for video, including fourcc and VideoFormat. 12 | 13 | #ifndef INCLUDE_LIBYUV_VIDEO_COMMON_H_ 14 | #define INCLUDE_LIBYUV_VIDEO_COMMON_H_ 15 | 16 | #include "basic_types.h" 17 | 18 | #ifdef __cplusplus 19 | namespace libyuv { 20 | extern "C" { 21 | #endif 22 | 23 | ////////////////////////////////////////////////////////////////////////////// 24 | // Definition of FourCC codes 25 | ////////////////////////////////////////////////////////////////////////////// 26 | 27 | // Convert four characters to a FourCC code. 28 | // Needs to be a macro otherwise the OS X compiler complains when the kFormat* 29 | // constants are used in a switch. 30 | #ifdef __cplusplus 31 | #define FOURCC(a, b, c, d) ( \ 32 | (static_cast(a)) | (static_cast(b) << 8) | \ 33 | (static_cast(c) << 16) | (static_cast(d) << 24)) 34 | #else 35 | #define FOURCC(a, b, c, d) ( \ 36 | ((uint32)(a)) | ((uint32)(b) << 8) | /* NOLINT */ \ 37 | ((uint32)(c) << 16) | ((uint32)(d) << 24)) /* NOLINT */ 38 | #endif 39 | 40 | // Some pages discussing FourCC codes: 41 | // http://www.fourcc.org/yuv.php 42 | // http://v4l2spec.bytesex.org/spec/book1.htm 43 | // http://developer.apple.com/quicktime/icefloe/dispatch020.html 44 | // http://msdn.microsoft.com/library/windows/desktop/dd206750.aspx#nv12 45 | // http://people.xiph.org/~xiphmont/containers/nut/nut4cc.txt 46 | 47 | // FourCC codes grouped according to implementation efficiency. 48 | // Primary formats should convert in 1 efficient step. 49 | // Secondary formats are converted in 2 steps. 50 | // Auxilliary formats call primary converters. 51 | enum FourCC { 52 | // 8 Primary YUV formats: 5 planar, 2 biplanar, 2 packed. 53 | FOURCC_I420 = FOURCC('I', '4', '2', '0'), 54 | FOURCC_I422 = FOURCC('I', '4', '2', '2'), 55 | FOURCC_I444 = FOURCC('I', '4', '4', '4'), 56 | FOURCC_I411 = FOURCC('I', '4', '1', '1'), // deprecated. 57 | FOURCC_I400 = FOURCC('I', '4', '0', '0'), 58 | FOURCC_NV21 = FOURCC('N', 'V', '2', '1'), 59 | FOURCC_NV12 = FOURCC('N', 'V', '1', '2'), 60 | FOURCC_YUY2 = FOURCC('Y', 'U', 'Y', '2'), 61 | FOURCC_UYVY = FOURCC('U', 'Y', 'V', 'Y'), 62 | 63 | // 1 Secondary YUV format: row biplanar. 64 | FOURCC_M420 = FOURCC('M', '4', '2', '0'), 65 | FOURCC_Q420 = FOURCC('Q', '4', '2', '0'), // deprecated. 66 | 67 | // 9 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp. 68 | FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'), 69 | FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'), 70 | FOURCC_ABGR = FOURCC('A', 'B', 'G', 'R'), 71 | FOURCC_24BG = FOURCC('2', '4', 'B', 'G'), 72 | FOURCC_RAW = FOURCC('r', 'a', 'w', ' '), 73 | FOURCC_RGBA = FOURCC('R', 'G', 'B', 'A'), 74 | FOURCC_RGBP = FOURCC('R', 'G', 'B', 'P'), // rgb565 LE. 75 | FOURCC_RGBO = FOURCC('R', 'G', 'B', 'O'), // argb1555 LE. 76 | FOURCC_R444 = FOURCC('R', '4', '4', '4'), // argb4444 LE. 77 | 78 | // 4 Secondary RGB formats: 4 Bayer Patterns. deprecated. 79 | FOURCC_RGGB = FOURCC('R', 'G', 'G', 'B'), 80 | FOURCC_BGGR = FOURCC('B', 'G', 'G', 'R'), 81 | FOURCC_GRBG = FOURCC('G', 'R', 'B', 'G'), 82 | FOURCC_GBRG = FOURCC('G', 'B', 'R', 'G'), 83 | 84 | // 1 Primary Compressed YUV format. 85 | FOURCC_MJPG = FOURCC('M', 'J', 'P', 'G'), 86 | 87 | // 5 Auxiliary YUV variations: 3 with U and V planes are swapped, 1 Alias. 88 | FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'), 89 | FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'), 90 | FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'), 91 | FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Linux version of I420. 92 | FOURCC_J420 = FOURCC('J', '4', '2', '0'), 93 | FOURCC_J400 = FOURCC('J', '4', '0', '0'), // unofficial fourcc 94 | FOURCC_H420 = FOURCC('H', '4', '2', '0'), // unofficial fourcc 95 | 96 | // 14 Auxiliary aliases. CanonicalFourCC() maps these to canonical fourcc. 97 | FOURCC_IYUV = FOURCC('I', 'Y', 'U', 'V'), // Alias for I420. 98 | FOURCC_YU16 = FOURCC('Y', 'U', '1', '6'), // Alias for I422. 99 | FOURCC_YU24 = FOURCC('Y', 'U', '2', '4'), // Alias for I444. 100 | FOURCC_YUYV = FOURCC('Y', 'U', 'Y', 'V'), // Alias for YUY2. 101 | FOURCC_YUVS = FOURCC('y', 'u', 'v', 's'), // Alias for YUY2 on Mac. 102 | FOURCC_HDYC = FOURCC('H', 'D', 'Y', 'C'), // Alias for UYVY. 103 | FOURCC_2VUY = FOURCC('2', 'v', 'u', 'y'), // Alias for UYVY on Mac. 104 | FOURCC_JPEG = FOURCC('J', 'P', 'E', 'G'), // Alias for MJPG. 105 | FOURCC_DMB1 = FOURCC('d', 'm', 'b', '1'), // Alias for MJPG on Mac. 106 | FOURCC_BA81 = FOURCC('B', 'A', '8', '1'), // Alias for BGGR. 107 | FOURCC_RGB3 = FOURCC('R', 'G', 'B', '3'), // Alias for RAW. 108 | FOURCC_BGR3 = FOURCC('B', 'G', 'R', '3'), // Alias for 24BG. 109 | FOURCC_CM32 = FOURCC(0, 0, 0, 32), // Alias for BGRA kCMPixelFormat_32ARGB 110 | FOURCC_CM24 = FOURCC(0, 0, 0, 24), // Alias for RAW kCMPixelFormat_24RGB 111 | FOURCC_L555 = FOURCC('L', '5', '5', '5'), // Alias for RGBO. 112 | FOURCC_L565 = FOURCC('L', '5', '6', '5'), // Alias for RGBP. 113 | FOURCC_5551 = FOURCC('5', '5', '5', '1'), // Alias for RGBO. 114 | 115 | // 1 Auxiliary compressed YUV format set aside for capturer. 116 | FOURCC_H264 = FOURCC('H', '2', '6', '4'), 117 | 118 | // Match any fourcc. 119 | FOURCC_ANY = -1, 120 | }; 121 | 122 | enum FourCCBpp { 123 | // Canonical fourcc codes used in our code. 124 | FOURCC_BPP_I420 = 12, 125 | FOURCC_BPP_I422 = 16, 126 | FOURCC_BPP_I444 = 24, 127 | FOURCC_BPP_I411 = 12, 128 | FOURCC_BPP_I400 = 8, 129 | FOURCC_BPP_NV21 = 12, 130 | FOURCC_BPP_NV12 = 12, 131 | FOURCC_BPP_YUY2 = 16, 132 | FOURCC_BPP_UYVY = 16, 133 | FOURCC_BPP_M420 = 12, 134 | FOURCC_BPP_Q420 = 12, 135 | FOURCC_BPP_ARGB = 32, 136 | FOURCC_BPP_BGRA = 32, 137 | FOURCC_BPP_ABGR = 32, 138 | FOURCC_BPP_RGBA = 32, 139 | FOURCC_BPP_24BG = 24, 140 | FOURCC_BPP_RAW = 24, 141 | FOURCC_BPP_RGBP = 16, 142 | FOURCC_BPP_RGBO = 16, 143 | FOURCC_BPP_R444 = 16, 144 | FOURCC_BPP_RGGB = 8, 145 | FOURCC_BPP_BGGR = 8, 146 | FOURCC_BPP_GRBG = 8, 147 | FOURCC_BPP_GBRG = 8, 148 | FOURCC_BPP_YV12 = 12, 149 | FOURCC_BPP_YV16 = 16, 150 | FOURCC_BPP_YV24 = 24, 151 | FOURCC_BPP_YU12 = 12, 152 | FOURCC_BPP_J420 = 12, 153 | FOURCC_BPP_J400 = 8, 154 | FOURCC_BPP_H420 = 12, 155 | FOURCC_BPP_MJPG = 0, // 0 means unknown. 156 | FOURCC_BPP_H264 = 0, 157 | FOURCC_BPP_IYUV = 12, 158 | FOURCC_BPP_YU16 = 16, 159 | FOURCC_BPP_YU24 = 24, 160 | FOURCC_BPP_YUYV = 16, 161 | FOURCC_BPP_YUVS = 16, 162 | FOURCC_BPP_HDYC = 16, 163 | FOURCC_BPP_2VUY = 16, 164 | FOURCC_BPP_JPEG = 1, 165 | FOURCC_BPP_DMB1 = 1, 166 | FOURCC_BPP_BA81 = 8, 167 | FOURCC_BPP_RGB3 = 24, 168 | FOURCC_BPP_BGR3 = 24, 169 | FOURCC_BPP_CM32 = 32, 170 | FOURCC_BPP_CM24 = 24, 171 | 172 | // Match any fourcc. 173 | FOURCC_BPP_ANY = 0, // 0 means unknown. 174 | }; 175 | 176 | // Converts fourcc aliases into canonical ones. 177 | LIBYUV_API uint32 CanonicalFourCC(uint32 fourcc); 178 | 179 | #ifdef __cplusplus 180 | } // extern "C" 181 | } // namespace libyuv 182 | #endif 183 | 184 | #endif // INCLUDE_LIBYUV_VIDEO_COMMON_H_ 185 | -------------------------------------------------------------------------------- /Share/Video/NTESI420Frame.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by Netease on 15/4/17. 4 | // Copyright (c) 2017年 Netease. All rights reserved. 5 | // 6 | 7 | #import 8 | #import 9 | 10 | typedef NS_ENUM(NSUInteger, NTESI420FramePlane) { 11 | NTESI420FramePlaneY = 0, 12 | NTESI420FramePlaneU = 1, 13 | NTESI420FramePlaneV = 2, 14 | }; 15 | 16 | @interface NTESI420Frame : NSObject 17 | 18 | @property (nonatomic, readonly) int width; 19 | @property (nonatomic, readonly) int height; 20 | @property (nonatomic, readonly) int i420DataLength; 21 | @property (nonatomic, assign) UInt64 timetag; 22 | @property (nonatomic, readonly) UInt8 *data; 23 | 24 | + (instancetype)initWithData:(NSData *)data; 25 | 26 | - (NSData *)bytes; 27 | 28 | - (id)initWithWidth:(int)w height:(int)h; 29 | 30 | - (UInt8 *)dataOfPlane:(NTESI420FramePlane)plane; 31 | 32 | - (NSUInteger)strideOfPlane:(NTESI420FramePlane)plane; 33 | 34 | - (CMSampleBufferRef)convertToSampleBuffer; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Share/Video/NTESI420Frame.m: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by fenric on 15/4/17. 4 | // Copyright (c) 2015年 Netease. All rights reserved. 5 | // 6 | 7 | #import "NTESI420Frame.h" 8 | #import "NTESYUVConverter.h" 9 | 10 | @interface NTESI420Frame() { 11 | CFMutableDataRef _cfData; 12 | UInt8 *_planeData[3]; 13 | NSUInteger _stride[3]; 14 | } 15 | 16 | @end 17 | 18 | @implementation NTESI420Frame 19 | 20 | + (instancetype)initWithData:(NSData *)data { 21 | 22 | int width = 0; 23 | int height = 0; 24 | int i420DataLength = 0; 25 | UInt64 timetag = 0; 26 | 27 | int structSize = sizeof(width) + sizeof(height) + sizeof(i420DataLength) + sizeof(timetag); 28 | if(structSize > data.length) { 29 | return nil; 30 | } 31 | 32 | const void * buffer = [data bytes]; 33 | int offset = 0; 34 | 35 | memcpy(&width, buffer + offset, sizeof(width)); 36 | offset += sizeof(width); 37 | 38 | memcpy(&height,buffer + offset,sizeof(height)); 39 | offset += sizeof(height); 40 | 41 | memcpy(&i420DataLength,buffer + offset, sizeof(i420DataLength)); 42 | offset += sizeof(i420DataLength); 43 | 44 | memcpy(&timetag, buffer + offset, sizeof(timetag)); 45 | offset += sizeof(timetag); 46 | 47 | 48 | if(i420DataLength > data.length - structSize) { 49 | return nil; 50 | } 51 | NTESI420Frame *frame = [[[self class] alloc] initWithWidth:width height:height]; 52 | 53 | memcpy([frame dataOfPlane:NTESI420FramePlaneY], buffer+offset, [frame strideOfPlane:NTESI420FramePlaneY] * height); 54 | offset += [frame strideOfPlane:NTESI420FramePlaneY] * height; 55 | 56 | memcpy([frame dataOfPlane:NTESI420FramePlaneU], buffer+offset, [frame strideOfPlane:NTESI420FramePlaneU] * height / 2); 57 | offset += [frame strideOfPlane:NTESI420FramePlaneU] * height / 2; 58 | 59 | memcpy([frame dataOfPlane:NTESI420FramePlaneV], buffer+offset, [frame strideOfPlane:NTESI420FramePlaneV] * height / 2); 60 | offset += [frame strideOfPlane:NTESI420FramePlaneV] * height / 2; 61 | 62 | return frame; 63 | } 64 | 65 | - (NSData *)bytes { 66 | int structSize = sizeof(self.width) + sizeof(self.height) + sizeof(self.i420DataLength) + sizeof(self.timetag); 67 | 68 | void * buffer = malloc(structSize + self.i420DataLength); 69 | 70 | memset(buffer, 0, structSize + self.i420DataLength); 71 | int offset = 0; 72 | 73 | memcpy(buffer + offset, &_width, sizeof(_width)); 74 | offset += sizeof(_width); 75 | 76 | memcpy(buffer + offset, &_height, sizeof(_height)); 77 | offset += sizeof(_height); 78 | 79 | memcpy(buffer + offset, &_i420DataLength, sizeof(_i420DataLength)); 80 | offset += sizeof(_i420DataLength); 81 | 82 | memcpy(buffer + offset, &_timetag, sizeof(_timetag)); 83 | offset += sizeof(_timetag); 84 | 85 | 86 | memcpy(buffer + offset, [self dataOfPlane:NTESI420FramePlaneY], [self strideOfPlane:NTESI420FramePlaneY] * self.height); 87 | offset += [self strideOfPlane:NTESI420FramePlaneY] * self.height; 88 | 89 | memcpy(buffer + offset, [self dataOfPlane:NTESI420FramePlaneU], [self strideOfPlane:NTESI420FramePlaneU] * self.height / 2); 90 | offset += [self strideOfPlane:NTESI420FramePlaneU] * self.height / 2; 91 | 92 | memcpy(buffer + offset, [self dataOfPlane:NTESI420FramePlaneV], [self strideOfPlane:NTESI420FramePlaneV] * self.height / 2); 93 | offset += [self strideOfPlane:NTESI420FramePlaneV] * self.height / 2; 94 | 95 | NSData *data = [NSData dataWithBytes:buffer length:offset]; 96 | free(buffer); 97 | return data; 98 | } 99 | 100 | - (id)initWithWidth:(int)w 101 | height:(int)h 102 | { 103 | if (self = [super init]) { 104 | _width = w; 105 | _height = h; 106 | _i420DataLength = _width * _height * 3 >> 1; 107 | _cfData = CFDataCreateMutable(kCFAllocatorDefault, _i420DataLength); 108 | _data = CFDataGetMutableBytePtr(_cfData); 109 | _planeData[NTESI420FramePlaneY] = _data; 110 | _planeData[NTESI420FramePlaneU] = _planeData[NTESI420FramePlaneY] + _width * _height; 111 | _planeData[NTESI420FramePlaneV] = _planeData[NTESI420FramePlaneU] + _width * _height / 4; 112 | _stride[NTESI420FramePlaneY] = _width; 113 | _stride[NTESI420FramePlaneU] = _width >> 1; 114 | _stride[NTESI420FramePlaneV] = _width >> 1; 115 | 116 | } 117 | 118 | return self; 119 | 120 | } 121 | 122 | - (UInt8 *)dataOfPlane:(NTESI420FramePlane)plane 123 | { 124 | return _planeData[plane]; 125 | } 126 | 127 | - (NSUInteger)strideOfPlane:(NTESI420FramePlane)plane 128 | { 129 | return _stride[plane]; 130 | } 131 | 132 | -(void)freeData 133 | { 134 | CFRelease(_cfData); 135 | 136 | _data = NULL; 137 | _width = _height = _i420DataLength = 0; 138 | } 139 | 140 | - (void) dealloc 141 | { 142 | [self freeData]; 143 | } 144 | 145 | - (CMSampleBufferRef)convertToSampleBuffer 146 | { 147 | CVPixelBufferRef pixelBuffer = [NTESYUVConverter i420FrameToPixelBuffer:self]; 148 | if (!pixelBuffer) { 149 | return nil; 150 | } 151 | CMSampleBufferRef sampleBuffer = [NTESYUVConverter pixelBufferToSampleBuffer:pixelBuffer]; 152 | return sampleBuffer; 153 | } 154 | 155 | @end 156 | -------------------------------------------------------------------------------- /Share/Video/NTESVideoUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by fenric on 17/3/20. 4 | // Copyright © 2017年 Netease. All rights reserved. 5 | // 6 | 7 | #import 8 | #import 9 | 10 | @interface NTESVideoUtil : NSObject 11 | 12 | + (CMVideoDimensions)outputVideoDimens:(CMVideoDimensions)inputDimens 13 | crop:(float)ratio; 14 | 15 | + (CMVideoDimensions)calculateDiemnsDividedByTwo:(int)width andHeight:(int)height; 16 | 17 | + (CMVideoDimensions)outputVideoDimensEnhanced:(CMVideoDimensions)inputDimens crop:(float)ratio; 18 | @end 19 | -------------------------------------------------------------------------------- /Share/Video/NTESVideoUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by fenric on 17/3/20. 4 | // Copyright © 2017年 Netease. All rights reserved. 5 | // 6 | 7 | #import "NTESVideoUtil.h" 8 | 9 | #define NVSVideoUtilCropWidthAlignment 2 10 | 11 | @implementation NTESVideoUtil 12 | 13 | 14 | + (CMVideoDimensions)outputVideoDimensEnhanced:(CMVideoDimensions)inputDimens crop:(float)ratio 15 | { 16 | inputDimens.width >>= 1; 17 | inputDimens.width <<= 1; 18 | inputDimens.height >>= 1; 19 | inputDimens.height <<= 1; 20 | if (ratio <= 0 || ratio > 1) { 21 | return inputDimens; 22 | } 23 | 24 | 25 | CMVideoDimensions outputDimens = {0,0}; 26 | 27 | int cropW,cropH,sw,sh; 28 | sw = inputDimens.width; 29 | sh = inputDimens.height; 30 | 31 | if(sw/sh == ratio) { 32 | outputDimens.width = inputDimens.width; 33 | outputDimens.height = inputDimens.height; 34 | return outputDimens; 35 | } 36 | 37 | if(sw/sh < ratio) { 38 | for(cropW = 0; cropW < sw; cropW += 2) { 39 | for(cropH = 0; cropH < sh; cropH += 2) { 40 | if((sw - cropW) == ratio * (sh - cropH)) { 41 | outputDimens.height = sh - cropH; 42 | outputDimens.width = sw - cropW; 43 | 44 | return outputDimens; 45 | } 46 | } 47 | } 48 | }else{ 49 | for(cropH = 0; cropH < sh; cropH += 2) { 50 | for(cropW = 0; cropW < sw; cropW += 2) { 51 | if((sw - cropW) == ratio * (sh - cropH)) { 52 | outputDimens.height = sh - cropH; 53 | outputDimens.width = sw - cropW; 54 | 55 | return outputDimens; 56 | } 57 | } 58 | } 59 | } 60 | return outputDimens; 61 | } 62 | 63 | + (CMVideoDimensions)outputVideoDimens:(CMVideoDimensions)inputDimens crop:(float)ratio 64 | { 65 | if (ratio <= 0 || ratio > 1) { 66 | return inputDimens; 67 | } 68 | 69 | CMVideoDimensions outputDimens = inputDimens; 70 | 71 | if (inputDimens.width > inputDimens.height) { 72 | if (inputDimens.width * ratio > inputDimens.height) { 73 | outputDimens.width = inputDimens.height / ratio; 74 | } 75 | else { 76 | outputDimens.height = inputDimens.width * ratio; 77 | } 78 | } 79 | else { 80 | if (inputDimens.height * ratio > inputDimens.width) { 81 | outputDimens.height = inputDimens.width / ratio; 82 | } 83 | else { 84 | outputDimens.width = inputDimens.height * ratio; 85 | } 86 | } 87 | 88 | int32_t mod = outputDimens.width % NVSVideoUtilCropWidthAlignment; 89 | 90 | if (mod) { 91 | outputDimens.width -= mod; 92 | } 93 | 94 | mod = outputDimens.height % NVSVideoUtilCropWidthAlignment; 95 | 96 | if (mod) { 97 | outputDimens.height -= mod; 98 | } 99 | 100 | return outputDimens; 101 | } 102 | 103 | + (CMVideoDimensions)calculateDiemnsDividedByTwo:(int)width andHeight:(int)height 104 | { 105 | CMVideoDimensions dimens = {width,height}; 106 | int32_t mod = dimens.width % NVSVideoUtilCropWidthAlignment; 107 | if (mod) { 108 | dimens.width -= mod; 109 | } 110 | 111 | mod = dimens.height % NVSVideoUtilCropWidthAlignment; 112 | 113 | if (mod) { 114 | dimens.height -= mod; 115 | } 116 | 117 | return dimens; 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /Share/Video/NTESYUVConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // 3 | // Created by fenric on 16/3/25. 4 | // Copyright © 2016年 Netease. All rights reserved. 5 | // 6 | 7 | #import 8 | #import 9 | #import "NTESI420Frame.h" 10 | 11 | 12 | typedef NS_ENUM(uint8_t, NTESVideoPackOrientation) { 13 | NTESVideoPackOrientationPortrait = 0, //No rotation 14 | NTESVideoPackOrientationLandscapeLeft = 1, //Rotate 90 degrees clockwise 15 | NTESVideoPackOrientationPortraitUpsideDown = 2, //Rotate 180 degrees 16 | NTESVideoPackOrientationLandscapeRight = 3, //Rotate 270 degrees clockwise 17 | }; 18 | 19 | @interface NTESYUVConverter : NSObject 20 | 21 | + (NTESI420Frame *)pixelBufferToI420:(CVImageBufferRef)pixelBuffer 22 | withCrop:(float)cropRatio 23 | targetSize:(CGSize)size 24 | andOrientation:(NTESVideoPackOrientation)orientation; 25 | 26 | + (CVPixelBufferRef)i420FrameToPixelBuffer:(NTESI420Frame *)i420Frame; 27 | 28 | + (CMSampleBufferRef)pixelBufferToSampleBuffer:(CVPixelBufferRef)pixelBuffer; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Share/Video/NTESYUVConverter.mm: -------------------------------------------------------------------------------- 1 | // Created by fenric on 16/3/25. 2 | // Copyright © 2016年 Netease. All rights reserved. 3 | // 4 | 5 | #import "NTESYUVConverter.h" 6 | #import "NTESVideoUtil.h" 7 | #import "libyuv.h" 8 | 9 | 10 | @implementation NTESYUVConverter 11 | 12 | + (NTESI420Frame *)I420ScaleWithSourceI420Frame:(NTESI420Frame *)I420Frame 13 | dstWidth:(float)width 14 | dstHeight:(float)height{ 15 | 16 | NTESI420Frame *scaledI420Frame = [[NTESI420Frame alloc] initWithWidth:width height:height]; 17 | 18 | 19 | libyuv::I420Scale([I420Frame dataOfPlane:NTESI420FramePlaneY], 20 | (int)[I420Frame strideOfPlane:NTESI420FramePlaneY], 21 | [I420Frame dataOfPlane:NTESI420FramePlaneU], 22 | (int)[I420Frame strideOfPlane:NTESI420FramePlaneU], 23 | [I420Frame dataOfPlane:NTESI420FramePlaneV], 24 | (int)[I420Frame strideOfPlane:NTESI420FramePlaneV], 25 | I420Frame.width, I420Frame.height, 26 | [scaledI420Frame dataOfPlane:NTESI420FramePlaneY], 27 | (int)[scaledI420Frame strideOfPlane:NTESI420FramePlaneY], 28 | [scaledI420Frame dataOfPlane:NTESI420FramePlaneU], 29 | (int)[scaledI420Frame strideOfPlane:NTESI420FramePlaneU], 30 | [scaledI420Frame dataOfPlane:NTESI420FramePlaneV], 31 | (int)[scaledI420Frame strideOfPlane:NTESI420FramePlaneV], 32 | width, height, libyuv::kFilterNone); 33 | 34 | return scaledI420Frame; 35 | 36 | } 37 | 38 | //+ (NVSI420Frame *)pixelBufferToI420:(CVImageBufferRef)pixelBuffer withCrop:(float)cropRatio targetSize:(CGSize)size andOrientation:(NVSVideoPackOrientation)orientation { 39 | // 40 | //// CMVideoDimensions outputDimens = [NVSVideoUtil outputVideoDimens:inputDimens crop:cropRatio]; 41 | // return [self pixelBufferToI420:pixelBuffer withCrop:cropRatio andScale:0 andOrientation:orientation]; 42 | //} 43 | 44 | + (NTESI420Frame *)pixelBufferToI420:(CVImageBufferRef)pixelBuffer 45 | withCrop:(float)cropRatio 46 | targetSize:(CGSize)size 47 | andOrientation:(NTESVideoPackOrientation)orientation 48 | { 49 | if (pixelBuffer == NULL) { 50 | return nil; 51 | } 52 | 53 | CVPixelBufferLockBaseAddress( pixelBuffer, 0 ); 54 | 55 | OSType sourcePixelFormat = CVPixelBufferGetPixelFormatType( pixelBuffer ); 56 | 57 | 58 | size_t bufferWidth = 0; 59 | size_t bufferHeight = 0; 60 | size_t rowSize = 0; 61 | uint8_t *pixel = NULL; 62 | 63 | if (CVPixelBufferIsPlanar(pixelBuffer)) { 64 | int basePlane = 0; 65 | pixel = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, basePlane); 66 | bufferHeight = CVPixelBufferGetHeightOfPlane(pixelBuffer, basePlane); 67 | bufferWidth = CVPixelBufferGetWidthOfPlane(pixelBuffer, basePlane); 68 | rowSize = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, basePlane); 69 | 70 | } else { 71 | pixel = (uint8_t *)CVPixelBufferGetBaseAddress(pixelBuffer); 72 | bufferWidth = CVPixelBufferGetWidth(pixelBuffer); 73 | bufferHeight = CVPixelBufferGetHeight(pixelBuffer); 74 | rowSize = CVPixelBufferGetBytesPerRow(pixelBuffer); 75 | } 76 | 77 | NTESI420Frame *convertedI420Frame = [[NTESI420Frame alloc] initWithWidth:(int)bufferWidth height:(int)bufferHeight]; 78 | 79 | int error = -1; 80 | 81 | if ( kCVPixelFormatType_32BGRA == sourcePixelFormat ) { 82 | 83 | error = libyuv::ARGBToI420( 84 | pixel, (int)rowSize, 85 | [convertedI420Frame dataOfPlane:NTESI420FramePlaneY], (int)[convertedI420Frame strideOfPlane:NTESI420FramePlaneY], 86 | [convertedI420Frame dataOfPlane:NTESI420FramePlaneU], (int)[convertedI420Frame strideOfPlane:NTESI420FramePlaneU], 87 | [convertedI420Frame dataOfPlane:NTESI420FramePlaneV], (int)[convertedI420Frame strideOfPlane:NTESI420FramePlaneV], 88 | (int)bufferWidth, (int)bufferHeight); 89 | } 90 | else if (kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange == sourcePixelFormat || kCVPixelFormatType_420YpCbCr8BiPlanarFullRange == sourcePixelFormat) { 91 | 92 | error = libyuv::NV12ToI420( 93 | pixel, 94 | (int)rowSize, 95 | (const uint8 *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1), 96 | (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1), 97 | [convertedI420Frame dataOfPlane:NTESI420FramePlaneY], 98 | (int)[convertedI420Frame strideOfPlane:NTESI420FramePlaneY], 99 | [convertedI420Frame dataOfPlane:NTESI420FramePlaneU], 100 | (int)[convertedI420Frame strideOfPlane:NTESI420FramePlaneU], 101 | [convertedI420Frame dataOfPlane:NTESI420FramePlaneV], 102 | (int)[convertedI420Frame strideOfPlane:NTESI420FramePlaneV], 103 | (int)bufferWidth, 104 | (int)bufferHeight); 105 | } 106 | 107 | 108 | if (error) { 109 | CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 ); 110 | NSLog(@"error convert pixel buffer to i420 with error %d", error); 111 | return nil; 112 | } 113 | else { 114 | rowSize = [convertedI420Frame strideOfPlane:NTESI420FramePlaneY]; 115 | pixel = convertedI420Frame.data; 116 | } 117 | 118 | 119 | CMVideoDimensions inputDimens = {(int32_t)bufferWidth, (int32_t)bufferHeight}; 120 | CMVideoDimensions outputDimens = [NTESVideoUtil outputVideoDimensEnhanced:inputDimens crop:cropRatio]; 121 | // CMVideoDimensions outputDimens = {(int32_t)738,(int32_t)1312}; 122 | CMVideoDimensions sizeDimens = {(int32_t)size.width, (int32_t)size.height}; 123 | CMVideoDimensions targetDimens = [NTESVideoUtil outputVideoDimensEnhanced:sizeDimens crop:cropRatio]; 124 | int cropX = (inputDimens.width - outputDimens.width)/2; 125 | int cropY = (inputDimens.height - outputDimens.height)/2; 126 | 127 | if (cropX % 2) { 128 | cropX += 1; 129 | } 130 | 131 | if (cropY % 2) { 132 | cropY += 1; 133 | } 134 | float scale = targetDimens.width*1.0/outputDimens.width; 135 | 136 | NTESI420Frame *croppedI420Frame = [[NTESI420Frame alloc] initWithWidth:outputDimens.width height:outputDimens.height]; 137 | 138 | error = libyuv::ConvertToI420(pixel, bufferHeight * rowSize * 1.5, 139 | [croppedI420Frame dataOfPlane:NTESI420FramePlaneY], (int)[croppedI420Frame strideOfPlane:NTESI420FramePlaneY], 140 | [croppedI420Frame dataOfPlane:NTESI420FramePlaneU], (int)[croppedI420Frame strideOfPlane:NTESI420FramePlaneU], 141 | [croppedI420Frame dataOfPlane:NTESI420FramePlaneV], (int)[croppedI420Frame strideOfPlane:NTESI420FramePlaneV], 142 | cropX, cropY, 143 | (int)bufferWidth, (int)bufferHeight, 144 | croppedI420Frame.width, croppedI420Frame.height, 145 | libyuv::kRotate0, libyuv::FOURCC_I420); 146 | 147 | if (error) { 148 | CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 ); 149 | NSLog(@"error convert pixel buffer to i420 with error %d", error); 150 | return nil; 151 | } 152 | 153 | 154 | NTESI420Frame *i420Frame; 155 | 156 | if (scale == 1.0) { 157 | i420Frame = croppedI420Frame; 158 | }else { 159 | int width = outputDimens.width * scale; 160 | width &= 0xFFFFFFFE; 161 | int height = outputDimens.height * scale; 162 | height &= 0xFFFFFFFE; 163 | 164 | i420Frame = [[NTESI420Frame alloc] initWithWidth:width height:height]; 165 | 166 | libyuv::I420Scale([croppedI420Frame dataOfPlane:NTESI420FramePlaneY], (int)[croppedI420Frame strideOfPlane:NTESI420FramePlaneY], 167 | [croppedI420Frame dataOfPlane:NTESI420FramePlaneU], (int)[croppedI420Frame strideOfPlane:NTESI420FramePlaneU], 168 | [croppedI420Frame dataOfPlane:NTESI420FramePlaneV], (int)[croppedI420Frame strideOfPlane:NTESI420FramePlaneV], 169 | croppedI420Frame.width, croppedI420Frame.height, 170 | [i420Frame dataOfPlane:NTESI420FramePlaneY], (int)[i420Frame strideOfPlane:NTESI420FramePlaneY], 171 | [i420Frame dataOfPlane:NTESI420FramePlaneU], (int)[i420Frame strideOfPlane:NTESI420FramePlaneU], 172 | [i420Frame dataOfPlane:NTESI420FramePlaneV], (int)[i420Frame strideOfPlane:NTESI420FramePlaneV], 173 | i420Frame.width, i420Frame.height, 174 | libyuv::kFilterBilinear); 175 | } 176 | 177 | 178 | int dstWidth, dstHeight; 179 | libyuv::RotationModeEnum rotateMode = [NTESYUVConverter rotateMode:orientation]; 180 | 181 | if (rotateMode != libyuv::kRotateNone) { 182 | if (rotateMode == libyuv::kRotate270 || rotateMode == libyuv::kRotate90) { 183 | dstWidth = i420Frame.height; 184 | dstHeight = i420Frame.width; 185 | } 186 | else { 187 | dstWidth = i420Frame.width; 188 | dstHeight = i420Frame.height; 189 | } 190 | NTESI420Frame *rotatedI420Frame = [[NTESI420Frame alloc]initWithWidth:dstWidth height:dstHeight]; 191 | 192 | libyuv::I420Rotate([i420Frame dataOfPlane:NTESI420FramePlaneY], (int)[i420Frame strideOfPlane:NTESI420FramePlaneY], 193 | [i420Frame dataOfPlane:NTESI420FramePlaneU], (int)[i420Frame strideOfPlane:NTESI420FramePlaneU], 194 | [i420Frame dataOfPlane:NTESI420FramePlaneV], (int)[i420Frame strideOfPlane:NTESI420FramePlaneV], 195 | [rotatedI420Frame dataOfPlane:NTESI420FramePlaneY], (int)[rotatedI420Frame strideOfPlane:NTESI420FramePlaneY], 196 | [rotatedI420Frame dataOfPlane:NTESI420FramePlaneU], (int)[rotatedI420Frame strideOfPlane:NTESI420FramePlaneU], 197 | [rotatedI420Frame dataOfPlane:NTESI420FramePlaneV], (int)[rotatedI420Frame strideOfPlane:NTESI420FramePlaneV], 198 | i420Frame.width, i420Frame.height, 199 | rotateMode); 200 | i420Frame = rotatedI420Frame; 201 | 202 | } 203 | 204 | CVPixelBufferUnlockBaseAddress( pixelBuffer, 0 ); 205 | 206 | return i420Frame; 207 | } 208 | 209 | + (CVPixelBufferRef)i420FrameToPixelBuffer:(NTESI420Frame *)i420Frame 210 | { 211 | if (i420Frame == nil) { 212 | return NULL; 213 | } 214 | 215 | CVPixelBufferRef pixelBuffer = NULL; 216 | 217 | 218 | NSDictionary *pixelBufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys: 219 | [NSDictionary dictionary], (id)kCVPixelBufferIOSurfacePropertiesKey, 220 | nil]; 221 | 222 | CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault, 223 | i420Frame.width, 224 | i420Frame.height, 225 | kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, 226 | (__bridge CFDictionaryRef)pixelBufferAttributes, 227 | &pixelBuffer); 228 | 229 | if (result != kCVReturnSuccess) { 230 | // NVSLogErr(@"Failed to create pixel buffer: %d", result); 231 | return NULL; 232 | } 233 | 234 | 235 | 236 | result = CVPixelBufferLockBaseAddress(pixelBuffer, 0); 237 | 238 | if (result != kCVReturnSuccess) { 239 | CFRelease(pixelBuffer); 240 | // NVSLogErr(@"Failed to lock base address: %d", result); 241 | return NULL; 242 | } 243 | 244 | 245 | uint8 *dstY = (uint8 *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0); 246 | int dstStrideY = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0); 247 | uint8* dstUV = (uint8*)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1); 248 | int dstStrideUV = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1); 249 | 250 | int ret = libyuv::I420ToNV12([i420Frame dataOfPlane:NTESI420FramePlaneY], (int)[i420Frame strideOfPlane:NTESI420FramePlaneY], 251 | [i420Frame dataOfPlane:NTESI420FramePlaneU], (int)[i420Frame strideOfPlane:NTESI420FramePlaneU], 252 | [i420Frame dataOfPlane:NTESI420FramePlaneV], (int)[i420Frame strideOfPlane:NTESI420FramePlaneV], 253 | dstY, dstStrideY, dstUV, dstStrideUV, 254 | i420Frame.width, i420Frame.height); 255 | CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); 256 | if (ret) { 257 | // NVSLogErr(@"Error converting I420 VideoFrame to NV12: %d", result); 258 | CFRelease(pixelBuffer); 259 | return NULL; 260 | } 261 | 262 | return pixelBuffer; 263 | } 264 | 265 | + (libyuv::RotationModeEnum)rotateMode:(NTESVideoPackOrientation)orientation 266 | { 267 | switch (orientation) { 268 | case NTESVideoPackOrientationPortraitUpsideDown: 269 | return libyuv::kRotate180; 270 | case NTESVideoPackOrientationLandscapeLeft: 271 | return libyuv::kRotate90; 272 | case NTESVideoPackOrientationLandscapeRight: 273 | return libyuv::kRotate270; 274 | case NTESVideoPackOrientationPortrait: 275 | default: 276 | return libyuv::kRotate0; 277 | } 278 | } 279 | 280 | 281 | + (CMSampleBufferRef)pixelBufferToSampleBuffer:(CVPixelBufferRef)pixelBuffer 282 | { 283 | if(pixelBuffer == NULL) { 284 | return NULL; 285 | } 286 | CMSampleBufferRef sampleBuffer; 287 | CMTime frameTime = CMTimeMakeWithSeconds([[NSDate date] timeIntervalSince1970], 1000000000); 288 | CMSampleTimingInfo timing = {kCMTimeInvalid, frameTime, kCMTimeInvalid}; 289 | CMVideoFormatDescriptionRef videoInfo = NULL; 290 | CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBuffer, &videoInfo); 291 | 292 | OSStatus status = CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, true, NULL, NULL, videoInfo, &timing, &sampleBuffer); 293 | if (status != noErr) { 294 | NSLog(@"Failed to create sample buffer with error %zd.", status); 295 | } 296 | 297 | CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES); 298 | CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0); 299 | CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue); 300 | 301 | CVPixelBufferRelease(pixelBuffer); 302 | if(videoInfo) 303 | CFRelease(videoInfo); 304 | 305 | return sampleBuffer; 306 | } 307 | 308 | @end 309 | -------------------------------------------------------------------------------- /ShareScreen.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ShareScreen.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ShareScreen.xcodeproj/project.xcworkspace/xcuserdata/ampleskyimac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/githupchenqiang/ScreenShare/0e31ac757736bf321f0adab6dc0fbf825c553561/ShareScreen.xcodeproj/project.xcworkspace/xcuserdata/ampleskyimac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ShareScreen.xcodeproj/xcuserdata/ampleskyimac.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ShareScreen.xcodeproj/xcuserdata/ampleskyimac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Share.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 1 11 | 12 | ShareScreen.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | ShareSetupUI.xcscheme_^#shared#^_ 18 | 19 | orderHint 20 | 2 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ShareScreen/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ShareScreen 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @property (nonatomic, strong)NSURLSessionDataTask *dataTask; 16 | @property (nonatomic, strong)NSTimer* timer; 17 | @property (nonatomic, unsafe_unretained) UIBackgroundTaskIdentifier backgroundTaskIdentifier; 18 | @property (nonatomic, strong)AVAudioPlayer *audioPlayer; 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /ShareScreen/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ShareScreen 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | self.backgroundTaskIdentifier =[application beginBackgroundTaskWithExpirationHandler:^(void) { 32 | [self endBackgroundTask]; 33 | 34 | }]; 35 | 36 | if (!self.audioPlayer) { 37 | [self setAudio]; 38 | NSLog(@"初始化"); 39 | }else{ 40 | [self.audioPlayer play]; 41 | NSLog(@"播放"); 42 | } 43 | 44 | } 45 | 46 | 47 | - (void)applicationWillEnterForeground:(UIApplication *)application { 48 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 49 | } 50 | 51 | 52 | - (void)applicationDidBecomeActive:(UIApplication *)application { 53 | [[UIApplication sharedApplication]endBackgroundTask:self.backgroundTaskIdentifier]; 54 | // 销毁后台任务标识符 55 | self.backgroundTaskIdentifier = UIBackgroundTaskInvalid; 56 | [self.audioPlayer pause]; 57 | 58 | } 59 | 60 | 61 | - (void)applicationWillTerminate:(UIApplication *)application { 62 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 63 | } 64 | 65 | 66 | - (void) endBackgroundTask{ 67 | 68 | dispatch_queue_t mainQueue = dispatch_get_main_queue(); 69 | 70 | AppDelegate *weakSelf = self; 71 | 72 | dispatch_async(mainQueue, ^(void) { 73 | 74 | AppDelegate *strongSelf = weakSelf; 75 | 76 | if (strongSelf != nil){ 77 | 78 | // [strongSelf.myTimer invalidate];// 停止定时器 79 | 80 | // 每个对 beginBackgroundTaskWithExpirationHandler:方法的调用,必须要相应的调用 endBackgroundTask:方法。这样,来告诉应用程序你已经执行完成了。 81 | 82 | // 也就是说,我们向 iOS 要更多时间来完成一个任务,那么我们必须告诉 iOS 你什么时候能完成那个任务。 83 | 84 | // 也就是要告诉应用程序:“好借好还”嘛。 85 | 86 | // 标记指定的后台任务完成 87 | 88 | [[UIApplication sharedApplication]endBackgroundTask:self.backgroundTaskIdentifier]; 89 | 90 | // 销毁后台任务标识符 91 | 92 | strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid; 93 | 94 | } 95 | 96 | }); 97 | 98 | } 99 | 100 | - (void)setAudio{ 101 | dispatch_async(dispatch_get_main_queue(), ^(void) { 102 | NSError *audioSessionError = nil; 103 | AVAudioSession *audioSession = [AVAudioSession sharedInstance]; 104 | if ([audioSession setCategory:AVAudioSessionCategoryPlayback error:&audioSessionError]){ 105 | 106 | NSLog(@"Successfully set the audio session."); 107 | 108 | } else { 109 | NSLog(@"Could not set the audio session"); 110 | } 111 | [audioSession setActive:YES error:nil]; 112 | [[UIApplication sharedApplication]beginReceivingRemoteControlEvents]; 113 | NSBundle *mainBundle = [NSBundle mainBundle]; 114 | 115 | NSString *filePath = [mainBundle pathForResource:@"NoAudio"ofType:@"mp3"]; 116 | 117 | NSData *fileData = [NSData dataWithContentsOfFile:filePath]; 118 | 119 | NSError *error = nil; 120 | 121 | self.audioPlayer = [[AVAudioPlayer alloc] initWithData:fileData error:&error]; 122 | 123 | if (self.audioPlayer != nil){ 124 | // [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(AudioPlayerNotice:) name:AVAudioSessionInterruptionNotification object:nil]; 125 | self.audioPlayer.delegate = self; 126 | 127 | [self.audioPlayer setNumberOfLoops:-1]; 128 | [self.audioPlayer prepareToPlay]; 129 | [self.audioPlayer play]; 130 | if ([self.audioPlayer prepareToPlay] && [self.audioPlayer play]){ 131 | NSLog(@"Successfully started playing..."); 132 | } else { 133 | NSLog(@"Failed to play."); 134 | } 135 | } else { 136 | 137 | } 138 | }); 139 | 140 | } 141 | 142 | @end 143 | -------------------------------------------------------------------------------- /ShareScreen/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /ShareScreen/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ShareScreen/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ShareScreen/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ShareScreen/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | ShareScreen 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ShareScreen/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ShareScreen 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ShareScreen/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ShareScreen 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import "GCDAsyncSocket.h" 12 | #import "NTESTPCircularBuffer.h" 13 | #import "NTESSocketPacket.h" 14 | #import "NTESI420Frame.h" 15 | #import "NTESYUVConverter.h" 16 | @interface ViewController () 17 | @property (nonatomic, strong) GCDAsyncSocket *socket; 18 | @property (nonatomic, strong) dispatch_queue_t queue; 19 | @property (nonatomic, strong) NSMutableArray *sockets; 20 | @property (nonatomic, assign) NTESTPCircularBuffer *recvBuffer; 21 | @property (nonatomic, assign)NSInteger rotation; 22 | @property (nonatomic,strong)RPSystemBroadcastPickerView *broadPickerView; 23 | @end 24 | 25 | @implementation ViewController 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | [self setupSocket]; 30 | [self.view addSubview:self.broadPickerView]; 31 | } 32 | //getMedia 33 | 34 | - (RPSystemBroadcastPickerView *)broadPickerView{ 35 | if(!_broadPickerView){ 36 | _broadPickerView = [[RPSystemBroadcastPickerView alloc] initWithFrame:CGRectMake(100, 100, 50, 50)]; 37 | // _broadPickerView.showsMicrophoneButton = NO; 38 | _broadPickerView.preferredExtension = @"com.amplesky.client.claireye.upLoadPro"; 39 | } 40 | return _broadPickerView; 41 | } 42 | 43 | 44 | - (void)setupSocket 45 | { 46 | 47 | self.sockets = [NSMutableArray array]; 48 | self.recvBuffer = (NTESTPCircularBuffer *)malloc(sizeof(NTESTPCircularBuffer)); // 需要释放 49 | NTESTPCircularBufferInit(self.recvBuffer, kRecvBufferMaxSize); 50 | // self.queue = dispatch_queue_create("com.netease.edu.rp.server", DISPATCH_QUEUE_SERIAL); 51 | self.queue = dispatch_get_main_queue(); 52 | self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:self.queue]; 53 | self.socket.IPv6Enabled = NO; 54 | NSError *error; 55 | // [self.socket acceptOnUrl:[NSURL fileURLWithPath:serverURL] error:&error]; 56 | [self.socket acceptOnPort:8999 error:&error]; 57 | [self.socket readDataWithTimeout:-1 tag:0]; 58 | if (error == nil) 59 | { 60 | NSLog(@"开启成功"); 61 | } 62 | else 63 | { 64 | NSLog(@"开启失败"); 65 | [self setupSocket]; 66 | } 67 | NSNotificationCenter *center =[NSNotificationCenter defaultCenter]; 68 | [center addObserver:self 69 | selector:@selector(defaultsChanged:) 70 | name:NSUserDefaultsDidChangeNotification 71 | object:nil]; 72 | } 73 | 74 | - (void)defaultsChanged:(NSNotification *)notification 75 | { 76 | GCDAsyncSocket *socket = self.sockets.count ? self.sockets[0] : nil; 77 | 78 | NSUserDefaults *defaults = (NSUserDefaults*)[notification object]; 79 | id setting = nil; 80 | // 分辨率 81 | static NSInteger quality; 82 | setting = [defaults objectForKey:@"videochat_preferred_video_quality"]; 83 | if (quality != [setting integerValue] && setting) 84 | { 85 | quality = [setting integerValue]; 86 | NTESPacketHead head; 87 | head.service_id = 0; 88 | head.command_id = 1; // 1:分辨率 2:裁剪比例 3:视频方向 89 | head.data_len = 0; 90 | head.version = 0; 91 | NSString *str = [NSString stringWithFormat:@"%d", [setting intValue]]; 92 | [socket writeData:[NTESSocketPacket packetWithBuffer:[str dataUsingEncoding:NSUTF8StringEncoding] head:&head] withTimeout:-1 tag:0]; 93 | } 94 | 95 | // 视频方向 96 | static NSInteger orientation; 97 | setting = [defaults objectForKey:@"videochat_preferred_video_orientation"]; 98 | if (orientation != [setting integerValue] && setting) 99 | { 100 | orientation = [setting integerValue]; 101 | self.rotation = orientation; 102 | NTESPacketHead head; 103 | head.service_id = 0; 104 | head.command_id = 3; // 1:分辨率 2:裁剪比例 3:视频方向 105 | head.data_len = 0; 106 | head.version = 0; 107 | head.serial_id = 0; 108 | NSString *str = [NSString stringWithFormat:@"%@", setting]; 109 | [socket writeData:[NTESSocketPacket packetWithBuffer:[str dataUsingEncoding:NSUTF8StringEncoding] head:&head] withTimeout:-1 tag:0]; 110 | 111 | } 112 | } 113 | 114 | - (void)stopSocket 115 | { 116 | if (self.socket) 117 | { 118 | [self.socket disconnect]; 119 | self.socket = nil; 120 | [self.sockets removeAllObjects]; 121 | NTESTPCircularBufferCleanup(self.recvBuffer); 122 | } 123 | [[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:nil]; 124 | 125 | } 126 | 127 | #pragma mark - GCDAsyncSocketDelegate 128 | - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(nullable NSError *)err 129 | { 130 | NSLog(@"===断开连接=="); 131 | NTESTPCircularBufferClear(self.recvBuffer); 132 | [self.sockets removeObject:sock]; 133 | } 134 | 135 | - (void)socketDidCloseReadStream:(GCDAsyncSocket *)sock 136 | { 137 | NTESTPCircularBufferClear(self.recvBuffer); 138 | [self.sockets removeObject:sock]; 139 | } 140 | 141 | - (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket 142 | { 143 | NTESTPCircularBufferClear(self.recvBuffer); 144 | [self.sockets addObject:newSocket]; 145 | [newSocket readDataWithTimeout:-1 tag:0]; 146 | } 147 | 148 | - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag 149 | { 150 | static uint64_t currenDataSize = 0; 151 | static uint64_t targeDataSize = 0; 152 | 153 | BOOL isHeader = NO; 154 | if (data.length == sizeof(NTESPacketHead)) { // 检查是不是帧头 155 | NTESPacketHead *header = (NTESPacketHead *)data.bytes; 156 | if (header->version == 1 && header->command_id == 1 && header->service_id == 1) { 157 | isHeader = YES; 158 | targeDataSize = header->data_len; 159 | currenDataSize = 0; 160 | } 161 | } else { 162 | currenDataSize += data.length; 163 | } 164 | 165 | if (isHeader) { // a.接收到新的帧头,需要先把原来的缓存处理或者清空 166 | [self handleRecvBuffer]; 167 | NTESTPCircularBufferProduceBytes(self.recvBuffer, 168 | data.bytes, 169 | (int32_t)data.length); 170 | } else if (currenDataSize >= targeDataSize 171 | && currenDataSize != -1) { // b.加上新来的数据后缓存中已经满足一帧 172 | NTESTPCircularBufferProduceBytes(self.recvBuffer, 173 | data.bytes, 174 | (int32_t)data.length); 175 | currenDataSize = -1; 176 | [self handleRecvBuffer]; 177 | } else { // c.不够一帧,只添加不处理 178 | NTESTPCircularBufferProduceBytes(self.recvBuffer, 179 | data.bytes, 180 | (int32_t)data.length); 181 | } 182 | [sock readDataWithTimeout:-1 tag:0]; 183 | 184 | } 185 | 186 | 187 | - (void)handleRecvBuffer { 188 | if (!self.sockets.count) 189 | { 190 | return; 191 | } 192 | 193 | int32_t availableBytes = 0; 194 | void * buffer = NTESTPCircularBufferTail(self.recvBuffer, &availableBytes); 195 | int32_t headSize = sizeof(NTESPacketHead); 196 | 197 | if(availableBytes <= headSize) { 198 | // NSLog(@" > 不够文件头"); 199 | NTESTPCircularBufferClear(self.recvBuffer); 200 | return; 201 | } 202 | 203 | NTESPacketHead head; 204 | memset(&head, 0, sizeof(head)); 205 | memcpy(&head, buffer, headSize); 206 | uint64_t dataLen = head.data_len; 207 | 208 | if(dataLen > availableBytes - headSize && dataLen >0) { 209 | // NSLog(@" > 不够数据体"); 210 | NTESTPCircularBufferClear(self.recvBuffer); 211 | return; 212 | } 213 | 214 | void *data = malloc(dataLen); 215 | memset(data, 0, dataLen); 216 | memcpy(data, buffer + headSize, dataLen); 217 | NTESTPCircularBufferClear(self.recvBuffer); // 处理完一帧数据就清空缓存 218 | 219 | if([self respondsToSelector:@selector(onRecvData:)]) { 220 | @autoreleasepool { 221 | [self onRecvData:[NSData dataWithBytes:data length:dataLen]]; 222 | }; 223 | } 224 | 225 | free(data); 226 | } 227 | 228 | 229 | #pragma mark - NTESSocketDelegate 230 | 231 | - (void)onRecvData:(NSData *)data 232 | { 233 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 234 | NTESI420Frame *frame = [NTESI420Frame initWithData:data]; 235 | CMSampleBufferRef sampleBuffer = [frame convertToSampleBuffer]; 236 | if (sampleBuffer == NULL) { 237 | return; 238 | } 239 | int64_t timeStampNs = CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer)) * 240 | 1000; 241 | CVPixelBufferRef rtcPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 242 | // RTCVideoFrame *aframe = [[RTCVideoFrame alloc]initWithPixelBuffer:rtcPixelBuffer rotation:self.rotation timeStampNs:timeStampNs]; 243 | // [self.videoCapturer.delegate capturer:self.videoCapturer didCaptureVideoFrame:aframe]; 244 | NSLog(@"%@",sampleBuffer); 245 | CFRelease(sampleBuffer); 246 | }); 247 | 248 | } 249 | 250 | 251 | static NSString * const ScreenHoleNotificationName = @"ScreenHoleNotificationName"; 252 | void MyHoleNotificationCallback(CFNotificationCenterRef center, 253 | void * observer, 254 | CFStringRef name, 255 | void const * object, 256 | CFDictionaryRef userInfo) { 257 | NSString *identifier = (__bridge NSString *)name; 258 | NSObject *sender = (__bridge NSObject *)observer; 259 | //NSDictionary *info = (__bridge NSDictionary *)userInfo; 260 | NSDictionary *info = CFBridgingRelease(userInfo); 261 | 262 | NSLog(@"userInfo %@ %@",userInfo,info); 263 | 264 | NSDictionary *notiUserInfo = @{@"identifier":identifier}; 265 | [[NSNotificationCenter defaultCenter] postNotificationName:ScreenHoleNotificationName 266 | object:sender 267 | userInfo:notiUserInfo]; 268 | } 269 | 270 | 271 | - (void)registerForNotificationsWithIdentifier:(nullable NSString *)identifier { 272 | [self unregisterForNotificationsWithIdentifier:identifier]; 273 | 274 | CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter(); 275 | CFStringRef str = (__bridge CFStringRef)identifier; 276 | CFNotificationCenterAddObserver(center, 277 | (__bridge const void *)(self), 278 | MyHoleNotificationCallback, 279 | str, 280 | NULL, 281 | CFNotificationSuspensionBehaviorDeliverImmediately); 282 | } 283 | - (void)unregisterForNotificationsWithIdentifier:(nullable NSString *)identifier { 284 | CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter(); 285 | CFStringRef str = (__bridge CFStringRef)identifier; 286 | CFNotificationCenterRemoveObserver(center, 287 | (__bridge const void *)(self), 288 | str, 289 | NULL); 290 | } 291 | 292 | @end 293 | -------------------------------------------------------------------------------- /ShareScreen/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ShareScreen 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ShareScreenTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ShareScreenTests/ShareScreenTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ShareScreenTests.m 3 | // ShareScreenTests 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ShareScreenTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ShareScreenTests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | } 20 | 21 | - (void)tearDown { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | - (void)testExample { 26 | // This is an example of a functional test case. 27 | // Use XCTAssert and related functions to verify your tests produce the correct results. 28 | } 29 | 30 | - (void)testPerformanceExample { 31 | // This is an example of a performance test case. 32 | [self measureBlock:^{ 33 | // Put the code you want to measure the time of here. 34 | }]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /ShareScreenUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ShareScreenUITests/ShareScreenUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ShareScreenUITests.m 3 | // ShareScreenUITests 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ShareScreenUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ShareScreenUITests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | 20 | // In UI tests it is usually best to stop immediately when a failure occurs. 21 | self.continueAfterFailure = NO; 22 | 23 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 24 | [[[XCUIApplication alloc] init] launch]; 25 | 26 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 27 | } 28 | 29 | - (void)tearDown { 30 | // Put teardown code here. This method is called after the invocation of each test method in the class. 31 | } 32 | 33 | - (void)testExample { 34 | // Use recording to get started writing UI tests. 35 | // Use XCTAssert and related functions to verify your tests produce the correct results. 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ShareSetupUI/BroadcastSetupViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // BroadcastSetupViewController.h 3 | // ShareSetupUI 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface BroadcastSetupViewController : UIViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ShareSetupUI/BroadcastSetupViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // BroadcastSetupViewController.m 3 | // ShareSetupUI 4 | // 5 | // Created by AmpleSky on 2020/4/8. 6 | // Copyright © 2020年 ampleskyTeam. All rights reserved. 7 | // 8 | 9 | #import "BroadcastSetupViewController.h" 10 | 11 | @implementation BroadcastSetupViewController 12 | 13 | // Call this method when the user has finished interacting with the view controller and a broadcast stream can start 14 | - (void)userDidFinishSetup { 15 | 16 | // URL of the resource where broadcast can be viewed that will be returned to the application 17 | NSURL *broadcastURL = [NSURL URLWithString:@"http://apple.com/broadcast/streamID"]; 18 | 19 | // Dictionary with setup information that will be provided to broadcast extension when broadcast is started 20 | NSDictionary *setupInfo = @{ @"broadcastName" : @"example" }; 21 | 22 | // Tell ReplayKit that the extension is finished setting up and can begin broadcasting 23 | [self.extensionContext completeRequestWithBroadcastURL:broadcastURL setupInfo:setupInfo]; 24 | } 25 | 26 | - (void)userDidCancelSetup { 27 | // Tell ReplayKit that the extension was cancelled by the user 28 | [self.extensionContext cancelRequestWithError:[NSError errorWithDomain:@"YourAppDomain" code:-1 userInfo:nil]]; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ShareSetupUI/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | ShareSetupUI 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | NSExtension 24 | 25 | NSExtensionAttributes 26 | 27 | NSExtensionActivationRule 28 | 29 | NSExtensionActivationSupportsReplayKitStreaming 30 | 31 | 32 | 33 | NSExtensionPointIdentifier 34 | com.apple.broadcast-services-setupui 35 | NSExtensionPrincipalClass 36 | BroadcastSetupViewController 37 | 38 | 39 | 40 | --------------------------------------------------------------------------------