123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- //
- // YBIBVideoData.m
- // YBImageBrowserDemo
- //
- // Created by 波儿菜 on 2019/7/10.
- // Copyright © 2019 杨波. All rights reserved.
- //
- #import "YBIBVideoData.h"
- #import "YBIBVideoCell.h"
- #import "YBIBVideoData+Internal.h"
- #import "YBIBUtilities.h"
- #import "YBIBPhotoAlbumManager.h"
- #import "YBIBCopywriter.h"
- extern CGImageRef YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decodeForDisplay);
- @interface YBIBVideoData () <NSURLSessionDelegate>
- @end
- @implementation YBIBVideoData {
- NSURLSessionDownloadTask *_downloadTask;
- }
- #pragma mark - life cycle
- - (instancetype)init {
- self = [super init];
- if (self) {
- [self initValue];
- }
- return self;
- }
- - (void)initValue {
- _loadingFirstFrame = NO;
- _loadingAVAssetFromPHAsset = NO;
- _downloading = NO;
- _interactionProfile = [YBIBInteractionProfile new];
- _repeatPlayCount = 0;
- _autoPlayCount = 0;
- _shouldHideForkButton = NO;
- _allowSaveToPhotoAlbum = YES;
- }
- #pragma mark - load data
- - (void)loadData {
- // Always load 'thumbImage'.
- [self loadThumbImage];
-
- if (self.videoAVAsset) {
- [self.delegate yb_videoData:self readyForAVAsset:self.videoAVAsset];
- } else if (self.videoPHAsset) {
- [self loadAVAssetFromPHAsset];
- } else {
- [self.delegate yb_videoIsInvalidForData:self];
- }
- }
- - (void)loadAVAssetFromPHAsset {
- if (!self.videoPHAsset) return;
- if (self.isLoadingAVAssetFromPHAsset) {
- self.loadingAVAssetFromPHAsset = YES;
- return;
- }
-
- self.loadingAVAssetFromPHAsset = YES;
- [YBIBPhotoAlbumManager getAVAssetWithPHAsset:self.videoPHAsset completion:^(AVAsset * _Nullable asset) {
- YBIB_DISPATCH_ASYNC_MAIN(^{
- self.loadingAVAssetFromPHAsset = NO;
-
- self.videoAVAsset = asset;
- [self.delegate yb_videoData:self readyForAVAsset:self.videoAVAsset];
- [self loadThumbImage];
- })
- }];
- }
- - (void)loadThumbImage {
- if (self.thumbImage) {
- [self.delegate yb_videoData:self readyForThumbImage:self.thumbImage];
- } else if (self.projectiveView && [self.projectiveView isKindOfClass:UIImageView.self] && ((UIImageView *)self.projectiveView).image) {
- self.thumbImage = ((UIImageView *)self.projectiveView).image;
- [self.delegate yb_videoData:self readyForThumbImage:self.thumbImage];
- } else {
- [self loadThumbImage_firstFrame];
- }
- }
- - (void)loadThumbImage_firstFrame {
- if (!self.videoAVAsset) return;
- if (self.isLoadingFirstFrame) {
- self.loadingFirstFrame = YES;
- return;
- }
-
- self.loadingFirstFrame = YES;
- CGSize containerSize = self.yb_containerSize(self.yb_currentOrientation());
- CGSize maximumSize = containerSize;
-
- __weak typeof(self) wSelf = self;
- YBIB_DISPATCH_ASYNC(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-
- AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:self.videoAVAsset];
- generator.appliesPreferredTrackTransform = YES;
- generator.maximumSize = maximumSize;
- NSError *error = nil;
- CGImageRef cgImage = [generator copyCGImageAtTime:CMTimeMake(0, 1) actualTime:NULL error:&error];
- CGImageRef decodedImage = YYCGImageCreateDecodedCopy(cgImage, YES);
- UIImage *resultImage = [UIImage imageWithCGImage:decodedImage];
- if (cgImage) CGImageRelease(cgImage);
- if (decodedImage) CGImageRelease(decodedImage);
-
- YBIB_DISPATCH_ASYNC_MAIN(^{
- __strong typeof(wSelf) self = wSelf;
- if (!self) return;
- self.loadingFirstFrame = NO;
- if (!error && resultImage) {
- self.thumbImage = resultImage;
- [self.delegate yb_videoData:self readyForThumbImage:self.thumbImage];
- }
- })
- })
- }
- #pragma mark - <YBIBDataProtocol>
- @synthesize yb_currentOrientation = _yb_currentOrientation;
- @synthesize yb_containerView = _yb_containerView;
- @synthesize yb_containerSize = _yb_containerSize;
- @synthesize yb_isHideTransitioning = _yb_isHideTransitioning;
- @synthesize yb_auxiliaryViewHandler = _yb_auxiliaryViewHandler;
- - (nonnull Class)yb_classOfCell {
- return YBIBVideoCell.self;
- }
- - (UIView *)yb_projectiveView {
- return self.projectiveView;
- }
- - (CGRect)yb_imageViewFrameWithContainerSize:(CGSize)containerSize imageSize:(CGSize)imageSize orientation:(UIDeviceOrientation)orientation {
- if (containerSize.width <= 0 || containerSize.height <= 0 || imageSize.width <= 0 || imageSize.height <= 0) return CGRectZero;
- CGFloat x = 0, y = 0, width = 0, height = 0;
- if (imageSize.width / imageSize.height >= containerSize.width / containerSize.height) {
- width = containerSize.width;
- height = containerSize.width * (imageSize.height / imageSize.width);
- x = 0;
- y = (containerSize.height - height) / 2.0;
- } else {
- height = containerSize.height;
- width = containerSize.height * (imageSize.width / imageSize.height);
- x = (containerSize.width - width) / 2.0;
- y = 0;
- }
- return CGRectMake(x, y, width, height);
- }
- - (void)yb_preload {
- if (!self.delegate) {
- [self loadData];
- }
- }
- - (BOOL)yb_allowSaveToPhotoAlbum {
- return self.allowSaveToPhotoAlbum;
- }
- - (void)yb_saveToPhotoAlbum {
- void(^unableToSave)(void) = ^(){
- [self.yb_auxiliaryViewHandler() yb_showIncorrectToastWithContainer:self.yb_containerView text:[YBIBCopywriter sharedCopywriter].unableToSave];
- };
-
- if (self.videoAVAsset && [self.videoAVAsset isKindOfClass:AVURLAsset.class]) {
- AVURLAsset *asset = (AVURLAsset *)self.videoAVAsset;
- NSURL *URL = asset.URL;
- if ([URL.scheme isEqualToString:@"file"]) {
- NSString *path = URL.path;
- if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(path)) {
- UISaveVideoAtPathToSavedPhotosAlbum(path, self, @selector(UISaveVideoAtPathToSavedPhotosAlbum_videoPath:didFinishSavingWithError:contextInfo:), nil);
- } else {
- unableToSave();
- }
- } else if ([URL.scheme containsString:@"http"]) {
- [self downloadWithURL:URL];
- } else {
- unableToSave();
- }
- } else {
- unableToSave();
- }
- }
- #pragma mark - private
- - (void)UISaveVideoAtPathToSavedPhotosAlbum_videoPath:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
- if (error) {
- [self.yb_auxiliaryViewHandler() yb_showIncorrectToastWithContainer:self.yb_containerView text:[YBIBCopywriter sharedCopywriter].saveToPhotoAlbumFailed];
- } else {
- [self.yb_auxiliaryViewHandler() yb_showCorrectToastWithContainer:self.yb_containerView text:[YBIBCopywriter sharedCopywriter].saveToPhotoAlbumSuccess];
- }
- }
- - (void)downloadWithURL:(NSURL *)URL {
- if (self.isDownloading) {
- self.downloading = YES;
- return;
- }
-
- self.downloading = YES;
- NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
- NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
- _downloadTask = [session downloadTaskWithURL:URL];
- [_downloadTask resume];
- }
- #pragma mark - <NSURLSessionDelegate>
- - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
- didWriteData:(int64_t)bytesWritten
- totalBytesWritten:(int64_t)totalBytesWritten
- totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
- CGFloat progress = totalBytesWritten / (double)totalBytesExpectedToWrite;
- if (progress < 0) progress = 0;
- if (progress > 1) progress = 1;
- [self.delegate yb_videoData:self downloadingWithProgress:progress];
- }
- - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
- didCompleteWithError:(nullable NSError *)error {
- if (error) {
- [self.yb_auxiliaryViewHandler() yb_showIncorrectToastWithContainer:self.yb_containerView text:[YBIBCopywriter sharedCopywriter].downloadFailed];
- }
- self.downloading = NO;
- }
- - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
- didFinishDownloadingToURL:(NSURL *)location {
- NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
- NSString *file = [cache stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
- [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:file] error:nil];
- if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(file)) {
- UISaveVideoAtPathToSavedPhotosAlbum(file, self, @selector(UISaveVideoAtPathToSavedPhotosAlbum_videoPath:didFinishSavingWithError:contextInfo:), nil);
- } else {
- [self.yb_auxiliaryViewHandler() yb_showIncorrectToastWithContainer:self.yb_containerView text:[YBIBCopywriter sharedCopywriter].saveToPhotoAlbumFailed];
- }
- self.downloading = NO;
- }
- #pragma mark - getters & setters
- - (void)setVideoURL:(NSURL *)videoURL{
- _videoURL = [videoURL isKindOfClass:NSString.class] ? [NSURL URLWithString:(NSString *)videoURL] : videoURL;
- self.videoAVAsset = [AVURLAsset URLAssetWithURL:_videoURL options:nil];
- }
- - (void)setDownloading:(BOOL)downloading {
- _downloading = downloading;
- if (downloading) {
- [self.delegate yb_videoData:self downloadingWithProgress:0];
- } else {
- [self.delegate yb_finishDownloadingForData:self];
- }
- }
- - (void)setLoadingAVAssetFromPHAsset:(BOOL)loadingAVAssetFromPHAsset {
- _loadingAVAssetFromPHAsset = loadingAVAssetFromPHAsset;
- if (loadingAVAssetFromPHAsset) {
- [self.delegate yb_startLoadingAVAssetFromPHAssetForData:self];
- } else {
- [self.delegate yb_finishLoadingAVAssetFromPHAssetForData:self];
- }
- }
- - (void)setLoadingFirstFrame:(BOOL)loadingFirstFrame {
- _loadingFirstFrame = loadingFirstFrame;
- if (loadingFirstFrame) {
- [self.delegate yb_startLoadingFirstFrameForData:self];
- } else {
- [self.delegate yb_finishLoadingFirstFrameForData:self];
- }
- }
- @synthesize delegate = _delegate;
- - (void)setDelegate:(id<YBIBVideoDataDelegate>)delegate {
- _delegate = delegate;
- if (delegate) {
- [self loadData];
- }
- }
- - (id<YBIBVideoDataDelegate>)delegate {
- // Stop sending data to the '_delegate' if it is transiting.
- return self.yb_isHideTransitioning() ? nil : _delegate;
- }
- @end
|