萤石云 iOSSDK,移植跨平台相关工程
Davin
2024-12-18 b4e1288a9b63eb820e9c9489c56aac4bf6b31067
EZSDK/EZSDK/EZ/UIViewControllers/EZPlaybackViewController.m
@@ -10,27 +10,31 @@
#import "UIViewController+EZBackPop.h"
#import "DDCollectionViewFlowLayout.h"
#import "MJRefresh.h"
#import "EZRecordDownloader.h"
#import "EZDeviceRecordDownloadTask.h"
#import "EZCloudRecordDownloadTask.h"
#import <EZOpenSDKFramework/EZRecordDownloader.h>
#import <EZOpenSDKFramework/EZDeviceRecordDownloadTask.h>
#import <EZOpenSDKFramework/EZCloudRecordDownloadTask.h>
#import "EZRecordCell.h"
#import "DDKit.h"
#import "EZCloudRecordFile.h"
#import "EZDeviceRecordFile.h"
#import "EZPlayer.h"
#import <EZOpenSDKFramework/EZCloudRecordFile.h>
#import <EZOpenSDKFramework/EZDeviceRecordFile.h>
#import <EZOpenSDKFramework/EZPlayer.h>
#import "HIKLoadView.h"
#import "Masonry.h"
#import "EZCameraInfo.h"
#import <EZOpenSDKFramework/EZCameraInfo.h>
#import "MBProgressHUD.h"
#import "Toast+UIView.h"
#import "EZCustomTableView.h"
#import "EZStreamPlayer.h"
#import <EZOpenSDKFramework/EZStreamPlayer.h>
#import <Photos/Photos.h>
#import "FCFileManager.h"
#import <EZOpenSDKFramework/EZVideoTransformer.h>
@interface EZPlaybackViewController ()<DDCollectionViewDelegateFlowLayout, UICollectionViewDataSource,EZPlayerDelegate, UIAlertViewDelegate, EZRecordCellDelegate, EZCustomTableViewDelegate,EZStreamPlayerDelegate>
{
    BOOL _isOpenSound;
    BOOL _isPlaying;
    BOOL _landscape;    // 是否旋转
    
    NSTimeInterval _playSeconds; //播放秒数
    NSTimeInterval _duringSeconds; //录像时长
@@ -57,6 +61,7 @@
@property (nonatomic, strong) HIKLoadView *loadingView;
@property (nonatomic) BOOL isSelectedDevice;
@property (nonatomic, weak) IBOutlet UIView *playerView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *playViewWHScale;
@property (nonatomic, weak) IBOutlet UILabel *largeTitleLabel;
@property (nonatomic, weak) IBOutlet UIDatePicker *datePicker;
@property (nonatomic, weak) IBOutlet UITextField *dateTextField;
@@ -115,6 +120,7 @@
    self.isAutorotate = YES;
    self.largeTitleLabel.text = self.deviceInfo.deviceName;
    self.largeTitleLabel.hidden = YES;
    _landscape = NO;
    
