SellyCloudSDK_demo/Example/SellyCloudSDK/VideoCall/SLSVideoTileView.m

195 lines
6.7 KiB
Objective-C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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