SVGAVideoEntity.m 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. //
  2. // SVGAVideoEntity.m
  3. // SVGAPlayer
  4. //
  5. // Created by 崔明辉 on 16/6/17.
  6. // Copyright © 2016年 UED Center. All rights reserved.
  7. //
  8. #import <AVFoundation/AVFoundation.h>
  9. #import "SVGAVideoEntity.h"
  10. #import "SVGABezierPath.h"
  11. #import "SVGAVideoSpriteEntity.h"
  12. #import "SVGAAudioEntity.h"
  13. #import "Svga.pbobjc.h"
  14. #define MP3_MAGIC_NUMBER "ID3"
  15. @interface SVGAVideoEntity ()
  16. @property (nonatomic, assign) CGSize videoSize;
  17. @property (nonatomic, assign) int FPS;
  18. @property (nonatomic, assign) int frames;
  19. @property (nonatomic, copy) NSDictionary<NSString *, UIImage *> *images;
  20. @property (nonatomic, copy) NSDictionary<NSString *, NSData *> *audiosData;
  21. @property (nonatomic, copy) NSArray<SVGAVideoSpriteEntity *> *sprites;
  22. @property (nonatomic, copy) NSArray<SVGAAudioEntity *> *audios;
  23. @property (nonatomic, copy) NSString *cacheDir;
  24. @end
  25. @implementation SVGAVideoEntity
  26. static NSCache *videoCache;
  27. + (void)load {
  28. static dispatch_once_t onceToken;
  29. dispatch_once(&onceToken, ^{
  30. videoCache = [[NSCache alloc] init];
  31. });
  32. }
  33. - (instancetype)initWithJSONObject:(NSDictionary *)JSONObject cacheDir:(NSString *)cacheDir {
  34. self = [super init];
  35. if (self) {
  36. _videoSize = CGSizeMake(100, 100);
  37. _FPS = 20;
  38. _images = @{};
  39. _cacheDir = cacheDir;
  40. [self resetMovieWithJSONObject:JSONObject];
  41. }
  42. return self;
  43. }
  44. - (void)resetMovieWithJSONObject:(NSDictionary *)JSONObject {
  45. if ([JSONObject isKindOfClass:[NSDictionary class]]) {
  46. NSDictionary *movieObject = JSONObject[@"movie"];
  47. if ([movieObject isKindOfClass:[NSDictionary class]]) {
  48. NSDictionary *viewBox = movieObject[@"viewBox"];
  49. if ([viewBox isKindOfClass:[NSDictionary class]]) {
  50. NSNumber *width = viewBox[@"width"];
  51. NSNumber *height = viewBox[@"height"];
  52. if ([width isKindOfClass:[NSNumber class]] && [height isKindOfClass:[NSNumber class]]) {
  53. _videoSize = CGSizeMake(width.floatValue, height.floatValue);
  54. }
  55. }
  56. NSNumber *FPS = movieObject[@"fps"];
  57. if ([FPS isKindOfClass:[NSNumber class]]) {
  58. _FPS = [FPS intValue];
  59. }
  60. NSNumber *frames = movieObject[@"frames"];
  61. if ([frames isKindOfClass:[NSNumber class]]) {
  62. _frames = [frames intValue];
  63. }
  64. }
  65. }
  66. }
  67. - (void)resetImagesWithJSONObject:(NSDictionary *)JSONObject {
  68. if ([JSONObject isKindOfClass:[NSDictionary class]]) {
  69. NSMutableDictionary<NSString *, UIImage *> *images = [[NSMutableDictionary alloc] init];
  70. NSDictionary<NSString *, NSString *> *JSONImages = JSONObject[@"images"];
  71. if ([JSONImages isKindOfClass:[NSDictionary class]]) {
  72. [JSONImages enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
  73. if ([obj isKindOfClass:[NSString class]]) {
  74. NSString *filePath = [self.cacheDir stringByAppendingFormat:@"/%@.png", obj];
  75. NSData *imageData = [NSData dataWithContentsOfFile:filePath];
  76. if (imageData != nil) {
  77. UIImage *image = [[UIImage alloc] initWithData:imageData scale:2.0];
  78. if (image != nil) {
  79. [images setObject:image forKey:[key stringByDeletingPathExtension]];
  80. }
  81. }
  82. }
  83. }];
  84. }
  85. self.images = images;
  86. }
  87. }
  88. - (void)resetSpritesWithJSONObject:(NSDictionary *)JSONObject {
  89. if ([JSONObject isKindOfClass:[NSDictionary class]]) {
  90. NSMutableArray<SVGAVideoSpriteEntity *> *sprites = [[NSMutableArray alloc] init];
  91. NSArray<NSDictionary *> *JSONSprites = JSONObject[@"sprites"];
  92. if ([JSONSprites isKindOfClass:[NSArray class]]) {
  93. [JSONSprites enumerateObjectsUsingBlock:^(NSDictionary * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  94. if ([obj isKindOfClass:[NSDictionary class]]) {
  95. SVGAVideoSpriteEntity *spriteItem = [[SVGAVideoSpriteEntity alloc] initWithJSONObject:obj];
  96. [sprites addObject:spriteItem];
  97. }
  98. }];
  99. }
  100. self.sprites = sprites;
  101. }
  102. }
  103. - (instancetype)initWithProtoObject:(SVGAProtoMovieEntity *)protoObject cacheDir:(NSString *)cacheDir {
  104. self = [super init];
  105. if (self) {
  106. _videoSize = CGSizeMake(100, 100);
  107. _FPS = 20;
  108. _images = @{};
  109. _cacheDir = cacheDir;
  110. [self resetMovieWithProtoObject:protoObject];
  111. }
  112. return self;
  113. }
  114. - (void)resetMovieWithProtoObject:(SVGAProtoMovieEntity *)protoObject {
  115. if (protoObject.hasParams) {
  116. self.videoSize = CGSizeMake((CGFloat)protoObject.params.viewBoxWidth, (CGFloat)protoObject.params.viewBoxHeight);
  117. self.FPS = (int)protoObject.params.fps;
  118. self.frames = (int)protoObject.params.frames;
  119. }
  120. }
  121. + (BOOL)isMP3Data:(NSData *)data {
  122. BOOL result = NO;
  123. if (!strncmp([data bytes], MP3_MAGIC_NUMBER, strlen(MP3_MAGIC_NUMBER))) {
  124. result = YES;
  125. }
  126. return result;
  127. }
  128. - (void)resetImagesWithProtoObject:(SVGAProtoMovieEntity *)protoObject {
  129. NSMutableDictionary<NSString *, UIImage *> *images = [[NSMutableDictionary alloc] init];
  130. NSMutableDictionary<NSString *, NSData *> *audiosData = [[NSMutableDictionary alloc] init];
  131. NSDictionary *protoImages = [protoObject.images copy];
  132. for (NSString *key in protoImages) {
  133. NSString *fileName = [[NSString alloc] initWithData:protoImages[key] encoding:NSUTF8StringEncoding];
  134. if (fileName != nil) {
  135. NSString *filePath = [self.cacheDir stringByAppendingFormat:@"/%@.png", fileName];
  136. if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
  137. filePath = [self.cacheDir stringByAppendingFormat:@"/%@", fileName];
  138. }
  139. if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
  140. NSData *imageData = [NSData dataWithContentsOfFile:filePath];
  141. if (imageData != nil) {
  142. UIImage *image = [[UIImage alloc] initWithData:imageData scale:2.0];
  143. if (image != nil) {
  144. [images setObject:image forKey:key];
  145. }
  146. }
  147. }
  148. }
  149. else if ([protoImages[key] isKindOfClass:[NSData class]]) {
  150. if ([SVGAVideoEntity isMP3Data:protoImages[key]]) {
  151. // mp3
  152. [audiosData setObject:protoImages[key] forKey:key];
  153. } else {
  154. UIImage *image = [[UIImage alloc] initWithData:protoImages[key] scale:2.0];
  155. if (image != nil) {
  156. [images setObject:image forKey:key];
  157. }
  158. }
  159. }
  160. }
  161. self.images = images;
  162. self.audiosData = audiosData;
  163. }
  164. - (void)resetSpritesWithProtoObject:(SVGAProtoMovieEntity *)protoObject {
  165. NSMutableArray<SVGAVideoSpriteEntity *> *sprites = [[NSMutableArray alloc] init];
  166. NSArray *protoSprites = [protoObject.spritesArray copy];
  167. [protoSprites enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  168. if ([obj isKindOfClass:[SVGAProtoSpriteEntity class]]) {
  169. SVGAVideoSpriteEntity *spriteItem = [[SVGAVideoSpriteEntity alloc] initWithProtoObject:obj];
  170. [sprites addObject:spriteItem];
  171. }
  172. }];
  173. self.sprites = sprites;
  174. }
  175. - (void)resetAudiosWithProtoObject:(SVGAProtoMovieEntity *)protoObject {
  176. NSMutableArray<SVGAAudioEntity *> *audios = [[NSMutableArray alloc] init];
  177. NSArray *protoAudios = [protoObject.audiosArray copy];
  178. [protoAudios enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  179. if ([obj isKindOfClass:[SVGAProtoAudioEntity class]]) {
  180. SVGAAudioEntity *audioItem = [[SVGAAudioEntity alloc] initWithProtoObject:obj];
  181. [audios addObject:audioItem];
  182. }
  183. }];
  184. self.audios = audios;
  185. }
  186. + (SVGAVideoEntity *)readCache:(NSString *)cacheKey {
  187. return [videoCache objectForKey:cacheKey];
  188. }
  189. - (void)saveCache:(NSString *)cacheKey {
  190. [videoCache setObject:self forKey:cacheKey];
  191. }
  192. @end
  193. @interface SVGAVideoSpriteEntity()
  194. @property (nonatomic, copy) NSString *imageKey;
  195. @property (nonatomic, copy) NSArray<SVGAVideoSpriteFrameEntity *> *frames;
  196. @property (nonatomic, copy) NSString *matteKey;
  197. @end