    if(!_records)
        _records = [NSMutableArray new];
@@ -227,7 +233,17 @@
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAllButUpsideDown;
    if (@available(iOS 16.0, *)) {
        if (_landscape) {
            //横屏
            return UIInterfaceOrientationMaskLandscape;
        } else {
            //竖屏
            return UIInterfaceOrientationMaskPortrait;
        }
    } else {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
@@ -242,6 +258,13 @@
    self.largeButton.hidden = NO;
    self.voiceButton.hidden = NO;
    self.playButton.hidden = NO;
    [self.playerView setTranslatesAutoresizingMaskIntoConstraints:NO];
    [NSLayoutConstraint deactivateConstraints:@[self.playViewWHScale]];
    self.playViewWHScale = [NSLayoutConstraint constraintWithItem:self.playerView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.playerView attribute:NSLayoutAttributeHeight multiplier:16/9. constant:0];
    [NSLayoutConstraint activateConstraints:@[self.playViewWHScale]];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.playerView layoutIfNeeded];
    });
    if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
       toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
    {
@@ -254,6 +277,18 @@
        self.playbackList.hidden = YES;
        self.largeBackButton.hidden = NO;
        self.navigationController.navigationBarHidden = YES;
        CGFloat tureScreenW = HDLEZ_APP_SCREEN_WIDTH > HDLEZ_APP_SCREEN_HEIGHT ? HDLEZ_APP_SCREEN_HEIGHT : HDLEZ_APP_SCREEN_WIDTH;
        CGFloat tureScreenH = HDLEZ_APP_SCREEN_WIDTH < HDLEZ_APP_SCREEN_HEIGHT ? HDLEZ_APP_SCREEN_HEIGHT : HDLEZ_APP_SCREEN_WIDTH;
        [self.playerView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [NSLayoutConstraint deactivateConstraints:@[self.playViewWHScale]];
        self.playViewWHScale = [NSLayoutConstraint constraintWithItem:self.playerView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.playerView attribute:NSLayoutAttributeHeight multiplier:tureScreenH/(tureScreenW) constant:0];
        [NSLayoutConstraint activateConstraints:@[self.playViewWHScale]];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.playerView layoutIfNeeded];
        });
    }
}
@@ -301,7 +336,7 @@
    cell.isSelectedDevice = _isSelectedDevice;
    cell.delegate = self;
    //2021-07-21 隐藏下载按钮
    [cell.downloadBtn setHidden:YES];
    [cell.downloadBtn setHidden:NO];
    
    if(_isSelectedDevice)
    {
@@ -389,9 +424,16 @@
        
        EZDeviceRecordFile *deviceFile = (EZDeviceRecordFile *)recordFile;
        
        NSString *path = [NSString stringWithFormat:@"%@/ezopensdk/DeviceRecord/%@.ps",[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject], [dateformatter stringFromDate:deviceFile.startTime]];
        NSString *path = [NSString stringWithFormat:@"%@/ezopensdk/DeviceRecord/%@.ps",[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject], [dateformatter stringFromDate:deviceFile.startTime]];
        NSLog(@"path: %@ ", path);
        [self startDeviceRecordDownload:path deviceFile:deviceFile];
        __weak __typeof(self)weakSelf = self;
        [self authPhotoLibraries:^(BOOL isAblity) {
            if (isAblity) {
                [weakSelf startDeviceRecordDownload:path deviceFile:deviceFile];
            } else {
                [weakSelf guideUserOpenAuth];
            }
        }];
    }
    else {
        
@@ -422,10 +464,17 @@
            NSLog(@"statuCode:%ld", (long)statusCode);
            
            switch (statusCode) {
                case EZRecordDownloaderStatusFinish:
                    [self.navigationController.view makeToast:[NSString stringWithFormat:@"SDD Task:%lu-下载成功", (unsigned long)strongTask.taskID]];
                case EZRecordDownloaderStatusFinish:{
                    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                        NSLog(@"#########开始保存视频!!!!%@", path);
                        NSDateFormatter *dateformatter = [[NSDateFormatter alloc] init];
                        dateformatter.dateFormat = @"yyyyMMddHHmmss";
                        NSString *mp4Path = [NSString stringWithFormat:@"%@/ezopensdk/DeviceRecord/%@.mp4", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject], [dateformatter stringFromDate:deviceFile.startTime]];
                        [self videoFormatConvertAndSave2Album:path mp4Path:mp4Path];
                    });
                }
                    break;
                case EZRecordDownloaderStatusMoreToken:
                    
@@ -468,6 +517,40 @@
    }];
}
/** 如果需要把回放视频保存到相册,一定要先把.ps文件转成.mp4文件
    注意:下载录像过程中因为网络原因导致.ps文件未下载完,也可以调用此方法将已下载的录像片段解码成.mp4文件。
 */
- (void)videoFormatConvertAndSave2Album:(NSString *)psPath mp4Path:(NSString *)mp4Path {
    [FCFileManager createFileAtPath:mp4Path overwrite:YES];
    __weak typeof(self) weakSelf = self;
    [EZVideoTransformer videoTransFormerPSPath:psPath toPath:mp4Path type:EZVideoTransformerTypeMP4 withKey:_verifyCode succBlock:^{
        NSLog(@"转换成功");
        // 将.mp4文件保存到相册
        PHPhotoLibrary *photoLibrary = [PHPhotoLibrary sharedPhotoLibrary];
        [photoLibrary performChanges:^{
            [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:mp4Path]];
        } completionHandler:^(BOOL success, NSError * _Nullable error) {
            if (success) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [weakSelf.navigationController.view makeToast:HDLEZLocallizedString(@"device_save_gallery")];
                });
                NSLog(@"########保存成功!!!");
                // 下载完成后删除.ps和.mp4文件
                [FCFileManager removeItemAtPath:psPath];
                [FCFileManager removeItemAtPath:mp4Path];
            } else {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [weakSelf.navigationController.view makeToast:HDLEZLocallizedString(@"device_save_gallery_failure")];
                });
            }
        }];
    } processBlock:^(int rate) {
        // 转换进度
    } failBlock:^(int errCode) {
        NSLog(@"转换失败");
    }];
}
- (void) startCloudRecordDownload:(NSString*)path cloudFile:(EZCloudRecordFile *)cloudFile {
    
    EZCloudRecordDownloadTask *task = [[EZCloudRecordDownloadTask alloc] initTaskWithID:_selectedIndexPath.row cloudRecordFile:cloudFile verifyCode:self.verifyCode savePath:path];
@@ -480,9 +563,17 @@
        NSLog(@"statuCode:%ld", (long)statusCode);
        
        switch (statusCode) {
            case EZRecordDownloaderStatusFinish:
                [self.navigationController.view makeToast:[NSString stringWithFormat:@"CD Task:%lu-下载成功", (unsigned long)strongTask.taskID]];
            case EZRecordDownloaderStatusFinish: {
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    NSLog(@"#########开始保存视频!!!!%@", path);
                    NSDateFormatter *dateformatter = [[NSDateFormatter alloc] init];
                    dateformatter.dateFormat = @"yyyyMMddHHmmss";
                    NSString *mp4Path = [NSString stringWithFormat:@"%@/ezopensdk/DeviceRecord/%@.mp4", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject], [dateformatter stringFromDate:cloudFile.startTime]];
                    [self videoFormatConvertAndSave2Album:path mp4Path:mp4Path];
                });
            }
                
                break;
            case EZRecordDownloaderStatusMoreToken:
