diff --git a/ios/Classes/AgoraTextureViewFactory.h b/ios/Classes/AgoraTextureViewFactory.h deleted file mode 100644 index 4539add7a..000000000 --- a/ios/Classes/AgoraTextureViewFactory.h +++ /dev/null @@ -1,14 +0,0 @@ -//#ifndef AgoraTextureViewFactory_h -//#define AgoraTextureViewFactory_h -// -//#import -// -//@interface AgoraTextureViewFactory : NSObject -//- (instancetype)initWithRegistrar:(NSObject *)registrar; -// -//- (int64_t)createTextureRenderer:(void *)renderer; -// -//- (BOOL)destroyTextureRenderer:(int64_t)textureId; -//@end -// -//#endif /* AgoraTextureViewFactory_h */ diff --git a/ios/Classes/AgoraTextureViewFactory.mm b/ios/Classes/AgoraTextureViewFactory.mm deleted file mode 100644 index 99740bf9d..000000000 --- a/ios/Classes/AgoraTextureViewFactory.mm +++ /dev/null @@ -1,191 +0,0 @@ -//#import "AgoraTextureViewFactory.h" -//#import -//#import -//#import -// -//using namespace agora::iris; -//using namespace agora::iris::rtc; -// -//@interface TextureRenderer : NSObject -//@property(nonatomic, weak) NSObject *textureRegistry; -//@property(nonatomic, assign) int64_t textureId; -//@property(nonatomic, strong) FlutterMethodChannel *channel; -//@property(nonatomic) CVPixelBufferRef buffer_cache; -//@property(nonatomic) CVPixelBufferRef buffer_temp; -//@property(nonatomic) IrisVideoFrameBufferManager *renderer; -//@property(nonatomic, strong) dispatch_semaphore_t lock; -// -//- (instancetype) -// initWithTextureRegistry:(NSObject *)textureRegistry -// messenger:(NSObject *)messenger -// renderer:(IrisVideoFrameBufferManager *)renderer; -// -//- (void)destroy; -//@end -// -//namespace { -//class RendererDelegate : public IrisVideoFrameBufferDelegate { -//public: -// RendererDelegate(void *renderer) : renderer_(renderer) {} -// -// void OnVideoFrameReceived(const IrisVideoFrame &video_frame, -// const IrisVideoFrameBufferConfig *config, -// bool resize) override { -// @autoreleasepool { -// TextureRenderer *renderer = (__bridge TextureRenderer *)renderer_; -// CVPixelBufferRef buffer = NULL; -// NSDictionary *dic = [NSDictionary -// dictionaryWithObjectsAndKeys: -// @(YES), kCVPixelBufferCGBitmapContextCompatibilityKey, @(YES), -// kCVPixelBufferCGImageCompatibilityKey, @(YES), -// kCVPixelBufferOpenGLCompatibilityKey, @(YES), -// kCVPixelBufferMetalCompatibilityKey, nil]; -// CVPixelBufferCreate(kCFAllocatorDefault, video_frame.width, -// video_frame.height, kCVPixelFormatType_32BGRA, -// (__bridge CFDictionaryRef)dic, &buffer); -// -// CVPixelBufferLockBaseAddress(buffer, 0); -// void *copyBaseAddress = CVPixelBufferGetBaseAddress(buffer); -// memcpy(copyBaseAddress, video_frame.y_buffer, -// video_frame.y_buffer_length); -// CVPixelBufferUnlockBaseAddress(buffer, 0); -// -// dispatch_semaphore_wait(renderer.lock, DISPATCH_TIME_FOREVER); -// if (renderer.buffer_cache) { -// CVPixelBufferRelease(renderer.buffer_cache); -// } -// renderer.buffer_cache = buffer; -// dispatch_semaphore_signal(renderer.lock); -// -// [renderer.textureRegistry textureFrameAvailable:renderer.textureId]; -// } -// } -// -//public: -// void *renderer_; -//}; -//} -// -//@interface TextureRenderer () -//@property(nonatomic) RendererDelegate *delegate; -//@end -// -//@implementation TextureRenderer -//- (instancetype) -// initWithTextureRegistry:(NSObject *)textureRegistry -// messenger:(NSObject *)messenger -// renderer:(IrisVideoFrameBufferManager *)renderer { -// self = [super init]; -// if (self) { -// self.textureRegistry = textureRegistry; -// self.textureId = [self.textureRegistry registerTexture:self]; -// self.channel = [FlutterMethodChannel -// methodChannelWithName: -// [NSString stringWithFormat:@"agora_rtc_engine/texture_render_%lld", -// self.textureId] -// binaryMessenger:messenger]; -// self.renderer = renderer; -// self.lock = dispatch_semaphore_create(1); -// self.delegate = new ::RendererDelegate((__bridge void *)self); -// __weak __typeof(self) weakSelf = self; -// [self.channel setMethodCallHandler:^(FlutterMethodCall *_Nonnull call, -// FlutterResult _Nonnull result) { -// if (!weakSelf) { -// return; -// } -// if ([@"setData" isEqualToString:call.method]) { -// NSDictionary *data = call.arguments[@"data"]; -// NSNumber *uid = data[@"uid"]; -// NSString *channelId = data[@"channelId"]; -// -// IrisVideoFrameBuffer buffer(kVideoFrameTypeBGRA, -// weakSelf.delegate); -// IrisVideoFrameBufferConfig config; -// -// config.id = [uid unsignedIntValue]; -// if (config.id == 0) { -// config.type = IrisVideoSourceType::kVideoSourceTypeCameraPrimary; -// } else { -// config.type = IrisVideoSourceType::kVideoSourceTypeRemote; -// } -// if (channelId && (NSNull *)channelId != [NSNull null]) { -// strcpy(config.key, [channelId UTF8String]); -// -// } else { -// strcpy(config.key, ""); -// } -// renderer->EnableVideoFrameBuffer(buffer, &config); -// } -// }]; -// } -// return self; -//} -// -//- (void)dealloc { -// [self destroy]; -// if (self.buffer_cache) { -// CVPixelBufferRelease(self.buffer_cache); -// } -//// if (self.buffer_temp) { -//// CVPixelBufferRelease(self.buffer_temp); -//// } -//} -// -//- (void)destroy { -// self.renderer->DisableVideoFrameBuffer(self.delegate); -// [self.textureRegistry unregisterTexture:self.textureId]; -//} -// -//- (CVPixelBufferRef)copyPixelBuffer { -// dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER); -//// CVPixelBufferRelease(self.buffer_temp); -// self.buffer_temp = self.buffer_cache; -// CVPixelBufferRetain(self.buffer_temp); -// dispatch_semaphore_signal(self.lock); -// return self.buffer_temp; -//// return nil; -//} -// -//- (void)onTextureUnregistered:(NSObject *)texture { -//} -//@end -// -//@interface AgoraTextureViewFactory () -//@property(nonatomic, weak) NSObject *registrar; -//@property(nonatomic, weak) NSObject *messenger; -//@property(nonatomic, strong) -// NSMutableDictionary *renderers; -//@end -// -//@implementation AgoraTextureViewFactory -//- (instancetype)initWithRegistrar: -// (NSObject *)registrar { -// self = [super init]; -// if (self) { -// self.registrar = [registrar textures]; -// self.messenger = [registrar messenger]; -// self.renderers = [NSMutableDictionary new]; -// } -// return self; -//} -// -//- (int64_t)createTextureRenderer:(void *)renderer { -// TextureRenderer *texture = [[TextureRenderer alloc] -// initWithTextureRegistry:self.registrar -// messenger:self.messenger -// renderer:(IrisVideoFrameBufferManager *)renderer]; -// int64_t textureId = [texture textureId]; -// self.renderers[@(textureId)] = texture; -// return textureId; -//} -// -//- (BOOL)destroyTextureRenderer:(int64_t)textureId { -// TextureRenderer *texture = [self.renderers objectForKey:@(textureId)]; -// if (texture != nil) { -// [texture destroy]; -// [self.renderers removeObjectForKey:@(textureId)]; -// return YES; -// } -// return NO; -//} -//@end diff --git a/ios/Classes/TextureRenderer.h b/ios/Classes/TextureRenderer.h deleted file mode 100644 index 3ca463926..000000000 --- a/ios/Classes/TextureRenderer.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef TextureRenderer_h -#define TextureRenderer_h - -#if TARGET_OS_IPHONE -#import -#else -#import -#endif - -@interface TextureRender : NSObject - -- (instancetype) -initWithTextureRegistry:(NSObject *)textureRegistry - messenger:(NSObject *)messenger - videoFrameBufferManager:(void *)manager; - -- (void)updateData:(NSNumber *)uid channelId:(NSString *)channelId videoSourceType:(NSNumber *)videoSourceType; - -- (void)dispose; - -@property(nonatomic, assign) int64_t textureId; - -@end - - -#endif /* TextureRenderer_h */ diff --git a/ios/Classes/TextureRenderer.h b/ios/Classes/TextureRenderer.h new file mode 120000 index 000000000..a38749a1b --- /dev/null +++ b/ios/Classes/TextureRenderer.h @@ -0,0 +1 @@ +../../shared/darwin/TextureRenderer.h \ No newline at end of file diff --git a/ios/Classes/TextureRenderer.mm b/ios/Classes/TextureRenderer.mm deleted file mode 100644 index 293f941b3..000000000 --- a/ios/Classes/TextureRenderer.mm +++ /dev/null @@ -1,138 +0,0 @@ -#import -#import "TextureRenderer.h" -#import -#import -#import - -using namespace agora::iris; - -@interface TextureRender () - -@property(nonatomic, weak) NSObject *textureRegistry; -@property(nonatomic, strong) FlutterMethodChannel *channel; -@property(nonatomic) CVPixelBufferRef buffer_cache; -@property(nonatomic, strong) dispatch_semaphore_t lock; -@property(nonatomic) agora::iris::IrisVideoFrameBufferManager *videoFrameBufferManager; - -@end - -namespace { -class RendererDelegate : public IrisVideoFrameBufferDelegate { -public: - RendererDelegate(void *renderer) : renderer_(renderer) {} - - void OnVideoFrameReceived(const IrisVideoFrame &video_frame, - const IrisVideoFrameBufferConfig *config, - bool resize) override { - @autoreleasepool { - TextureRender *renderer = (__bridge TextureRender *)renderer_; - CVPixelBufferRef buffer = renderer.buffer_cache; - - NSDictionary *cvBufferProperties = @{ - (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA), - (__bridge NSString *)kCVPixelBufferIOSurfacePropertiesKey: @{}, - (__bridge NSString *)kCVPixelBufferOpenGLCompatibilityKey: @YES, - (__bridge NSString *)kCVPixelBufferMetalCompatibilityKey: @YES, - }; - - dispatch_semaphore_wait(renderer.lock, DISPATCH_TIME_FOREVER); - if (renderer.buffer_cache != NULL && resize) { - CVBufferRelease(renderer.buffer_cache); - renderer.buffer_cache = NULL; - } - - if (renderer.buffer_cache == NULL) { - CVPixelBufferCreate(kCFAllocatorDefault, video_frame.width, - video_frame.height, kCVPixelFormatType_32BGRA, - (__bridge CFDictionaryRef)cvBufferProperties, &buffer); - } - - CVPixelBufferLockBaseAddress(buffer, 0); - void *copyBaseAddress = CVPixelBufferGetBaseAddress(buffer); - memcpy(copyBaseAddress, video_frame.y_buffer, - video_frame.y_buffer_length); - CVPixelBufferUnlockBaseAddress(buffer, 0); - - renderer.buffer_cache = buffer; - - dispatch_semaphore_signal(renderer.lock); - - [renderer.textureRegistry textureFrameAvailable:renderer.textureId]; - } - } - -public: - void *renderer_; -}; -} - -@interface TextureRender () - -@property(nonatomic) RendererDelegate *delegate; - -@end - -@implementation TextureRender - -- (instancetype) initWithTextureRegistry:(NSObject *)textureRegistry - messenger:(NSObject *)messenger - videoFrameBufferManager:(void *)manager { - self = [super init]; - if (self) { - self.textureRegistry = textureRegistry; - self.videoFrameBufferManager = (IrisVideoFrameBufferManager *)manager; - self.textureId = [self.textureRegistry registerTexture:self]; - self.channel = [FlutterMethodChannel - methodChannelWithName: - [NSString stringWithFormat:@"agora_rtc_engine/texture_render_%lld", - self.textureId] - binaryMessenger:messenger]; - - self.lock = dispatch_semaphore_create(1); - self.delegate = new ::RendererDelegate((__bridge void *)self); - } - return self; -} - -- (void)updateData:(NSNumber *)uid channelId:(NSString *)channelId videoSourceType:(NSNumber *)videoSourceType { - IrisVideoFrameBuffer buffer(kVideoFrameTypeBGRA, - self.delegate, 16); - IrisVideoFrameBufferConfig config; - - config.id = [uid unsignedIntValue]; - config.type = (IrisVideoSourceType)[videoSourceType intValue]; - - if (channelId && (NSNull *)channelId != [NSNull null]) { - strcpy(config.key, [channelId UTF8String]); - - } else { - strcpy(config.key, ""); - } - - self.videoFrameBufferManager->EnableVideoFrameBuffer(buffer, &config); -} - -- (void)dispose { - self.videoFrameBufferManager->DisableVideoFrameBuffer(self.delegate); - if (self.delegate) { - delete self.delegate; - } - [self.textureRegistry unregisterTexture:self.textureId]; - if (self.buffer_cache) { - CVPixelBufferRelease(self.buffer_cache); - } -} - -- (CVPixelBufferRef _Nullable)copyPixelBuffer { - dispatch_semaphore_wait(self.lock, DISPATCH_TIME_FOREVER); - CVPixelBufferRef buffer_temp = CVPixelBufferRetain(self.buffer_cache); - dispatch_semaphore_signal(self.lock); - - return buffer_temp; -} - -- (void)onTextureUnregistered:(NSObject *)texture { -} - -@end - diff --git a/ios/Classes/TextureRenderer.mm b/ios/Classes/TextureRenderer.mm new file mode 120000 index 000000000..a344f3cdb --- /dev/null +++ b/ios/Classes/TextureRenderer.mm @@ -0,0 +1 @@ +../../shared/darwin/TextureRenderer.mm \ No newline at end of file diff --git a/ios/Classes/VideoViewController.h b/ios/Classes/VideoViewController.h deleted file mode 100644 index d76abc664..000000000 --- a/ios/Classes/VideoViewController.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef VideoViewController_h -#define VideoViewController_h - -#if TARGET_OS_IPHONE -#import -#else -#import -#endif - -@interface VideoViewController : NSObject - -- (instancetype)initWith:(NSObject *)textureRegistry - messenger: (NSObject *)messenger; - -- (int64_t)createPlatformRender; - -- (BOOL)destroyPlatformRender:(int64_t)platformRenderId; - -- (int64_t)createTextureRender:(NSNumber *)uid channelId:(NSString *)channelId videoSourceType:(NSNumber *)videoSourceType; - -- (BOOL)destroyTextureRender:(int64_t)textureId; - -@end - - -#endif /* VideoViewController_h */ diff --git a/ios/Classes/VideoViewController.h b/ios/Classes/VideoViewController.h new file mode 120000 index 000000000..9eeec8f9b --- /dev/null +++ b/ios/Classes/VideoViewController.h @@ -0,0 +1 @@ +../../shared/darwin/VideoViewController.h \ No newline at end of file diff --git a/ios/Classes/VideoViewController.mm b/ios/Classes/VideoViewController.mm deleted file mode 100644 index 35d93f188..000000000 --- a/ios/Classes/VideoViewController.mm +++ /dev/null @@ -1,137 +0,0 @@ -#import -#import "VideoViewController.h" -#import "TextureRenderer.h" -#import -#import - -@interface VideoViewController () -@property(nonatomic, weak) NSObject *textureRegistry; -@property(nonatomic, weak) NSObject *messenger; -@property(nonatomic) NSMutableDictionary *textureRenders; -@property(nonatomic) agora::iris::IrisVideoFrameBufferManager *videoFrameBufferManager; -//@property(nonatomic) intptr_t irisRtcEnginePtr; -@property(nonatomic, strong) FlutterMethodChannel *methodChannel; -@end - -@implementation VideoViewController - -- (instancetype)initWith:(NSObject *)textureRegistry - messenger: (NSObject *)messenger { - self = [super init]; - if (self) { - self.textureRegistry = textureRegistry; - self.messenger = messenger; - self.textureRenders = [NSMutableDictionary new]; -// self.irisRtcEnginePtr = 0; - self.videoFrameBufferManager = new agora::iris::IrisVideoFrameBufferManager; - - self.methodChannel = [FlutterMethodChannel - methodChannelWithName: - @"agora_rtc_ng/video_view_controller" - binaryMessenger:messenger]; - - __weak typeof(self) weakSelf = self; - [self.methodChannel setMethodCallHandler:^(FlutterMethodCall *_Nonnull call, - FlutterResult _Nonnull result) { - if (weakSelf != nil) { - [weakSelf onMethodCall:call result:result]; - } - }]; - - - - } - return self; -} - -- (void)onMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { - if ([@"attachVideoFrameBufferManager" isEqualToString:call.method]) { - NSNumber *enginePtrValue = call.arguments; -// if (self.irisRtcEnginePtr != 0) { -// result(@(YES)); -// return; -// } - intptr_t irisRtcEnginePtr = (intptr_t)[enginePtrValue longLongValue]; - IApiEngineBase *irisApiEngine = reinterpret_cast(irisRtcEnginePtr); -// agora::iris::rtc::IrisRtcRawData *rawData = engine->raw_data(); - irisApiEngine->Attach(self.videoFrameBufferManager); - - result(@((intptr_t)self.videoFrameBufferManager)); - } else if ([@"detachVideoFrameBufferManager" isEqualToString:call.method]) { - NSNumber *enginePtrValue = call.arguments; -// if (self.irisRtcEnginePtr == 0) { -// result(@(NO)); -// return; -// } - intptr_t irisRtcEnginePtr = (intptr_t)[enginePtrValue longLongValue]; - IApiEngineBase *irisApiEngine = reinterpret_cast(irisRtcEnginePtr); -// agora::iris::rtc::IrisRtcRawData *rawData = engine->raw_data(); - irisApiEngine->Detach(self.videoFrameBufferManager); - - result(@(YES)); - } - else if ([@"createTextureRender" isEqualToString:call.method]) { - NSDictionary *data = call.arguments; - NSNumber *uid = data[@"uid"]; - NSString *channelId = data[@"channelId"]; - NSNumber *videoSourceType = data[@"videoSourceType"]; - - int64_t textureId = [self createTextureRender:uid channelId:channelId videoSourceType:videoSourceType]; - result(@(textureId)); - } else if ([@"destroyTextureRender" isEqualToString:call.method]) { - NSNumber *textureIdValue = call.arguments; - BOOL success = [self destroyTextureRender: [textureIdValue longLongValue]]; - result(@(success)); - } else if ([@"updateTextureRenderData" isEqualToString:call.method]) { - NSDictionary *data = call.arguments; - int64_t textureId = [data[@"uid"] longLongValue]; - NSNumber *uid = data[@"uid"]; - NSString *channelId = data[@"channelId"]; - NSNumber *videoSourceType = data[@"videoSourceType"]; - - [self updateTextureRenderData:textureId uid:uid channelId:channelId videoSourceType:videoSourceType]; - result(@(YES)); - } -} - -- (int64_t)createPlatformRender { - return 0; -} - -- (BOOL)destroyPlatformRender:(int64_t)platformRenderId { - return true; -} - -- (int64_t)createTextureRender:(NSNumber *)uid channelId:(NSString *)channelId videoSourceType:(NSNumber *)videoSourceType { - TextureRender *textureRender = [[TextureRender alloc] - initWithTextureRegistry:self.textureRegistry - messenger:self.messenger - videoFrameBufferManager:self.videoFrameBufferManager]; - int64_t textureId = [textureRender textureId]; - [textureRender updateData:uid channelId:channelId videoSourceType:videoSourceType]; - self.textureRenders[@(textureId)] = textureRender; - return textureId; -} - -- (void)updateTextureRenderData:(int64_t)textureId uid:(NSNumber *)uid channelId:(NSString *)channelId videoSourceType:(NSNumber *)videoSourceType { - [self.textureRenders[@(textureId)] updateData:uid channelId:channelId videoSourceType:videoSourceType]; -} - -- (BOOL)destroyTextureRender:(int64_t)textureId { - TextureRender *textureRender = [self.textureRenders objectForKey:@(textureId)]; - if (textureRender != nil) { - [textureRender dispose]; - [self.textureRenders removeObjectForKey:@(textureId)]; - return YES; - } - return NO; -} - -- (void)dealloc { - if (self.videoFrameBufferManager) { - delete self.videoFrameBufferManager; - self.videoFrameBufferManager = nil; - } -} - -@end diff --git a/ios/Classes/VideoViewController.mm b/ios/Classes/VideoViewController.mm new file mode 120000 index 000000000..a73160490 --- /dev/null +++ b/ios/Classes/VideoViewController.mm @@ -0,0 +1 @@ +../../shared/darwin/VideoViewController.mm \ No newline at end of file diff --git a/lib/src/impl/agora_video_view_impl.dart b/lib/src/impl/agora_video_view_impl.dart index 81e4b53f9..96433d656 100644 --- a/lib/src/impl/agora_video_view_impl.dart +++ b/lib/src/impl/agora_video_view_impl.dart @@ -181,7 +181,8 @@ class _AgoraRtcRenderTextureState extends State @override void maybeCreateChannel(int viewId, String viewType) { - if (defaultTargetPlatform != TargetPlatform.macOS) { + if (!(defaultTargetPlatform == TargetPlatform.macOS || + defaultTargetPlatform == TargetPlatform.iOS)) { return; } @@ -256,7 +257,8 @@ class _AgoraRtcRenderTextureState extends State @override Widget build(BuildContext context) { if (widget.controller.getTextureId() != kTextureNotInit) { - if (defaultTargetPlatform != TargetPlatform.macOS) { + if (!(defaultTargetPlatform == TargetPlatform.macOS || + defaultTargetPlatform == TargetPlatform.iOS)) { return buildTexure(widget.controller.getTextureId()); } diff --git a/test_shard/rendering_test/README.md b/test_shard/rendering_test/README.md index 501998b38..1b72f9e90 100644 --- a/test_shard/rendering_test/README.md +++ b/test_shard/rendering_test/README.md @@ -1,14 +1,36 @@ # rendering_test -A new Flutter project. +## Running rendering test +### Android/iOS + +``` +flutter drive --driver=test_driver/integration_test.dart \ + --target=integration_test/agora_video_view_render_test.dart \ + --dart-define=TEST_APP_ID="" +``` + +### macOS/Windows -## Getting Started +``` +flutter test integration_test/agora_video_view_render_test.dart \ + --dart-define=TEST_APP_ID="" +``` + +## Update screenshot ### Android/iOS +To update the screenshot, pass the `export UPDATE_GOLDEN="true"` in command line. + ``` +export UPDATE_GOLDEN="true" +flutter drive --driver=test_driver/integration_test.dart \ + --target=integration_test/agora_video_view_render_test.dart \ + --dart-define=TEST_APP_ID="" ``` ### macOS/Windows +To update the screenshot, pass the `--dart-define=UPDATE_GOLDEN=true` to the `flutter test` command. + ``` flutter test integration_test/agora_video_view_render_test.dart \ --dart-define=TEST_APP_ID="" \ diff --git a/test_shard/rendering_test/integration_test/agora_video_view_render_test.dart b/test_shard/rendering_test/integration_test/agora_video_view_render_test.dart index 2db27a00f..f2d19902b 100644 --- a/test_shard/rendering_test/integration_test/agora_video_view_render_test.dart +++ b/test_shard/rendering_test/integration_test/agora_video_view_render_test.dart @@ -153,15 +153,17 @@ void main() { ); group( - 'AgoraVideoView iOS', + 'AgoraVideoView iOS screenshot test', () { group('platform view', () { testWidgets( - 'local rendering screenshot test', + 'local rendering', (WidgetTester tester) async { final onFrameCompleter = Completer(); await tester.pumpWidget(LocalVideoView( + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', onRendered: (RtcEngineEx rtcEngine) async { if (onFrameCompleter.isCompleted) { return; @@ -186,12 +188,14 @@ void main() { ); testWidgets( - 'remote rendering screenshot test', + 'remote rendering', (WidgetTester tester) async { final onFrameCompleter = Completer(); await tester.pumpWidget(RemoteVideoView( renderModeType: RenderModeType.renderModeFit, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', onRendered: (RtcEngineEx rtcEngine) async { if (onFrameCompleter.isCompleted) { return; @@ -217,71 +221,374 @@ void main() { group( 'flutter texture', () { - testWidgets( - 'local rendering screenshot test', - (WidgetTester tester) async { - final onFrameCompleter = Completer(); + group('local rendering', () { + testWidgets( + 'do not handle render mode', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(LocalVideoView( + useFlutterTexture: true, + isRenderModeTest: false, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.local.donot_handle_rendermode'); + + await waitDisposed(tester, binding); + }, + ); - await tester.pumpWidget(LocalVideoView( - useFlutterTexture: true, - onRendered: (RtcEngineEx rtcEngine) async { - if (onFrameCompleter.isCompleted) { - return; - } + testWidgets( + 'render mode default', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); - onFrameCompleter.complete(); - }, - )); + await tester.pumpWidget(LocalVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } - await tester.pumpAndSettle(const Duration(seconds: 10)); + onFrameCompleter.complete(); + }, + )); - await onFrameCompleter.future; - await tester.pumpAndSettle(const Duration(seconds: 10)); + await tester.pumpAndSettle(const Duration(seconds: 10)); - await tester.pumpAndSettle(); + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); - await binding - .takeScreenshot('ios.agora_video_view_render.texture.local'); + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.local.with_default_rendermode'); - await waitDisposed(tester, binding); - }, - // TODO(littlegnal): Flutter texture with software rendering on simulator is not supported. - // The log like below: - // Flutter: Attempted to composite external texture sources using the software backend. - // This backend is only used on simulators. This feature is only available - // on actual devices where OpenGL or Metal is used for rendering. - // - // Temporily skip flutter texture rendering test on ios at this time. - skip: true, - ); - - testWidgets( - 'remote rendering screenshot test', - (WidgetTester tester) async { - final onFrameCompleter = Completer(); - - await tester.pumpWidget(RemoteVideoView( - useFlutterTexture: true, - onRendered: (RtcEngineEx rtcEngine) async { - if (onFrameCompleter.isCompleted) { - return; - } - - onFrameCompleter.complete(); - }, - )); - - await tester.pumpAndSettle(const Duration(seconds: 10)); - - await onFrameCompleter.future; - await tester.pumpAndSettle(const Duration(seconds: 10)); - - await binding - .takeScreenshot('ios.agora_video_view_render.texture.remote'); - - await waitDisposed(tester, binding); - }, - ); + await waitDisposed(tester, binding); + }, + ); + + testWidgets( + 'render mode renderModeHidden', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(LocalVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + renderModeType: RenderModeType.renderModeHidden, + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.local.with_rendermodehidden'); + + await waitDisposed(tester, binding); + }, + ); + + testWidgets( + 'render mode renderModeFit', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(LocalVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + renderModeType: RenderModeType.renderModeFit, + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.local.with_rendermodefit'); + + await waitDisposed(tester, binding); + }, + ); + + testWidgets( + 'render mode renderModeAdaptive', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(LocalVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + renderModeType: RenderModeType.renderModeAdaptive, + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.local.with_rendermodeadaptive'); + + await waitDisposed(tester, binding); + }, + ); + + testWidgets( + 'render mode default and videoMirrorModeDisabled', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(LocalVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + mirrorModeType: VideoMirrorModeType.videoMirrorModeDisabled, + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.local.with_default_rendermode.with_videomirrormodedisabled'); + + await waitDisposed(tester, binding); + }, + ); + }); + + group('remote rendering', () { + testWidgets( + 'do not handle render mode', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(RemoteVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.remote.donot_handle_rendermode'); + + await waitDisposed(tester, binding); + }, + ); + + testWidgets( + 'render mode default', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(RemoteVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.remote.with_default_rendermode'); + + await waitDisposed(tester, binding); + }, + ); + + testWidgets( + 'render mode renderModeHidden', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(RemoteVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + renderModeType: RenderModeType.renderModeHidden, + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.remote.with_rendermodehidden'); + + await waitDisposed(tester, binding); + }, + ); + + testWidgets( + 'render mode renderModeFit', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(RemoteVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + renderModeType: RenderModeType.renderModeFit, + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.remote.with_rendermodefit'); + + await waitDisposed(tester, binding); + }, + ); + + testWidgets( + 'render mode renderModeAdaptive', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(RemoteVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + renderModeType: RenderModeType.renderModeAdaptive, + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.remote.with_rendermodeadaptive'); + + await waitDisposed(tester, binding); + }, + ); + + testWidgets( + 'render mode default and videoMirrorModeDisabled', + (WidgetTester tester) async { + final onFrameCompleter = Completer(); + + await tester.pumpWidget(RemoteVideoView( + useFlutterTexture: true, + url: + 'https://download.agora.io/demo/test/agoravideoview_rendering_test_solid_spilt_asymmetrical.mp4', + mirrorModeType: VideoMirrorModeType.videoMirrorModeEnabled, + onRendered: (RtcEngineEx engine) async { + if (onFrameCompleter.isCompleted) { + return; + } + onFrameCompleter.complete(); + }, + )); + + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await onFrameCompleter.future; + await tester.pumpAndSettle(const Duration(seconds: 10)); + + await binding.takeScreenshot( + 'ios.agora_video_view_render.texture.remote.with_default_rendermodede.with_videoMirrorModeEnabled'); + + await waitDisposed(tester, binding); + }, + ); + }); }, // TODO(littlegnal): Flutter texture with software rendering on simulator is not supported. // The log like below: diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.platformview.local.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.platformview.local.png index 093e10400..83a7f883d 100644 Binary files a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.platformview.local.png and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.platformview.local.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.platformview.remote.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.platformview.remote.png index b406592fd..e1df1d0fb 100644 Binary files a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.platformview.remote.png and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.platformview.remote.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.donot_handle_rendermode.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.donot_handle_rendermode.png new file mode 100644 index 000000000..513d10dd2 Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.donot_handle_rendermode.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.png deleted file mode 100644 index f723e159c..000000000 Binary files a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.png and /dev/null differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_default_rendermode.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_default_rendermode.png new file mode 100644 index 000000000..4601b2fbe Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_default_rendermode.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_default_rendermode.with_videomirrormodedisabled.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_default_rendermode.with_videomirrormodedisabled.png new file mode 100644 index 000000000..8796b9541 Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_default_rendermode.with_videomirrormodedisabled.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_rendermodeadaptive.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_rendermodeadaptive.png new file mode 100644 index 000000000..130c0038e Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_rendermodeadaptive.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_rendermodefit.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_rendermodefit.png new file mode 100644 index 000000000..3515dcad3 Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_rendermodefit.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_rendermodehidden.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_rendermodehidden.png new file mode 100644 index 000000000..4601b2fbe Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.local.with_rendermodehidden.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.donot_handle_rendermode.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.donot_handle_rendermode.png new file mode 100644 index 000000000..87305d271 Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.donot_handle_rendermode.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_default_rendermode.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_default_rendermode.png new file mode 100644 index 000000000..ab042700f Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_default_rendermode.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_default_rendermodede.with_videoMirrorModeEnabled.png similarity index 53% rename from test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.png rename to test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_default_rendermodede.with_videoMirrorModeEnabled.png index 11551e960..500fa5fc0 100644 Binary files a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.png and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_default_rendermodede.with_videoMirrorModeEnabled.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_rendermodeadaptive.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_rendermodeadaptive.png new file mode 100644 index 000000000..6142dcc5f Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_rendermodeadaptive.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_rendermodefit.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_rendermodefit.png new file mode 100644 index 000000000..9afa18d7b Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_rendermodefit.png differ diff --git a/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_rendermodehidden.png b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_rendermodehidden.png new file mode 100644 index 000000000..fd744ede7 Binary files /dev/null and b/test_shard/rendering_test/screenshot/ios.agora_video_view_render.texture.remote.with_rendermodehidden.png differ