123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- //
- // YOUPAIXLVideoShotTool.m
- // XLChat
- //
- // Created by 张灿 on 2018/2/4.
- // Copyright © 2018年 张灿. All rights reserved.
- //
- #import "YOUPAIXLVideoShotTool.h"
- #import "YOUPAIAGVideoBuffer.h"
- #import "libyuv.h"
- @interface YOUPAIXLVideoShotTool ()
- @property (assign, nonatomic) BOOL isPushing,isUpload;
- @property (strong, nonatomic) YOUPAIAGVideoBuffer *localVideoBuffer;
- @property (strong, nonatomic) YOUPAIAGVideoBuffer *remoteVideoBuffer;
- @property (strong, nonatomic) dispatch_source_t videoPublishTimer;
- @property (strong, nonatomic) dispatch_source_t uploadPublishTimer;
- @end
- @implementation YOUPAIXLVideoShotTool
- + (YOUPAIXLVideoShotTool *)sharedPusher
- {
- static YOUPAIXLVideoShotTool *sharedPusher = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- sharedPusher = [[YOUPAIXLVideoShotTool alloc] init];
- sharedPusher.shotImageArray = [NSMutableArray array];
- sharedPusher.shotImageSem = dispatch_semaphore_create(1);
- });
- return sharedPusher;
- }
- + (dispatch_queue_t)sharedQueue
- {
- static dispatch_queue_t queue = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- queue = dispatch_queue_create("cn.sharesmile.ShotQueue", NULL);
- });
-
- return queue;
- }
- + (void)start
- {
- [[self sharedPusher] start];
- }
- + (void)stop
- {
- [[self sharedPusher] stop];
- }
- - (void)start
- {
- if (self.isPushing) {
- return;
- }
-
- self.isPushing = YES;
- self.isUpload =YES;
- __block int timeout =0;
- __block int checkTime =0;
- WeakSelf;
- // dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- // dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,[YOUPAIXLVideoShotTool sharedQueue]);
- _videoPublishTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,[YOUPAIXLVideoShotTool sharedQueue]);
- // self.videoPublishTimer = timer;
- __block NSMutableArray *startArray = [[self.periodArray valueForKeyPath:@"start"] mutableCopy];
- __block NSMutableArray *endArray = [[self.periodArray valueForKeyPath:@"end"] mutableCopy];
- dispatch_source_set_timer(_videoPublishTimer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒执行
- dispatch_source_set_event_handler(_videoPublishTimer, ^{
- // timeout++;
- //add by leo period 检测周期 shotcycle 截图周期
- __strong typeof (weakSelf)strongSelf = weakSelf;
- #ifdef OLOPornCheck
- if (strongSelf.period==0) {
- if (timeout%weakSelf.shotCycle==0 ) {
- [strongSelf shotImage];
-
- }
- }else{
- if(timeout<2*strongSelf.period)
- {
- if(timeout<=strongSelf.period)
- {
- if(timeout!=0&&timeout%strongSelf.shotCycle==0)
- {
- [strongSelf shotImage];
- }
- }
- }
- else if((timeout/strongSelf.period)%2==0)
- {
- checkTime = timeout / strongSelf.period;
- if(timeout!=strongSelf.period*checkTime)
- {
- if((timeout%strongSelf.period)%strongSelf.shotCycle==0)
- {
- [strongSelf shotImage];
- }
- }
-
-
- }
- else if(timeout%strongSelf.period==0)
- {
- if((strongSelf.period)%strongSelf.shotCycle==0)
- {
- [strongSelf shotImage];
- }
- }
- }
- #endif
- if(startArray!=nil&&startArray.count>0) {
- NSInteger startTime = [[startArray objectAtIndex:0] integerValue];
- NSInteger endTime = [[endArray objectAtIndex:0] integerValue];
- if(timeout>startTime&&(timeout%startTime)%strongSelf.shotCycle==0&&timeout<endTime) {
- [strongSelf shotImage];
- }
- else if(timeout>endTime)
- {
- [startArray removeObjectAtIndex:0];
- [endArray removeObjectAtIndex:0];
- }
- }
- timeout++;
- });
- dispatch_resume(_videoPublishTimer);
- }
- - (void)stop
- {
- if (!self.isPushing) {
- return;
- }
- dispatch_source_cancel(self.videoPublishTimer);
- self.videoPublishTimer = nil;
- // self.uploadPublishTimer = nil;
- self.isPushing = NO;
- [self.shotImageArray removeAllObjects];
- }
- #pragma mark add video data
- + (void)youpaifaddLocalYBuffer:(void *)yBuffer uBuffer:(void *)uBuffer vBuffer:(void *)vBuffer
- yStride:(int)yStride uStride:(int)uStride vStride:(int)vStride
- width:(int)width height:(int)height
- rotation:(int)rotation
- {
- [[self sharedPusher] youpaifaddLocalYBuffer:yBuffer uBuffer:uBuffer vBuffer:vBuffer yStride:yStride uStride:uStride vStride:vStride width:width height:height rotation:rotation];
- }
- + (void)youpaifaddRemoteOfUId:(unsigned int)uid
- yBuffer:(void *)yBuffer uBuffer:(void *)uBuffer vBuffer:(void *)vBuffer
- yStride:(int)yStride uStride:(int)uStride vStride:(int)vStride
- width:(int)width height:(int)height
- rotation:(int)rotation
- {
-
- [[self sharedPusher] youpaifaddRemoteOfUId:uid yBuffer:yBuffer uBuffer:uBuffer vBuffer:vBuffer yStride:yStride uStride:uStride vStride:vStride width:width height:height rotation:rotation];
- }
- - (void)youpaifaddLocalYBuffer:(void *)yBuffer uBuffer:(void *)uBuffer vBuffer:(void *)vBuffer
- yStride:(int)yStride uStride:(int)uStride vStride:(int)vStride
- width:(int)width height:(int)height
- rotation:(int)rotation
- {
- YOUPAIAGVideoBuffer *buffer = [[YOUPAIAGVideoBuffer alloc] initWithUId:0 yBuffer:yBuffer uBuffer:uBuffer vBuffer:vBuffer yStride:yStride uStride:uStride vStride:vStride width:width height:height rotation:rotation];
- dispatch_async([YOUPAIXLVideoShotTool sharedQueue], ^{
- if (self.localVideoBuffer != nil && self.localVideoBuffer.width == width && self.localVideoBuffer.height == height) {
- [self.localVideoBuffer youpaifupdateWithYBuffer:buffer.yBuffer uBuffer:buffer.uBuffer vBuffer:buffer.vBuffer yStride:buffer.yStride uStride:buffer.uStride vStride:buffer.vStride width:buffer.width height:buffer.height rotation:buffer.rotation];
- } else {
- self.localVideoBuffer = buffer;
- }
- });
-
- }
- - (void)youpaifaddRemoteOfUId:(unsigned int)uid
- yBuffer:(void *)yBuffer uBuffer:(void *)uBuffer vBuffer:(void *)vBuffer
- yStride:(int)yStride uStride:(int)uStride vStride:(int)vStride
- width:(int)width height:(int)height
- rotation:(int)rotation
- {
- // NSLog(@"youpaifaddRemoteOfUId CALLBALCK\n");
- return;
- dispatch_semaphore_wait(self.shotImageSem, DISPATCH_TIME_FOREVER);
- self.remoteVideoBuffer = [[YOUPAIAGVideoBuffer alloc] initWithUId:0 yBuffer:yBuffer uBuffer:uBuffer vBuffer:vBuffer yStride:yStride uStride:uStride vStride:vStride width:width height:height rotation:rotation];
- dispatch_semaphore_signal(self.shotImageSem);
- // dispatch_async([YOUPAIXLVideoShotTool sharedQueue], ^{
- // if (self.remoteVideoBuffer != nil && self.remoteVideoBuffer.width == width && self.remoteVideoBuffer.height == height) {
- // [self.remoteVideoBuffer youpaifupdateWithYBuffer:buffer.yBuffer uBuffer:buffer.uBuffer vBuffer:buffer.vBuffer yStride:buffer.yStride uStride:buffer.uStride vStride:buffer.vStride width:buffer.width height:buffer.height rotation:buffer.rotation];
- // } else {
- // self.remoteVideoBuffer = buffer;
- // }
- // });
-
-
- }
- -(void)shotImage {
- //modify by leo
- dispatch_async(dispatch_get_main_queue(), ^{
- UIImage *image = [UIImage screenView:self.localVideo];
- //UIImage *image= [UIImage imageNamed:@"jianhuang"];
- NSLog(@"上传截图");
- NSDate * newData = [NSDate date];
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
- NSString* dataString = [dateFormatter stringFromDate:newData];
- NSLog(@"截图时间 is %@\n",dataString);
- if(self->_isUpload) {
- [self youpaifuploadImage:image];
- // [self SavePhotoLibary:image];
- }
-
- // self.remoteVideoBuffer = nil;
- });
-
- }
- #pragma mark - 访问相册
- -(void)SavePhotoLibary:(UIImage *)image{
- if(@available(iOS 11.0, *))
- {
- [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status)
- {
- if (status == PHAuthorizationStatusNotDetermined || status == PHAuthorizationStatusAuthorized) {
- [self loadImageFinished:image];
-
- }else
- {
- // [ZCHUDHelper showTitle:@"请给予相册保存权限" showtime:2];
- return ;
-
- }
-
- }];
- }
- else
- {
- PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
- if (authStatus == PHAuthorizationStatusRestricted|| authStatus == PHAuthorizationStatusDenied)
- {
- // [ZCHUDHelper showTitle:@"请给予相册保存权限" showtime:2];
- return;
-
- }
- else{
- [self loadImageFinished:image];
- }
- }
- }
- - (void)loadImageFinished:(UIImage *)image
- {
- [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
-
- //写入图片到相册
-
- [PHAssetChangeRequest creationRequestForAssetFromImage:image];
-
- } completionHandler:^(BOOL success, NSError * _Nullable error) {
-
- NSLog(@"success = %d, error = %@", success, error);
- if(success){
- dispatch_async(dispatch_get_main_queue(), ^{
- // [ZCHUDHelper showTitle:@"保存成功" showtime:1];
- });
- }
- }];
- }
- - (void)shotImage2{
- dispatch_semaphore_wait(self.shotImageSem, DISPATCH_TIME_FOREVER);
- if(self.remoteVideoBuffer){
- //add by leo for test
- NSLog(@"shotImage called \n");
- int retomeYBufferSize = self.remoteVideoBuffer.yStride * self.remoteVideoBuffer.height;
- int retomeUBufferSize = self.remoteVideoBuffer.uStride * self.remoteVideoBuffer.height / 2;
- int retomeVBufferSize = self.remoteVideoBuffer.vStride * self.remoteVideoBuffer.height / 2;
- unsigned char *retomeYBuffer = [YOUPAIAGVideoBuffer copy:self.remoteVideoBuffer.yBuffer size:retomeYBufferSize];
- unsigned char *retomeUBuffer = [YOUPAIAGVideoBuffer copy:self.remoteVideoBuffer.uBuffer size:retomeUBufferSize];
- unsigned char *retomeVBuffer = [YOUPAIAGVideoBuffer copy:self.remoteVideoBuffer.vBuffer size:retomeVBufferSize];
- NSLog(@"retomeUBuffer is %s",retomeUBuffer);
- //rotate local
- unsigned char *rotatedretomeYBuffer = malloc(retomeYBufferSize);
- unsigned char *rotatedretomeUBuffer = malloc(retomeUBufferSize);
- unsigned char *rotatedretomeVBuffer = malloc(retomeVBufferSize);
-
- I420Rotate(retomeYBuffer, self.remoteVideoBuffer.yStride,
- retomeUBuffer, self.remoteVideoBuffer.uStride,
- retomeVBuffer, self.remoteVideoBuffer.vStride,
- rotatedretomeYBuffer, self.remoteVideoBuffer.height,
- rotatedretomeUBuffer, self.remoteVideoBuffer.height/2,
- rotatedretomeVBuffer, self.remoteVideoBuffer.height/2,
- self.remoteVideoBuffer.height, self.remoteVideoBuffer.width, self.remoteVideoBuffer.rotation);
-
-
- free(retomeYBuffer);
- free(retomeUBuffer);
- free(retomeVBuffer);
-
- int dataLength = retomeYBufferSize + retomeUBufferSize + retomeVBufferSize;
- unsigned char *youpaifyuvData = malloc(dataLength);
- memcpy(youpaifyuvData, rotatedretomeYBuffer, retomeYBufferSize);
- memcpy(youpaifyuvData + retomeYBufferSize, rotatedretomeUBuffer, retomeUBufferSize);
- memcpy(youpaifyuvData + retomeYBufferSize + retomeUBufferSize, rotatedretomeVBuffer, retomeVBufferSize);
-
- UIImage* image =[self makeUIImage:self.remoteVideoBuffer];
- [self youpaifuploadImage:image];
- free(youpaifyuvData);
- free(rotatedretomeYBuffer);
- free(rotatedretomeUBuffer);
- free(rotatedretomeVBuffer);
- self.remoteVideoBuffer = nil;
- }
- dispatch_semaphore_signal(self.shotImageSem);
-
- }
- - (UIImage *)makeUIImage:(YOUPAIAGVideoBuffer*)videoBuffer
- {
- unsigned char* argb = (unsigned char*)malloc(videoBuffer.width * videoBuffer.height * 4 * sizeof(unsigned char));
- I420ToARGB(videoBuffer.yBuffer, videoBuffer.yStride, videoBuffer.uBuffer, videoBuffer.uStride, videoBuffer.vBuffer, videoBuffer.vStride, argb, 4*videoBuffer.width, videoBuffer.width, videoBuffer.height);
-
-
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-
- CGContextRef context = CGBitmapContextCreate(argb, videoBuffer.width, videoBuffer.height, 8, videoBuffer.width * 4, colorSpace,
-
- kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
-
- CGImageRef quartzImage = CGBitmapContextCreateImage(context);
- CGContextRelease(context);
- CGColorSpaceRelease(colorSpace);
- UIImage *image = [UIImage imageWithCGImage:quartzImage];
- CGImageRelease(quartzImage);
- free(argb);
- argb = NULL;
- return image;
-
- }
- - (UIImage *)makeUIImage:(unsigned char *)inBaseAddress
- width:(int)inWidth
- height:(int)inHeight
- {
- int scale = 1;
- unsigned char* y0 = inBaseAddress;
- unsigned char* uv0 = inBaseAddress + inWidth * inHeight * sizeof(unsigned char);
- // int outWidth = inWidth / scale;
- // int outHeight = inHeight / scale;
- inWidth = (inWidth >> 2) << 2;
- inHeight = (inHeight >> 2) << 2;
- align_buffer_64(sdata, inWidth * inHeight * 1.5 * sizeof(unsigned char));
- unsigned char* y1 = sdata;
- unsigned char* uv1 = sdata + inWidth * inHeight;
- memset(uv1, 128, 0.5 * inWidth * inHeight);
- ScalePlane_16((uint16*)uv0, inWidth / 2,
- inWidth / 2, inHeight / 2,
- (uint16*)uv1, inWidth / 2,
- inWidth / 2, inHeight / 2,
- kFilterNone);
- ScalePlane(y0, inWidth,
- inWidth, inHeight,
- y1, inWidth,
- inWidth, inHeight,
- kFilterNone);
-
- unsigned char* argb = (unsigned char*)malloc(inWidth * inHeight * 4 * sizeof(unsigned char));
- NV12ToARGB(y1, inWidth, uv1, inWidth, argb, inWidth * 4, inWidth, inHeight);
- // int NV12ToARGB(const uint8* src_y, int src_stride_y,
- // const uint8* src_uv, int src_stride_uv,
- // uint8* dst_argb, int dst_stride_argb,
- // int width, int height);
- // int I420ToARGB(const uint8* src_y, int src_stride_y,
- // const uint8* src_u, int src_stride_u,
- // const uint8* src_v, int src_stride_v,
- // uint8* dst_argb, int dst_stride_argb,
- // int width, int height);
- free_aligned_buffer_64(sdata);
-
- CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-
- CGContextRef context = CGBitmapContextCreate(argb, inWidth, inHeight, 8, inWidth * 4, colorSpace,
-
- kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
-
- CGImageRef quartzImage = CGBitmapContextCreateImage(context);
- CGContextRelease(context);
- CGColorSpaceRelease(colorSpace);
- UIImage *image = [UIImage imageWithCGImage:quartzImage];
- CGImageRelease(quartzImage);
- free(argb);
- argb = NULL;
- return image;
- }
- - (void)youpaifuploadImage:(UIImage*)image{
-
-
- NSData *imageData = [UIImage zipNSDataWithImage:image maxFileSize:20*1024];
- NSString *encodedImageStr = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
- NSMutableDictionary* parm = [NSMutableDictionary dictionary];
- [parm setObject:self.room_id forKey:@"room_id"];
- [parm setObject:encodedImageStr forKey:@"from"];
- //[parm setObject:encodedImageStr forKey:@"to"];
- if (self.isFrom) { // 主叫
- [parm setObject:self.uid forKey:@"uid"];
- }else{ // 被叫
- [parm setObject:self.uid forKey:@"uid"];
- }
- WeakSelf;
- [LCHttpHelper requestWithURLString:VideoPornCheck parameters:parm needToken:YES type:(HttpRequestTypePost) success:^(id responseObject) {
- NSLog(@"输出🍀VideoPornCheck\n%@",responseObject);
- NSDictionary* dict = (NSDictionary*)responseObject;
- NSInteger code = [[dict objectForKey:@"code"] integerValue];
- if (code==0) {
- if ([dict[@"data"][@"is_upload"] integerValue] == 0) {
- weakSelf.isUpload = NO;
- }
- }
- } failure:^(NSError *error) {
- NSLog(@"输出🍀VideoPornCheck\n%@",error);
-
- }];
- }
- @end
|