326 lines
8.8 KiB
Objective-C
326 lines
8.8 KiB
Objective-C
|
|
|
|
// Created by AI on 2025/1/20.
|
|
|
|
|
|
#import "MedalMediaDisplayManager.h"
|
|
#import <QGVAPWrapView.h>
|
|
#import "XPRoomGiftAnimationParser.h"
|
|
#import "NSString+XPExtension.h"
|
|
#import "UIImageConstant.h"
|
|
|
|
@interface MedalMediaDisplayManager () <HWDMP4PlayDelegate>
|
|
|
|
@property (nonatomic, copy, readwrite, nullable) NSString *currentImagePath;
|
|
@property (nonatomic, copy, readwrite, nullable) NSString *currentMP4Path;
|
|
@property (nonatomic, strong) XPRoomGiftAnimationParser *mp4Parser;
|
|
@property (nonatomic, assign) NSInteger mp4PlaybackTag;
|
|
|
|
@end
|
|
|
|
@implementation MedalMediaDisplayManager
|
|
|
|
#pragma mark - 初始化
|
|
|
|
- (instancetype)initWithDelegate:(id<MedalMediaDisplayDelegate>)delegate {
|
|
self = [super init];
|
|
if (self) {
|
|
_delegate = delegate;
|
|
_isVisible = YES;
|
|
_mp4PlaybackTag = 0;
|
|
[self setupNotifications];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[self cleanupResources];
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
NSLog(@"MedalMediaDisplayManager dealloc");
|
|
}
|
|
|
|
#pragma mark - 公共接口
|
|
|
|
- (void)updateDisplayWithModel:(id)model {
|
|
self.currentModel = model;
|
|
[self handleMediaDisplayWithModel:model];
|
|
}
|
|
|
|
- (void)willDisplay {
|
|
self.isVisible = YES;
|
|
[self resumeMP4PlaybackIfNeeded];
|
|
}
|
|
|
|
- (void)didEndDisplaying {
|
|
self.isVisible = NO;
|
|
[self pauseMP4Playback];
|
|
}
|
|
|
|
- (void)stopMP4Playback {
|
|
VAPView *mp4View = [self.delegate getMP4View];
|
|
if (mp4View) {
|
|
[mp4View stopHWDMP4];
|
|
self.mp4PlaybackTag = 0;
|
|
}
|
|
}
|
|
|
|
- (void)pauseMP4Playback {
|
|
VAPView *mp4View = [self.delegate getMP4View];
|
|
if (mp4View && !mp4View.hidden) {
|
|
[mp4View pauseHWDMP4];
|
|
}
|
|
}
|
|
|
|
- (void)resumeMP4Playback {
|
|
[self resumeMP4PlaybackIfNeeded];
|
|
}
|
|
|
|
- (void)cleanupResources {
|
|
[self stopMP4Playback];
|
|
self.mp4Parser = nil;
|
|
self.currentImagePath = nil;
|
|
self.currentMP4Path = nil;
|
|
self.currentModel = nil;
|
|
}
|
|
|
|
#pragma mark - 核心媒体处理逻辑
|
|
|
|
- (void)handleMediaDisplayWithModel:(id)model {
|
|
if (!model || !self.delegate) {
|
|
[self showDefaultPlaceholder];
|
|
return;
|
|
}
|
|
|
|
NSString *mp4Url = [self.delegate getMP4UrlFromModel:model];
|
|
NSString *picUrl = [self.delegate getPicUrlFromModel:model];
|
|
|
|
|
|
if (![NSString isEmpty:mp4Url] && [self isValidMP4URL:mp4Url]) {
|
|
[self setMp4Path:mp4Url];
|
|
return;
|
|
}
|
|
|
|
|
|
if (![NSString isEmpty:picUrl]) {
|
|
if ([self isValidMP4URL:picUrl]) {
|
|
|
|
[self setMp4Path:picUrl];
|
|
return;
|
|
} else if ([NSString isValidImageURL:picUrl]) {
|
|
|
|
[self setImagePath:picUrl];
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
[self showDefaultPlaceholder];
|
|
}
|
|
|
|
- (void)setImagePath:(NSString *)imagePath {
|
|
[self stopMP4Playback];
|
|
|
|
self.currentImagePath = imagePath;
|
|
self.currentMP4Path = nil;
|
|
|
|
VAPView *mp4View = [self.delegate getMP4View];
|
|
NetImageView *imageView = [self.delegate getImageView];
|
|
|
|
mp4View.hidden = YES;
|
|
imageView.hidden = NO;
|
|
imageView.imageUrl = imagePath ?: @"";
|
|
|
|
[self notifyDisplayUpdated:NO success:![NSString isEmpty:imagePath]];
|
|
}
|
|
|
|
- (void)setMp4Path:(NSString *)mp4Path {
|
|
if ([NSString isEmpty:mp4Path]) {
|
|
[self showDefaultPlaceholder];
|
|
return;
|
|
}
|
|
|
|
[self stopMP4Playback];
|
|
|
|
self.currentMP4Path = mp4Path;
|
|
self.currentImagePath = nil;
|
|
|
|
VAPView *mp4View = [self.delegate getMP4View];
|
|
NetImageView *imageView = [self.delegate getImageView];
|
|
|
|
mp4View.hidden = NO;
|
|
imageView.hidden = YES;
|
|
|
|
if (!self.mp4Parser) {
|
|
self.mp4Parser = [[XPRoomGiftAnimationParser alloc] init];
|
|
}
|
|
|
|
@kWeakify(self);
|
|
[self.mp4Parser parseWithURL:mp4Path
|
|
completionBlock:^(NSString * _Nullable videoUrl) {
|
|
@kStrongify(self);
|
|
if (![NSString isEmpty:videoUrl]) {
|
|
self.mp4PlaybackTag = 1;
|
|
|
|
if (self.isVisible) {
|
|
[self startMP4PlaybackWithURL:videoUrl];
|
|
}
|
|
}
|
|
} failureBlock:^(NSError * _Nullable error) {
|
|
@kStrongify(self);
|
|
NSLog(@"[MedalMediaDisplayManager] Failed to parse mp4: %@", error);
|
|
[self handleMP4FailureWithFallback];
|
|
}];
|
|
}
|
|
|
|
- (void)startMP4PlaybackWithURL:(NSString *)videoUrl {
|
|
if ([NSString isEmpty:videoUrl] || !self.delegate) {
|
|
return;
|
|
}
|
|
|
|
VAPView *mp4View = [self.delegate getMP4View];
|
|
if (mp4View && !mp4View.hidden) {
|
|
[mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:self];
|
|
[self notifyDisplayUpdated:YES success:YES];
|
|
NSLog(@"[MedalMediaDisplayManager] Started MP4 playback: %@", videoUrl);
|
|
}
|
|
}
|
|
|
|
- (void)handleMP4FailureWithFallback {
|
|
if (!self.delegate || !self.currentModel) {
|
|
[self showDefaultPlaceholder];
|
|
return;
|
|
}
|
|
|
|
|
|
NSString *picUrl = [self.delegate getPicUrlFromModel:self.currentModel];
|
|
if (![NSString isEmpty:picUrl] && [NSString isValidImageURL:picUrl]) {
|
|
[self setImagePath:picUrl];
|
|
} else {
|
|
[self showDefaultPlaceholder];
|
|
}
|
|
}
|
|
|
|
- (void)showDefaultPlaceholder {
|
|
[self stopMP4Playback];
|
|
|
|
VAPView *mp4View = [self.delegate getMP4View];
|
|
NetImageView *imageView = [self.delegate getImageView];
|
|
|
|
mp4View.hidden = YES;
|
|
imageView.hidden = NO;
|
|
imageView.imageUrl = @"";
|
|
|
|
|
|
UIImage *placeholderImage = nil;
|
|
if ([self.delegate respondsToSelector:@selector(getDefaultPlaceholderImage)]) {
|
|
placeholderImage = [self.delegate getDefaultPlaceholderImage];
|
|
}
|
|
if (!placeholderImage) {
|
|
placeholderImage = [UIImageConstant defaultEmptyPlaceholder];
|
|
}
|
|
imageView.image = placeholderImage;
|
|
|
|
[self notifyDisplayUpdated:NO success:NO];
|
|
}
|
|
|
|
- (void)resumeMP4PlaybackIfNeeded {
|
|
if (!self.isVisible || [NSString isEmpty:self.currentMP4Path]) {
|
|
return;
|
|
}
|
|
|
|
VAPView *mp4View = [self.delegate getMP4View];
|
|
if (mp4View && !mp4View.hidden) {
|
|
if (self.mp4PlaybackTag == 1) {
|
|
|
|
@kWeakify(self);
|
|
[self.mp4Parser parseWithURL:self.currentMP4Path
|
|
completionBlock:^(NSString * _Nullable videoUrl) {
|
|
@kStrongify(self);
|
|
if (![NSString isEmpty:videoUrl] && self.isVisible) {
|
|
[self startMP4PlaybackWithURL:videoUrl];
|
|
}
|
|
} failureBlock:^(NSError * _Nullable error) {
|
|
@kStrongify(self);
|
|
[self handleMP4FailureWithFallback];
|
|
}];
|
|
} else {
|
|
|
|
[mp4View resumeHWDMP4];
|
|
}
|
|
}
|
|
}
|
|
|
|
#pragma mark - 辅助方法
|
|
|
|
- (BOOL)isValidMP4URL:(NSString *)url {
|
|
if ([NSString isEmpty:url]) {
|
|
return NO;
|
|
}
|
|
|
|
NSString *lowercaseUrl = [url lowercaseString];
|
|
return [lowercaseUrl hasSuffix:@".mp4"] ||
|
|
[lowercaseUrl containsString:@"mp4"] ||
|
|
[lowercaseUrl containsString:@"video"];
|
|
}
|
|
|
|
- (void)notifyDisplayUpdated:(BOOL)isMP4 success:(BOOL)success {
|
|
if ([self.delegate respondsToSelector:@selector(onMediaDisplayUpdated:success:)]) {
|
|
[self.delegate onMediaDisplayUpdated:isMP4 success:success];
|
|
}
|
|
}
|
|
|
|
#pragma mark - 通知处理
|
|
|
|
- (void)setupNotifications {
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleAppDidEnterBackground)
|
|
name:UIApplicationDidEnterBackgroundNotification
|
|
object:nil];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleAppWillEnterForeground)
|
|
name:UIApplicationWillEnterForegroundNotification
|
|
object:nil];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleMemoryWarning)
|
|
name:UIApplicationDidReceiveMemoryWarningNotification
|
|
object:nil];
|
|
}
|
|
|
|
- (void)handleAppDidEnterBackground {
|
|
[self pauseMP4Playback];
|
|
}
|
|
|
|
- (void)handleAppWillEnterForeground {
|
|
if (self.isVisible) {
|
|
[self resumeMP4PlaybackIfNeeded];
|
|
}
|
|
}
|
|
|
|
- (void)handleMemoryWarning {
|
|
if (!self.isVisible) {
|
|
[self stopMP4Playback];
|
|
}
|
|
}
|
|
|
|
#pragma mark - HWDMP4PlayDelegate
|
|
|
|
- (BOOL)shouldStartPlayMP4:(VAPView *)container config:(QGVAPConfigModel *)config {
|
|
return YES;
|
|
}
|
|
|
|
- (void)viewDidFinishPlayMP4:(NSInteger)totalFrameCount view:(VAPView *)container {
|
|
|
|
}
|
|
|
|
- (void)viewDidStopPlayMP4:(NSInteger)lastFrameIndex view:(VAPView *)container {
|
|
|
|
}
|
|
|
|
- (void)viewDidFailPlayMP4:(NSError *)error {
|
|
NSLog(@"[MedalMediaDisplayManager] MP4 播放失败: %@", error);
|
|
[self handleMP4FailureWithFallback];
|
|
}
|
|
|
|
@end |