@@ -519,6 +610,69 @@
            [self.navigationController.view makeToast:[NSString stringWithFormat:@"CD Task:%lu-任务已在下载中", (unsigned long)task.taskID]];
        }
    }
}
#pragma mark 视频保存完毕的回调
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (error) {
            [self.navigationController.view makeToast:HDLEZLocallizedString(@"device_save_gallery_failure")];
            NSLog(@"保存视频过程中发生错误,错误信息:%@",error.localizedDescription);
            NSLog(@"保存视频过程中发生错误,错误信息:%@",error);
        }else{
            [self.navigationController.view makeToast:HDLEZLocallizedString(@"device_save_gallery")];
            NSLog(@"视频保存成功.");
        }
    });
}
/*访问相册权限
 */
-(void)authPhotoLibraries:(void(^)(BOOL isAblity))result {
    PHAuthorizationStatus author =[PHPhotoLibrary authorizationStatus];
    if (author == PHAuthorizationStatusRestricted || author ==PHAuthorizationStatusDenied){
        if (result) {
            result(NO);
        }
    } else if (author == PHAuthorizationStatusNotDetermined) {  // 首次授权
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_async(queue, ^{
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                if (status != PHAuthorizationStatusAuthorized) {
                    if (result) {
                        result(NO);
                    }
                } else {
                    if (result) {
                        result(YES);
                    }
                }
            }];
        });
    } else {
        if (result) {
            result(YES);
        }
    }
}
/*引导用户授权获取图片
 */
- (void)guideUserOpenAuth{
    UIAlertController *alertC = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"hdl_ez_download_tip", @"温馨提示") message:NSLocalizedString(@"hdl_ez_download_auth", @"请打开访问权限") preferredStyle:(UIAlertControllerStyleAlert)];
    UIAlertAction *alertA = [UIAlertAction actionWithTitle:NSLocalizedString(@"hdl_ez_download_cancle", @"取消") style:(UIAlertActionStyleDefault) handler:nil];
    UIAlertAction *act = [UIAlertAction actionWithTitle:NSLocalizedString(@"hdl_ez_download_toSet", @"去设置") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        // 引导用户设置
        NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
        if ([[UIApplication sharedApplication] canOpenURL:url]) {
            [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
        }
    }];
    [alertC addAction:alertA];
    [alertC addAction:act];
    [self presentViewController:alertC animated:YES completion:nil];
}
#pragma mark - PlayerDelegate Methods
@@ -757,14 +911,60 @@
- (IBAction)large:(id)sender
{
    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
//    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
//    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    if (_landscape == YES) {
        [self largeBack:self.largeBackButton];
        return;
    }
    _landscape = YES;
    if (@available(iOS 16.0, *)) {
        if (self.navigationController) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.navigationController setNeedsUpdateOfSupportedInterfaceOrientations];
            });
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self setNeedsUpdateOfSupportedInterfaceOrientations];
            });
        }
        NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
        UIWindowScene *ws = (UIWindowScene *)array.firstObject;
        UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] init];
        geometryPreferences.interfaceOrientations = UIInterfaceOrientationMaskLandscape;
        [ws requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) {
            NSLog(@"iOS 16 Error: %@",error);
        }];
    } else {
        NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
}
- (IBAction)largeBack:(id)sender
{
    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    _landscape = NO;
    if (@available(iOS 16.0, *)) {
        if (self.navigationController) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.navigationController setNeedsUpdateOfSupportedInterfaceOrientations];
            });
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self setNeedsUpdateOfSupportedInterfaceOrientations];
            });
        }
        NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
        UIWindowScene *ws = (UIWindowScene *)array.firstObject;
        UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] init];
        geometryPreferences.interfaceOrientations = UIInterfaceOrientationMaskPortrait;
        [ws requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:^(NSError * _Nonnull error) {
            NSLog(@"iOS 16 Error: %@",error);
        }];
    } else {
        NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
}
- (IBAction)voiceButtonClicked:(id)sender
@@ -1160,4 +1360,8 @@
    }
}
- (BOOL)prefersHomeIndicatorAutoHidden {
    return YES;
}
@end