|
| 1 | +// |
| 2 | +// QNPHAssetFile.m |
| 3 | +// Pods |
| 4 | +// |
| 5 | +// Created by 何舒 on 15/10/21. |
| 6 | +// |
| 7 | +// |
| 8 | + |
| 9 | +#import "QNPHAssetFile.h" |
| 10 | + |
| 11 | +#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000) |
| 12 | +#import <Photos/Photos.h> |
| 13 | +#import <AVFoundation/AVFoundation.h> |
| 14 | +enum { |
| 15 | + kAMASSETMETADATA_PENDINGREADS = 1, |
| 16 | + kAMASSETMETADATA_ALLFINISHED = 0 |
| 17 | +}; |
| 18 | + |
| 19 | +#import "QNResponseInfo.h" |
| 20 | + |
| 21 | +@interface QNPHAssetFile () |
| 22 | +{ |
| 23 | + BOOL _hasGotInfo; |
| 24 | +} |
| 25 | + |
| 26 | +@property (nonatomic) PHAsset * phAsset; |
| 27 | + |
| 28 | +@property (readonly) int64_t fileSize; |
| 29 | + |
| 30 | +@property (readonly) int64_t fileModifyTime; |
| 31 | + |
| 32 | +@property (nonatomic, strong) NSData *assetData; |
| 33 | + |
| 34 | +@property (nonatomic, strong) NSURL *assetURL; |
| 35 | + |
| 36 | +@end |
| 37 | + |
| 38 | +@implementation QNPHAssetFile |
| 39 | + |
| 40 | +- (instancetype)init:(PHAsset *)phAsset error:(NSError *__autoreleasing *)error |
| 41 | +{ |
| 42 | + if (self = [super init]) { |
| 43 | + NSDate *createTime = phAsset.creationDate; |
| 44 | + int64_t t = 0; |
| 45 | + if (createTime != nil) { |
| 46 | + t = [createTime timeIntervalSince1970]; |
| 47 | + } |
| 48 | + _fileModifyTime = t; |
| 49 | + _phAsset = phAsset; |
| 50 | + [self getInfo]; |
| 51 | + |
| 52 | + } |
| 53 | + return self; |
| 54 | +} |
| 55 | + |
| 56 | +- (NSData *)read:(long)offset size:(long)size |
| 57 | +{ |
| 58 | + NSRange subRange = NSMakeRange(offset, size); |
| 59 | + if (!self.assetData) { |
| 60 | + self.assetData = [self fetchDataFromAsset:self.phAsset]; |
| 61 | + } |
| 62 | + NSData *subData = [self.assetData subdataWithRange:subRange]; |
| 63 | + |
| 64 | + return subData; |
| 65 | +} |
| 66 | + |
| 67 | +- (NSData *)readAll { |
| 68 | + return [self read:0 size:(long)_fileSize]; |
| 69 | +} |
| 70 | + |
| 71 | +- (void)close { |
| 72 | +} |
| 73 | + |
| 74 | +-(NSString *)path { |
| 75 | + return self.assetURL.path; |
| 76 | +} |
| 77 | + |
| 78 | +- (int64_t)modifyTime { |
| 79 | + return _fileModifyTime; |
| 80 | +} |
| 81 | + |
| 82 | +- (int64_t)size { |
| 83 | + return _fileSize; |
| 84 | +} |
| 85 | + |
| 86 | +- (void)getInfo |
| 87 | +{ |
| 88 | + if (!_hasGotInfo) { |
| 89 | + _hasGotInfo = YES; |
| 90 | + |
| 91 | + if (PHAssetMediaTypeImage == self.phAsset.mediaType) { |
| 92 | + PHImageRequestOptions *request = [PHImageRequestOptions new]; |
| 93 | + request.version = PHImageRequestOptionsVersionCurrent; |
| 94 | + request.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; |
| 95 | + request.resizeMode = PHImageRequestOptionsResizeModeNone; |
| 96 | + request.synchronous = YES; |
| 97 | + |
| 98 | + [[PHImageManager defaultManager] requestImageDataForAsset:self.phAsset |
| 99 | + options:request |
| 100 | + resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { |
| 101 | + _fileSize = imageData.length; |
| 102 | + _assetURL = [NSURL URLWithString:self.phAsset.localIdentifier]; |
| 103 | + } |
| 104 | + ]; |
| 105 | + } |
| 106 | + else if (PHAssetMediaTypeVideo == self.phAsset.mediaType) { |
| 107 | + PHVideoRequestOptions *request = [PHVideoRequestOptions new]; |
| 108 | + request.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic; |
| 109 | + request.version = PHVideoRequestOptionsVersionCurrent; |
| 110 | + |
| 111 | + NSConditionLock* assetReadLock = [[NSConditionLock alloc] initWithCondition:kAMASSETMETADATA_PENDINGREADS]; |
| 112 | + [[PHImageManager defaultManager] requestPlayerItemForVideo:self.phAsset options:request resultHandler:^(AVPlayerItem *playerItem, NSDictionary *info) { |
| 113 | + AVURLAsset *urlAsset = (AVURLAsset *)playerItem.asset; |
| 114 | + NSNumber *fileSize = nil; |
| 115 | + [urlAsset.URL getResourceValue:&fileSize forKey:NSURLFileSizeKey error:nil]; |
| 116 | + _fileSize = [fileSize unsignedLongLongValue]; |
| 117 | + _assetURL = urlAsset.URL; |
| 118 | + |
| 119 | + [assetReadLock lock]; |
| 120 | + [assetReadLock unlockWithCondition:kAMASSETMETADATA_ALLFINISHED]; |
| 121 | + }]; |
| 122 | + [assetReadLock lockWhenCondition:kAMASSETMETADATA_ALLFINISHED]; |
| 123 | + [assetReadLock unlock]; |
| 124 | + assetReadLock = nil; |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | +} |
| 129 | + |
| 130 | +- (NSData *)fetchDataFromAsset:(PHAsset *)asset |
| 131 | +{ |
| 132 | + __block NSData *tmpData = [NSData data]; |
| 133 | + |
| 134 | + // Image |
| 135 | + if (asset.mediaType == PHAssetMediaTypeImage) { |
| 136 | + PHImageRequestOptions *request = [PHImageRequestOptions new]; |
| 137 | + request.version = PHImageRequestOptionsVersionCurrent; |
| 138 | + request.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; |
| 139 | + request.resizeMode = PHImageRequestOptionsResizeModeNone; |
| 140 | + request.synchronous = YES; |
| 141 | + |
| 142 | + [[PHImageManager defaultManager] requestImageDataForAsset:asset |
| 143 | + options:request |
| 144 | + resultHandler: |
| 145 | + ^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) { |
| 146 | + tmpData = [NSData dataWithData:imageData]; |
| 147 | + }]; |
| 148 | + } |
| 149 | + // Video |
| 150 | + else { |
| 151 | + |
| 152 | + PHVideoRequestOptions *request = [PHVideoRequestOptions new]; |
| 153 | + request.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic; |
| 154 | + request.version = PHVideoRequestOptionsVersionCurrent; |
| 155 | + |
| 156 | + NSConditionLock *assetReadLock = [[NSConditionLock alloc] initWithCondition:kAMASSETMETADATA_PENDINGREADS]; |
| 157 | + |
| 158 | + |
| 159 | + [[PHImageManager defaultManager] requestAVAssetForVideo:asset |
| 160 | + options:request |
| 161 | + resultHandler: |
| 162 | + ^(AVAsset* asset, AVAudioMix* audioMix, NSDictionary* info) { |
| 163 | + AVURLAsset *urlAsset = (AVURLAsset *)asset; |
| 164 | + NSData *videoData = [NSData dataWithContentsOfURL:urlAsset.URL]; |
| 165 | + tmpData = [NSData dataWithData:videoData]; |
| 166 | + |
| 167 | + [assetReadLock lock]; |
| 168 | + [assetReadLock unlockWithCondition:kAMASSETMETADATA_ALLFINISHED]; |
| 169 | + }]; |
| 170 | + |
| 171 | + [assetReadLock lockWhenCondition:kAMASSETMETADATA_ALLFINISHED]; |
| 172 | + [assetReadLock unlock]; |
| 173 | + assetReadLock = nil; |
| 174 | + } |
| 175 | + |
| 176 | + return tmpData; |
| 177 | +} |
| 178 | + |
| 179 | +@end |
| 180 | +#endif |
0 commit comments