195 lines
6.7 KiB
Objective-C
195 lines
6.7 KiB
Objective-C
//
|
||
// SLSVideoTileView.m
|
||
// SellyCloudSDK_Example
|
||
//
|
||
// Created by Caleb on 13/11/25.
|
||
// Copyright © 2025 Caleb. All rights reserved.
|
||
//
|
||
|
||
#import "SLSVideoTileView.h"
|
||
|
||
@interface SLSVideoTileView ()
|
||
@property (nonatomic, strong)NSString *userId;
|
||
|
||
@property (nonatomic, strong) UIView *contentViewInternal;
|
||
@property (nonatomic, strong) UILabel *nameLabel;
|
||
@property (nonatomic, strong) UIImageView *muteIcon;
|
||
@property (nonatomic, strong) UIView *videoMaskView;
|
||
@property (nonatomic, strong) UILabel *videoOffLabel;
|
||
@property (nonatomic, strong) UILabel *bitrate;
|
||
@property (nonatomic, strong) UILabel *fps;
|
||
@property (nonatomic, strong) UILabel *codec;
|
||
@property (nonatomic, strong) UILabel *rtt;
|
||
@end
|
||
|
||
@implementation SLSVideoTileView
|
||
|
||
- (instancetype)initWithFrame:(CGRect)frame {
|
||
if (self = [super initWithFrame:frame]) {
|
||
self.layer.cornerRadius = 10.f;
|
||
self.clipsToBounds = YES;
|
||
self.backgroundColor = [UIColor blackColor];
|
||
|
||
_contentViewInternal = [[UIView alloc] initWithFrame:self.bounds];
|
||
_contentViewInternal.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||
_contentViewInternal.backgroundColor = [UIColor blackColor];
|
||
[self addSubview:_contentViewInternal];
|
||
|
||
_videoMaskView = [[UIView alloc] initWithFrame:self.bounds];
|
||
_videoMaskView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||
_videoMaskView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
|
||
_videoMaskView.hidden = YES;
|
||
[self addSubview:_videoMaskView];
|
||
|
||
_videoOffLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||
_videoOffLabel.textAlignment = NSTextAlignmentCenter;
|
||
_videoOffLabel.textColor = [UIColor lightGrayColor];
|
||
_videoOffLabel.font = [UIFont systemFontOfSize:14];
|
||
_videoOffLabel.text = @"视频已关闭";
|
||
[_videoMaskView addSubview:_videoOffLabel];
|
||
|
||
_nameLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
||
_nameLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightMedium];
|
||
_nameLabel.textColor = [UIColor whiteColor];
|
||
_nameLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.4];
|
||
_nameLabel.layer.cornerRadius = 8;
|
||
_nameLabel.clipsToBounds = YES;
|
||
[self addSubview:_nameLabel];
|
||
|
||
_muteIcon = [[UIImageView alloc] initWithImage:[UIImage systemImageNamed:@"mic.slash.fill"]];
|
||
_muteIcon.tintColor = [UIColor systemRedColor];
|
||
[self addSubview:_muteIcon];
|
||
|
||
[self addSubview:self.bitrate];
|
||
[self addSubview:self.fps];
|
||
[self addSubview:self.codec];
|
||
[self addSubview:self.rtt];
|
||
|
||
[self.bitrate mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.left.top.offset(10);
|
||
}];
|
||
|
||
[self.fps mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.top.equalTo(self.bitrate.mas_bottom).offset(10);
|
||
make.left.offset(10);
|
||
}];
|
||
|
||
[self.codec mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.top.equalTo(self.fps.mas_bottom).offset(10);
|
||
make.left.offset(10);
|
||
}];
|
||
|
||
[self.rtt mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.top.equalTo(self.codec.mas_bottom).offset(10);
|
||
make.left.offset(10);
|
||
}];
|
||
}
|
||
return self;
|
||
}
|
||
|
||
- (UIView *)contentView {
|
||
return self.contentViewInternal;
|
||
}
|
||
|
||
- (void)layoutSubviews {
|
||
[super layoutSubviews];
|
||
self.contentViewInternal.frame = self.bounds;
|
||
self.videoMaskView.frame = self.bounds;
|
||
self.videoOffLabel.frame = CGRectInset(self.videoMaskView.bounds, 8, 8);
|
||
|
||
CGFloat padding = 6.f;
|
||
CGSize maxSize = CGSizeMake(self.bounds.size.width - 2*padding, 20);
|
||
CGSize nameSize = [self.nameLabel sizeThatFits:maxSize];
|
||
self.nameLabel.frame = CGRectMake(padding,
|
||
self.bounds.size.height - nameSize.height - padding,
|
||
nameSize.width + 12,
|
||
nameSize.height);
|
||
|
||
self.muteIcon.frame = CGRectMake(CGRectGetMaxX(self.nameLabel.frame) + 4,
|
||
CGRectGetMinY(self.nameLabel.frame) - 2,
|
||
18,
|
||
18);
|
||
}
|
||
|
||
- (void)updateWithParticipant:(SLSParticipant *)p {
|
||
self.userId = p.uid;
|
||
// 昵称
|
||
self.nameLabel.text = p.displayName.length ? p.displayName : p.uid;
|
||
|
||
// 音频静音图标
|
||
self.muteIcon.hidden = !p.audioMuted;
|
||
|
||
// 视频开关:只用遮罩层控制,不移除 contentView 里的子视图
|
||
BOOL videoOn = !p.videoMuted;
|
||
self.videoMaskView.hidden = videoOn;
|
||
|
||
// 说话者高亮
|
||
if (p.level > 0.25 && !p.audioMuted) {
|
||
self.layer.borderWidth = 2.f;
|
||
self.layer.borderColor = [UIColor systemGreenColor].CGColor;
|
||
} else {
|
||
self.layer.borderWidth = 0.f;
|
||
self.layer.borderColor = nil;
|
||
}
|
||
|
||
[self setNeedsLayout];
|
||
}
|
||
|
||
- (void)setStats:(SellyRTCP2pStats *)stats {
|
||
_stats = stats;
|
||
|
||
|
||
self.rtt.text = [NSString stringWithFormat:@" rtt:%ldms ",(NSInteger)stats.transportRttMs];
|
||
self.codec.text = [NSString stringWithFormat:@" %@/%@ ",stats.videoCodec,stats.audioCodec];
|
||
if ([self.userId isEqualToString:SellyRTCEngine.sharedEngine.userId]) {
|
||
self.bitrate.text = [NSString stringWithFormat:@" 码率:%ld kbps ",(NSInteger)(stats.txKbps)];
|
||
self.fps.text = [NSString stringWithFormat:@" 视频:%ld fps %ldx%ld ",(NSInteger)(stats.sentFps),(NSInteger)(stats.sentWidth),(NSInteger)(stats.sentHeight)];
|
||
|
||
}
|
||
else {
|
||
self.bitrate.text = [NSString stringWithFormat:@" 码率:%ld kbps ",(NSInteger)(stats.rxKbps)];
|
||
self.fps.text = [NSString stringWithFormat:@" 视频:%ld fps %ldx%ld ",(NSInteger)(stats.recvFps),(NSInteger)(stats.recvWidth),(NSInteger)(stats.recvHeight)];
|
||
}
|
||
}
|
||
|
||
- (UILabel *)bitrate {
|
||
if (!_bitrate) {
|
||
_bitrate = [self createStatsLabel];
|
||
}
|
||
return _bitrate;
|
||
}
|
||
|
||
- (UILabel *)fps {
|
||
if (!_fps) {
|
||
_fps = [self createStatsLabel];
|
||
}
|
||
return _fps;
|
||
}
|
||
|
||
- (UILabel *)codec {
|
||
if (!_codec) {
|
||
_codec = [self createStatsLabel];
|
||
}
|
||
return _codec;
|
||
}
|
||
|
||
- (UILabel *)rtt {
|
||
if (!_rtt) {
|
||
_rtt = [self createStatsLabel];
|
||
}
|
||
return _rtt;
|
||
}
|
||
|
||
- (UILabel *)createStatsLabel {
|
||
UILabel *label = [[UILabel alloc] init];
|
||
label.font = [UIFont systemFontOfSize:12];
|
||
label.textColor = [UIColor whiteColor];
|
||
label.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2];
|
||
label.textAlignment = NSTextAlignmentLeft;
|
||
label.layer.cornerRadius = 4;
|
||
label.layer.masksToBounds = YES;
|
||
return label;
|
||
}
|
||
|
||
@end
|