├── 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 |
--------------------------------------------------------------------------------