From 1045ae9ec5d2f63a356e7e4f8f8d2faa50cad77f Mon Sep 17 00:00:00 2001 From: Goncalo Mendes <106695857+goncalocostamendes@users.noreply.github.com> Date: Thu, 17 Aug 2023 23:31:23 +0100 Subject: [PATCH] [VIDCS-922] Add Video transformers sample (#289) * Add Video transformers sample * Add Video Transformers smaple to travis build * Add a complete README with examples * Include the installation steps * Remove commented code showing how to remove transformers from publisher stream * Add Changelog file with know issues * Button to toggle Video transformers --------- Co-authored-by: pvenum <78760156+pvenum@users.noreply.github.com> --- Video-Transformers/CHANGELOG.md | 32 ++ Video-Transformers/Podfile | 8 + Video-Transformers/README.md | 139 +++++++ .../project.pbxproj | 379 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcschemes/Basic-Video-Chat.xcscheme | 87 ++++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../Video-Transformers/AppDelegate.h | 14 + .../Video-Transformers/AppDelegate.m | 45 +++ .../Base.lproj/Main_iPad.storyboard | 26 ++ .../Base.lproj/Main_iPhone.storyboard | 35 ++ .../AppIcon.appiconset/Contents.json | 98 +++++ .../Images.xcassets/Contents.json | 6 + .../Video-Transformers/Info.plist | 57 +++ .../Video-Transformers/ViewController.h | 12 + .../Video-Transformers/ViewController.m | 356 ++++++++++++++++ .../Video-Transformers/Vonage_Logo.png | Bin 0 -> 38656 bytes .../en.lproj/InfoPlist.strings | 2 + Video-Transformers/Video-Transformers/main.m | 18 + travis_build.sh | 4 + 22 files changed, 1351 insertions(+) create mode 100644 Video-Transformers/CHANGELOG.md create mode 100644 Video-Transformers/Podfile create mode 100644 Video-Transformers/README.md create mode 100644 Video-Transformers/Video-Transformers.xcodeproj/project.pbxproj create mode 100644 Video-Transformers/Video-Transformers.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Video-Transformers/Video-Transformers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Video-Transformers/Video-Transformers.xcodeproj/xcshareddata/xcschemes/Basic-Video-Chat.xcscheme create mode 100644 Video-Transformers/Video-Transformers.xcworkspace/contents.xcworkspacedata create mode 100644 Video-Transformers/Video-Transformers.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Video-Transformers/Video-Transformers/AppDelegate.h create mode 100644 Video-Transformers/Video-Transformers/AppDelegate.m create mode 100644 Video-Transformers/Video-Transformers/Base.lproj/Main_iPad.storyboard create mode 100644 Video-Transformers/Video-Transformers/Base.lproj/Main_iPhone.storyboard create mode 100644 Video-Transformers/Video-Transformers/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Video-Transformers/Video-Transformers/Images.xcassets/Contents.json create mode 100644 Video-Transformers/Video-Transformers/Info.plist create mode 100644 Video-Transformers/Video-Transformers/ViewController.h create mode 100644 Video-Transformers/Video-Transformers/ViewController.m create mode 100644 Video-Transformers/Video-Transformers/Vonage_Logo.png create mode 100644 Video-Transformers/Video-Transformers/en.lproj/InfoPlist.strings create mode 100644 Video-Transformers/Video-Transformers/main.m diff --git a/Video-Transformers/CHANGELOG.md b/Video-Transformers/CHANGELOG.md new file mode 100644 index 00000000..f68d4648 --- /dev/null +++ b/Video-Transformers/CHANGELOG.md @@ -0,0 +1,32 @@ +# Video Transformers Changelog + +All notable changes to this project will be documented in this file. + +## 2.25.2 + +### Added + +- Support pre-built transformers in the Vonage Media Processor library or create your own custom video transformer to apply to published video. + +### Known issues + +- When using Vonage's Background Blur, the ML model is not being automatically added to the main bundle. It is required to be added manually: + - Select the target for which you want to add the file. Go to the "Build Phases" tab. + - Expand the "Copy Bundle Resources" section. + - Click the "+" button to add a new file. A file picker dialog will appear. Choose ./Pods/VonageClientSDKVideo/OpenTok.xcframework/ios-arm64/OpenTok.framework/selfie_segmentation.tflite + +### Fixed + +- NA + +### Enhancements + +- NA + +### Changed + +- NA + +### Deprecated + +- NA diff --git a/Video-Transformers/Podfile b/Video-Transformers/Podfile new file mode 100644 index 00000000..01c0065b --- /dev/null +++ b/Video-Transformers/Podfile @@ -0,0 +1,8 @@ +require_relative '../OpenTokSDKVersion' + +platform :ios, '13' +use_frameworks! + +target 'Video-Transformers' do + pod 'VonageClientSDKVideo', '2.25.2' +end diff --git a/Video-Transformers/README.md b/Video-Transformers/README.md new file mode 100644 index 00000000..fad6fe1f --- /dev/null +++ b/Video-Transformers/README.md @@ -0,0 +1,139 @@ +Video Transformers +====================== + +The Video Transformers app is a very simple application created on top of Basic Video Chat meant to get a new developer +started using Media Processor APIs on OpenTok iOS SDK. For a full description, see the [Video Transformers tutorial at the +OpenTok developer center](https://tokbox.com/developer/guides/vonage-media-processor/ios). + +You can use pre-built transformers in the Vonage Media Processor library or create your own custom video transformer to apply to published video. + +You can use the OTPublisherKit.videoTransformers properties to apply video transformers to a stream. + +For video, you can apply the background blur video transformer included in the Vonage Media Library. +You can use the OTPublisherKit.audioTransformers and +OTPublisherKit.videoTransformers +properties to apply audio and video transformers to a stream. + +

+ Important: The audio and video transformer API is a beta feature. +

+ +For video, you can apply the background blur video transformer included in the Vonage Media Library. + +You can also create your own custom audio and video transformers. + +## Applying a video transformer from the Vonage Media Library + +Use the [OTVideoTransformer initWithName:properties:] +method to create a video transformer that uses a named transformer from the Vonage Media Library. + +Currently, only one transformer is supported: background blur. Set the `name` parameter to `"BackgroundBlur"`. +Set the `properties` parameter to a JSON string defining properties for the transformer. +For the background blur transformer, this JSON includes one property -- `radius` -- which can be set +to `"High"`, `"Low"`, or `"None"`. + +```objectivec +NSMutableArray * myVideoTransformers = [[NSMutableArray alloc] init]; +OTVideoTransformer *backgroundBlur = [[OTVideoTransformer alloc] initWithName:@"BackgroundBlur" + properties:@"{\"radius\":\"High\"}"]; +[myVideoTransformers addObject:backgroundBlur]; +_publisher.videoTransformers = [[NSArray alloc] initWithArray:myVideoTransformers]; +``` + +## Creating a custom video transformer + +Create a class that implements the OTCustomVideoTransformer +protocol. Implement the `[OTCustomVideoTransformer transform:]` method, applying a transformation to the `OTVideoFrame` object passed into the method. The `[OTCustomVideoTransformer transform:]` method is triggered for each video frame: + +```objectivec +@interface CustomTransformer : NSObject +@end +@implementation CustomTransformer +- (void)transform:(nonnull OTVideoFrame *)videoFrame { + // Your custom transformation +} +@end +``` + +In this sample, to display one of the infinite transformations that can be applied to video frames, a logo is being added to the bottom right corner of the video. + +```objectivec +@interface CustomTransformer : NSObject +@end +@implementation CustomTransformer +- (void)transform:(nonnull OTVideoFrame *)videoFrame { + + UIImage* image = [UIImage imageNamed:@"Vonage_Logo.png"]; + + uint32_t videoWidth = videoFrame.format.imageWidth; + uint32_t videoHeight = videoFrame.format.imageHeight; + + // Calculate the desired size of the image + CGFloat desiredWidth = videoWidth / 8; // Adjust this value as needed + CGFloat desiredHeight = image.size.height * (desiredWidth / image.size.width); + + // Resize the image to the desired size + UIImage *resizedImage = [self resizeImage:image toSize:CGSizeMake(desiredWidth, desiredHeight)]; + + // Get pointer to the Y plane + uint8_t* yPlane = [videoFrame getPlaneBinaryData:0]; + + // Create a CGContext from the Y plane + CGContextRef context = CGBitmapContextCreate(yPlane, videoWidth, videoHeight, 8, videoWidth, CGColorSpaceCreateDeviceGray(), kCGImageAlphaNone); + + // Location of the image (in this case right bottom corner) + CGFloat x = videoWidth * 4/5; + CGFloat y = videoHeight * 1/5; + + // Draw the resized image on top of the Y plane + CGRect rect = CGRectMake(x, y, desiredWidth, desiredHeight); + CGContextDrawImage(context, rect, resizedImage.CGImage); + + CGContextRelease(context); +} +@end +``` + +Then set the `OTPublisherKit.videoTransformers` property to an array that includes the object that implements the +OTCustomVideoTransformer interface: + +```objectivec +CustomTransformer* logoTransformer; +logoTransformer = [customTransformer alloc]; +OTVideoTransformer *myCustomTransformer = [[OTVideoTransformer alloc] initWithName:@"logo" transformer:logoTransformer]; + +NSMutableArray * myVideoTransformers = [[NSMutableArray alloc] init]; +[myVideoTransformers addObject:myCustomTransformer]; + +_publisher.videoTransformers = [[NSArray alloc] initWithArray:myVideoTransformers]; +``` + +You can combine the Vonage Media library transformer (see the previous section) with custom transformers or apply +multiple custom transformers by adding multiple PublisherKit.VideoTransformer objects to the ArrayList used +for the `OTPublisherKit.videoTransformers` property. + +## Clearing video transformers for a publisher + +To clear video transformers for a publisher, set the `OTPublisherKit.videoTransformers` property to an empty array. + +```objectivec +_publisher.videoTransformers = [[NSArray alloc] init]; +``` + +Adding the OpenTok library +========================== +In this example the OpenTok iOS SDK was not included as a dependency, +you can do it through Swift Package Manager or Cocoapods. + + +Swift Package Manager +--------------------- +To add a package dependency to your Xcode project, you should select +*File* > *Swift Packages* > *Add Package Dependency* and enter the repository URL: +`https://github.com/opentok/vonage-client-sdk-video.git`. + + +Cocoapods +--------- +To use CocoaPods to add the OpenTok library and its dependencies into this sample app +simply open Terminal, navigate to the root directory of the project and run: `pod install`. diff --git a/Video-Transformers/Video-Transformers.xcodeproj/project.pbxproj b/Video-Transformers/Video-Transformers.xcodeproj/project.pbxproj new file mode 100644 index 00000000..b9ce6743 --- /dev/null +++ b/Video-Transformers/Video-Transformers.xcodeproj/project.pbxproj @@ -0,0 +1,379 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + A05376311EB173CC00645696 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A05376251EB173CC00645696 /* AppDelegate.m */; }; + A05376321EB173CC00645696 /* Main_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A05376261EB173CC00645696 /* Main_iPad.storyboard */; }; + A05376331EB173CC00645696 /* Main_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A05376281EB173CC00645696 /* Main_iPhone.storyboard */; }; + A05376341EB173CC00645696 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A053762A1EB173CC00645696 /* InfoPlist.strings */; }; + A05376351EB173CC00645696 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A053762C1EB173CC00645696 /* Images.xcassets */; }; + A05376361EB173CC00645696 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A053762D1EB173CC00645696 /* main.m */; }; + A05376371EB173CC00645696 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A053762F1EB173CC00645696 /* ViewController.m */; }; + AD08FCCB2A2F8A4300F4F7A1 /* Vonage_Logo.png in Resources */ = {isa = PBXBuildFile; fileRef = AD08FCCA2A2F8A4300F4F7A1 /* Vonage_Logo.png */; }; + AD534BB82A335ED8007D996A /* selfie_segmentation.tflite in Resources */ = {isa = PBXBuildFile; fileRef = AD534BB72A335ED8007D996A /* selfie_segmentation.tflite */; }; + D442614C185F92C000E23699 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = D442614B185F92BF00E23699 /* README.md */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + A05376221EB173CC00645696 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A05376241EB173CC00645696 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + A05376251EB173CC00645696 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + A05376271EB173CC00645696 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPad.storyboard; sourceTree = ""; }; + A05376291EB173CC00645696 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main_iPhone.storyboard; sourceTree = ""; }; + A053762B1EB173CC00645696 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + A053762C1EB173CC00645696 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + A053762D1EB173CC00645696 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + A053762E1EB173CC00645696 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + A053762F1EB173CC00645696 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + AD08FCCA2A2F8A4300F4F7A1 /* Vonage_Logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Vonage_Logo.png; sourceTree = ""; }; + AD534BB72A335ED8007D996A /* selfie_segmentation.tflite */ = {isa = PBXFileReference; lastKnownFileType = file; name = selfie_segmentation.tflite; path = "Pods/VonageClientSDKVideo/OpenTok.xcframework/ios-arm64/OpenTok.framework/selfie_segmentation.tflite"; sourceTree = ""; }; + D44260F3185F81D800E23699 /* Video-Transformers.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Video-Transformers.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + D44260F6185F81D800E23699 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + D44260FA185F81D800E23699 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + D442614B185F92BF00E23699 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.md; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D44260F0185F81D800E23699 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 82EBC85A29B2215464A49FD9 /* Pods */ = { + isa = PBXGroup; + children = ( + ); + path = Pods; + sourceTree = ""; + }; + A05376211EB173CC00645696 /* Video-Transformers */ = { + isa = PBXGroup; + children = ( + A05376221EB173CC00645696 /* Info.plist */, + AD08FCCA2A2F8A4300F4F7A1 /* Vonage_Logo.png */, + A05376241EB173CC00645696 /* AppDelegate.h */, + A05376251EB173CC00645696 /* AppDelegate.m */, + A05376261EB173CC00645696 /* Main_iPad.storyboard */, + A05376281EB173CC00645696 /* Main_iPhone.storyboard */, + A053762A1EB173CC00645696 /* InfoPlist.strings */, + A053762C1EB173CC00645696 /* Images.xcassets */, + A053762D1EB173CC00645696 /* main.m */, + A053762E1EB173CC00645696 /* ViewController.h */, + A053762F1EB173CC00645696 /* ViewController.m */, + ); + path = "Video-Transformers"; + sourceTree = ""; + }; + D44260EA185F81D800E23699 = { + isa = PBXGroup; + children = ( + AD534BB72A335ED8007D996A /* selfie_segmentation.tflite */, + D442614B185F92BF00E23699 /* README.md */, + A05376211EB173CC00645696 /* Video-Transformers */, + D44260F5185F81D800E23699 /* Frameworks */, + D44260F4185F81D800E23699 /* Products */, + 82EBC85A29B2215464A49FD9 /* Pods */, + ); + sourceTree = ""; + }; + D44260F4185F81D800E23699 /* Products */ = { + isa = PBXGroup; + children = ( + D44260F3185F81D800E23699 /* Video-Transformers.app */, + ); + name = Products; + sourceTree = ""; + }; + D44260F5185F81D800E23699 /* Frameworks */ = { + isa = PBXGroup; + children = ( + D44260F6185F81D800E23699 /* Foundation.framework */, + D44260FA185F81D800E23699 /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + D44260F2185F81D800E23699 /* Video-Transformers */ = { + isa = PBXNativeTarget; + buildConfigurationList = D4426128185F81D800E23699 /* Build configuration list for PBXNativeTarget "Video-Transformers" */; + buildPhases = ( + D44260EF185F81D800E23699 /* Sources */, + D44260F0185F81D800E23699 /* Frameworks */, + D44260F1185F81D800E23699 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Video-Transformers"; + productName = "Hello-World"; + productReference = D44260F3185F81D800E23699 /* Video-Transformers.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D44260EB185F81D800E23699 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1200; + ORGANIZATIONNAME = "TokBox, Inc."; + TargetAttributes = { + D44260F2185F81D800E23699 = { + DevelopmentTeam = 2A784Y2X3Q; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = D44260EE185F81D800E23699 /* Build configuration list for PBXProject "Video-Transformers" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = D44260EA185F81D800E23699; + productRefGroup = D44260F4185F81D800E23699 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D44260F2185F81D800E23699 /* Video-Transformers */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D44260F1185F81D800E23699 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AD534BB82A335ED8007D996A /* selfie_segmentation.tflite in Resources */, + AD08FCCB2A2F8A4300F4F7A1 /* Vonage_Logo.png in Resources */, + A05376331EB173CC00645696 /* Main_iPhone.storyboard in Resources */, + A05376321EB173CC00645696 /* Main_iPad.storyboard in Resources */, + A05376351EB173CC00645696 /* Images.xcassets in Resources */, + D442614C185F92C000E23699 /* README.md in Resources */, + A05376341EB173CC00645696 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D44260EF185F81D800E23699 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A05376371EB173CC00645696 /* ViewController.m in Sources */, + A05376361EB173CC00645696 /* main.m in Sources */, + A05376311EB173CC00645696 /* AppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + A05376261EB173CC00645696 /* Main_iPad.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A05376271EB173CC00645696 /* Base */, + ); + name = Main_iPad.storyboard; + sourceTree = ""; + }; + A05376281EB173CC00645696 /* Main_iPhone.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A05376291EB173CC00645696 /* Base */, + ); + name = Main_iPhone.storyboard; + sourceTree = ""; + }; + A053762A1EB173CC00645696 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + A053762B1EB173CC00645696 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + D4426127185F81D800E23699 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_BITCODE = NO; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + D442612A185F81D800E23699 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 2A784Y2X3Q; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "${SRCROOT}", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ""; + INFOPLIST_FILE = "$(SRCROOT)/Video-Transformers/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + PRODUCT_BUNDLE_IDENTIFIER = "com.tokbox.Video-Transformers543e"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + F8DE15D11D95710C00EFFA79 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + ENABLE_BITCODE = NO; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Debug; + }; + F8DE15D21D95710C00EFFA79 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 2A784Y2X3Q; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "${SRCROOT}", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = ""; + INFOPLIST_FILE = "$(SRCROOT)/Video-Transformers/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + PRODUCT_BUNDLE_IDENTIFIER = "com.tokbox.Video-Transformers543e"; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D44260EE185F81D800E23699 /* Build configuration list for PBXProject "Video-Transformers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D4426127185F81D800E23699 /* Release */, + F8DE15D11D95710C00EFFA79 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D4426128185F81D800E23699 /* Build configuration list for PBXNativeTarget "Video-Transformers" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D442612A185F81D800E23699 /* Release */, + F8DE15D21D95710C00EFFA79 /* Debug */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D44260EB185F81D800E23699 /* Project object */; +} diff --git a/Video-Transformers/Video-Transformers.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Video-Transformers/Video-Transformers.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..df5530a0 --- /dev/null +++ b/Video-Transformers/Video-Transformers.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Video-Transformers/Video-Transformers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Video-Transformers/Video-Transformers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Video-Transformers/Video-Transformers.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Video-Transformers/Video-Transformers.xcodeproj/xcshareddata/xcschemes/Basic-Video-Chat.xcscheme b/Video-Transformers/Video-Transformers.xcodeproj/xcshareddata/xcschemes/Basic-Video-Chat.xcscheme new file mode 100644 index 00000000..d84a4a39 --- /dev/null +++ b/Video-Transformers/Video-Transformers.xcodeproj/xcshareddata/xcschemes/Basic-Video-Chat.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Video-Transformers/Video-Transformers.xcworkspace/contents.xcworkspacedata b/Video-Transformers/Video-Transformers.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..926fe098 --- /dev/null +++ b/Video-Transformers/Video-Transformers.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Video-Transformers/Video-Transformers.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Video-Transformers/Video-Transformers.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/Video-Transformers/Video-Transformers.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Video-Transformers/Video-Transformers/AppDelegate.h b/Video-Transformers/Video-Transformers/AppDelegate.h new file mode 100644 index 00000000..c6e9853f --- /dev/null +++ b/Video-Transformers/Video-Transformers/AppDelegate.h @@ -0,0 +1,14 @@ +// +// AppDelegate.h +// Hello-World +// +// Copyright (c) 2013 TokBox, Inc. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end diff --git a/Video-Transformers/Video-Transformers/AppDelegate.m b/Video-Transformers/Video-Transformers/AppDelegate.m new file mode 100644 index 00000000..aafb971a --- /dev/null +++ b/Video-Transformers/Video-Transformers/AppDelegate.m @@ -0,0 +1,45 @@ +// +// AppDelegate.m +// Hello-World +// +// Copyright (c) 2013 TokBox, Inc. All rights reserved. +// + +#import "AppDelegate.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/Video-Transformers/Video-Transformers/Base.lproj/Main_iPad.storyboard b/Video-Transformers/Video-Transformers/Base.lproj/Main_iPad.storyboard new file mode 100644 index 00000000..a185e8a5 --- /dev/null +++ b/Video-Transformers/Video-Transformers/Base.lproj/Main_iPad.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Video-Transformers/Video-Transformers/Base.lproj/Main_iPhone.storyboard b/Video-Transformers/Video-Transformers/Base.lproj/Main_iPhone.storyboard new file mode 100644 index 00000000..114c10e8 --- /dev/null +++ b/Video-Transformers/Video-Transformers/Base.lproj/Main_iPhone.storyboard @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Video-Transformers/Video-Transformers/Images.xcassets/AppIcon.appiconset/Contents.json b/Video-Transformers/Video-Transformers/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..1569f8dd --- /dev/null +++ b/Video-Transformers/Video-Transformers/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Video-Transformers/Video-Transformers/Images.xcassets/Contents.json b/Video-Transformers/Video-Transformers/Images.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Video-Transformers/Video-Transformers/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Video-Transformers/Video-Transformers/Info.plist b/Video-Transformers/Video-Transformers/Info.plist new file mode 100644 index 00000000..0db1a725 --- /dev/null +++ b/Video-Transformers/Video-Transformers/Info.plist @@ -0,0 +1,57 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + NSCameraUsageDescription + Opentok needs access to the camera to stream your video + NSMicrophoneUsageDescription + Opentok needs access to the microphone to stream your audio + UIBackgroundModes + + audio + + UIMainStoryboardFile + Main_iPhone + UIMainStoryboardFile~ipad + Main_iPad + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Video-Transformers/Video-Transformers/ViewController.h b/Video-Transformers/Video-Transformers/ViewController.h new file mode 100644 index 00000000..0d97d45f --- /dev/null +++ b/Video-Transformers/Video-Transformers/ViewController.h @@ -0,0 +1,12 @@ +// +// ViewController.h +// Hello-World +// +// Copyright (c) 2013 TokBox, Inc. All rights reserved. +// + +#import + +@interface ViewController : UIViewController + +@end diff --git a/Video-Transformers/Video-Transformers/ViewController.m b/Video-Transformers/Video-Transformers/ViewController.m new file mode 100644 index 00000000..38d42eb9 --- /dev/null +++ b/Video-Transformers/Video-Transformers/ViewController.m @@ -0,0 +1,356 @@ +// +// ViewController.m +// Hello-World +// +// Copyright (c) 2013 TokBox, Inc. All rights reserved. +// + +#import "ViewController.h" +#import + +// *** Fill the following variables using your own Project info *** +// *** https://dashboard.tokbox.com/projects *** +// Replace with your OpenTok API key +static NSString* const kApiKey = @""; +// Replace with your generated session ID +static NSString* const kSessionId = @""; +// Replace with your generated token +static NSString* const kToken = @""; + +@interface ViewController () +@property (nonatomic) OTSession *session; +@property (nonatomic) OTPublisher *publisher; +@property (nonatomic) OTSubscriber *subscriber; +@end + +static double widgetHeight = 240; +static double widgetWidth = 320; + +@interface customTransformer : NSObject + +- (UIImage *)resizeImage:(UIImage *)image toSize:(CGSize)size; + +@end + + +@implementation customTransformer + +- (UIImage *)resizeImage:(UIImage *)image toSize:(CGSize)size { + UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); + [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; + UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return resizedImage; +} + +- (void)transform:(nonnull OTVideoFrame *)videoFrame { + + UIImage* image = [UIImage imageNamed:@"Vonage_Logo.png"]; + + uint32_t videoWidth = videoFrame.format.imageWidth; + uint32_t videoHeight = videoFrame.format.imageHeight; + + // Calculate the desired size of the image + CGFloat desiredWidth = videoWidth / 8; // Adjust this value as needed + CGFloat desiredHeight = image.size.height * (desiredWidth / image.size.width); + + // Resize the image to the desired size + UIImage *resizedImage = [self resizeImage:image toSize:CGSizeMake(desiredWidth, desiredHeight)]; + + // Get pointer to the Y plane + uint8_t* yPlane = [videoFrame getPlaneBinaryData:0]; + + // Create a CGContext from the Y plane + CGContextRef context = CGBitmapContextCreate(yPlane, videoWidth, videoHeight, 8, videoWidth, CGColorSpaceCreateDeviceGray(), kCGImageAlphaNone); + + // Location of the image (in this case right bottom corner) + CGFloat x = videoWidth * 4/5; + CGFloat y = videoHeight * 1/5; + + // Draw the resized image on top of the Y plane + CGRect rect = CGRectMake(x, y, desiredWidth, desiredHeight); + CGContextDrawImage(context, rect, resizedImage.CGImage); + + CGContextRelease(context); +} + +@end + +customTransformer* logoTransformer; + +@implementation ViewController + +UIButton *buttonVideoTransformerToggle; + +#pragma mark - View lifecycle + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // Step 1: As the view comes into the foreground, initialize a new instance + // of OTSession and begin the connection process. + _session = [[OTSession alloc] initWithApiKey:kApiKey + sessionId:kSessionId + delegate:self]; + [self doConnect]; +} + +- (BOOL)prefersStatusBarHidden +{ + return YES; +} + +- (BOOL)shouldAutorotate { + return UIUserInterfaceIdiomPhone != [[UIDevice currentDevice] userInterfaceIdiom]; +} +#pragma mark - OpenTok methods + +/** + * Asynchronously begins the session connect process. Some time later, we will + * expect a delegate method to call us back with the results of this action. + */ +- (void)doConnect +{ + OTError *error = nil; + + [_session connectWithToken:kToken error:&error]; + if (error) + { + [self showAlert:[error localizedDescription]]; + } +} + +/** + * Sets up an instance of OTPublisher to use with this session. OTPubilsher + * binds to the device camera and microphone, and will provide A/V streams + * to the OpenTok session. + */ +- (void)doPublish +{ + OTPublisherSettings *settings = [[OTPublisherSettings alloc] init]; + settings.name = [UIDevice currentDevice].name; + _publisher = [[OTPublisher alloc] initWithDelegate:self settings:settings]; + + OTError *error = nil; + [_session publish:_publisher error:&error]; + if (error) + { + [self showAlert:[error localizedDescription]]; + } + + [self.view addSubview:_publisher.view]; + [_publisher.view setFrame:CGRectMake(0, 0, widgetWidth, widgetHeight)]; + + // Configure toogle button + buttonVideoTransformerToggle = [UIButton buttonWithType:UIButtonTypeCustom]; + buttonVideoTransformerToggle.frame = CGRectMake(widgetWidth - 65, 15, 50, 25); + buttonVideoTransformerToggle.layer.cornerRadius = 5.0; + [self.view addSubview:buttonVideoTransformerToggle]; + [self.view bringSubviewToFront:buttonVideoTransformerToggle]; + [buttonVideoTransformerToggle setTitle:@"set" forState:UIControlStateNormal]; + buttonVideoTransformerToggle.titleLabel.font = [UIFont systemFontOfSize:12]; + [buttonVideoTransformerToggle setTitleColor:[UIColor grayColor] forState:UIControlStateNormal]; + buttonVideoTransformerToggle.backgroundColor = [UIColor whiteColor]; + buttonVideoTransformerToggle.layer.borderWidth = 1.0; // Adjust the width as desired + buttonVideoTransformerToggle.layer.borderColor = [UIColor grayColor].CGColor; + [buttonVideoTransformerToggle addTarget:self action:@selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside]; + +} + +/** + * Cleans up the publisher and its view. At this point, the publisher should not + * be attached to the session any more. + */ +- (void)cleanupPublisher { + [_publisher.view removeFromSuperview]; + _publisher = nil; + // this is a good place to notify the end-user that publishing has stopped. +} + +/** + * Instantiates a subscriber for the given stream and asynchronously begins the + * process to begin receiving A/V content for this stream. Unlike doPublish, + * this method does not add the subscriber to the view hierarchy. Instead, we + * add the subscriber only after it has connected and begins receiving data. + */ +- (void)doSubscribe:(OTStream*)stream +{ + _subscriber = [[OTSubscriber alloc] initWithStream:stream delegate:self]; + + OTError *error = nil; + [_session subscribe:_subscriber error:&error]; + if (error) + { + [self showAlert:[error localizedDescription]]; + } +} + +/** + * Cleans the subscriber from the view hierarchy, if any. + * NB: You do *not* have to call unsubscribe in your controller in response to + * a streamDestroyed event. Any subscribers (or the publisher) for a stream will + * be automatically removed from the session during cleanup of the stream. + */ +- (void)cleanupSubscriber +{ + [_subscriber.view removeFromSuperview]; + _subscriber = nil; +} + +# pragma mark - OTSession delegate callbacks + +- (void)sessionDidConnect:(OTSession*)session +{ + NSLog(@"sessionDidConnect (%@)", session.sessionId); + + // Step 2: We have successfully connected, now instantiate a publisher and + // begin pushing A/V streams into OpenTok. + [self doPublish]; +} + +- (void)sessionDidDisconnect:(OTSession*)session +{ + NSString* alertMessage = + [NSString stringWithFormat:@"Session disconnected: (%@)", + session.sessionId]; + NSLog(@"sessionDidDisconnect (%@)", alertMessage); +} + + +- (void)session:(OTSession*)mySession + streamCreated:(OTStream *)stream +{ + NSLog(@"session streamCreated (%@)", stream.streamId); + + if (nil == _subscriber) + { + [self doSubscribe:stream]; + } +} + +- (void)session:(OTSession*)session +streamDestroyed:(OTStream *)stream +{ + NSLog(@"session streamDestroyed (%@)", stream.streamId); + + if ([_subscriber.stream.streamId isEqualToString:stream.streamId]) + { + [self cleanupSubscriber]; + } +} + +- (void) session:(OTSession *)session +connectionCreated:(OTConnection *)connection +{ + NSLog(@"session connectionCreated (%@)", connection.connectionId); +} + +- (void) session:(OTSession *)session +connectionDestroyed:(OTConnection *)connection +{ + NSLog(@"session connectionDestroyed (%@)", connection.connectionId); + if ([_subscriber.stream.connection.connectionId + isEqualToString:connection.connectionId]) + { + [self cleanupSubscriber]; + } +} + +- (void) session:(OTSession*)session +didFailWithError:(OTError*)error +{ + NSLog(@"didFailWithError: (%@)", error); +} + +# pragma mark - OTSubscriber delegate callbacks + +- (void)subscriberDidConnectToStream:(OTSubscriberKit*)subscriber +{ + NSLog(@"subscriberDidConnectToStream (%@)", + subscriber.stream.connection.connectionId); + assert(_subscriber == subscriber); + [_subscriber.view setFrame:CGRectMake(0, widgetHeight, widgetWidth, + widgetHeight)]; + [self.view addSubview:_subscriber.view]; +} + +- (void)subscriber:(OTSubscriberKit*)subscriber + didFailWithError:(OTError*)error +{ + NSLog(@"subscriber %@ didFailWithError %@", + subscriber.stream.streamId, + error); +} + +# pragma mark - OTPublisher delegate callbacks + +- (void)publisher:(OTPublisherKit *)publisher + streamCreated:(OTStream *)stream +{ + NSLog(@"Publishing"); +} + +- (void)publisher:(OTPublisherKit*)publisher + streamDestroyed:(OTStream *)stream +{ + if ([_subscriber.stream.streamId isEqualToString:stream.streamId]) + { + [self cleanupSubscriber]; + } + + [self cleanupPublisher]; +} + +- (void)publisher:(OTPublisherKit*)publisher + didFailWithError:(OTError*) error +{ + NSLog(@"publisher didFailWithError %@", error); + [self cleanupPublisher]; +} + +- (void)showAlert:(NSString *)string +{ + // show alertview on main UI + dispatch_async(dispatch_get_main_queue(), ^{ + UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"OTError" + message:string + preferredStyle:UIAlertControllerStyleAlert]; + [self presentViewController:alertVC animated:YES completion:nil]; + }); +} + +bool isSet = false; + +- (void)buttonTapped:(UIButton *)sender { + + if(!isSet) { + // Create background blur Vonage transformer + OTVideoTransformer *BackgroundBlur = [[OTVideoTransformer alloc] initWithName:@"BackgroundBlur" properties:@"{\"radius\":\"High\"}"]; + + // Create custom transformer + logoTransformer = [customTransformer alloc]; + OTVideoTransformer *myCustomTransformer = [[OTVideoTransformer alloc] initWithName:@"logo" transformer:logoTransformer]; + + NSMutableArray * myVideoTransformers = [[NSMutableArray alloc] init]; + + [myVideoTransformers addObject:BackgroundBlur]; + [myVideoTransformers addObject:myCustomTransformer]; + + // Set video transformers to publisher video stream + _publisher.videoTransformers = [[NSMutableArray alloc] initWithArray:myVideoTransformers]; + + [buttonVideoTransformerToggle setTitle:@"reset" forState:UIControlStateNormal]; + isSet = true; + } else { + // Clear all transformers from video stream + _publisher.videoTransformers = [[NSArray alloc] init]; + + [buttonVideoTransformerToggle setTitle:@"set" forState:UIControlStateNormal]; + isSet = false; + } + +} + + +@end diff --git a/Video-Transformers/Video-Transformers/Vonage_Logo.png b/Video-Transformers/Video-Transformers/Vonage_Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..2087713a8047a289115488e37061d0d6e2b85896 GIT binary patch literal 38656 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 KC!sB#U;H18QX`%K literal 0 HcmV?d00001 diff --git a/Video-Transformers/Video-Transformers/en.lproj/InfoPlist.strings b/Video-Transformers/Video-Transformers/en.lproj/InfoPlist.strings new file mode 100644 index 00000000..477b28ff --- /dev/null +++ b/Video-Transformers/Video-Transformers/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Video-Transformers/Video-Transformers/main.m b/Video-Transformers/Video-Transformers/main.m new file mode 100644 index 00000000..5865f159 --- /dev/null +++ b/Video-Transformers/Video-Transformers/main.m @@ -0,0 +1,18 @@ +// +// main.m +// Hello-World +// +// Created by Charley Robinson on 12/16/13. +// Copyright (c) 2013 TokBox, Inc. All rights reserved. +// + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/travis_build.sh b/travis_build.sh index 892a2056..25255641 100755 --- a/travis_build.sh +++ b/travis_build.sh @@ -53,3 +53,7 @@ xcodebuild -workspace FrameMetadata.xcworkspace -scheme FrameMetadata -sdk ipho cd ../Broadcast-Ext/ pod install xcodebuild -workspace Broadcast-Ext.xcworkspace -scheme Broadcast-Ext -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO -UseModernBuildSystem=NO + +cd Video-Transformers/ +pod install +xcodebuild -workspace Video-Transformers.xcworkspace -scheme Video-Transformers -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO -UseModernBuildSystem=NO