Skip to content

Commit

Permalink
feat: Video filters (#799)
Browse files Browse the repository at this point in the history
* Video filters

* tweak

* fix

* custom filter added

* fix

* tweaks

* typo fixed

* changelog added
  • Loading branch information
Brazol authored Jan 9, 2025
1 parent f78f88b commit 06ab616
Show file tree
Hide file tree
Showing 66 changed files with 1,850 additions and 256 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,64 @@
package io.getstream.video.flutter.dogfooding

import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.graphics.Paint

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.PluginRegistry

import io.getstream.video.flutter.stream_video_flutter.service.PictureInPictureHelper
import io.getstream.video.flutter.stream_video_flutter.videoFilters.common.VideoFrameProcessorWithBitmapFilter
import io.getstream.video.flutter.stream_video_flutter.videoFilters.common.BitmapVideoFilter
import io.getstream.webrtc.flutter.videoEffects.ProcessorProvider
import io.getstream.webrtc.flutter.videoEffects.VideoFrameProcessor
import io.getstream.webrtc.flutter.videoEffects.VideoFrameProcessorFactoryInterface

class MainActivity: FlutterActivity() {
private val CHANNEL = "io.getstream.video.flutter.dogfooding.channel"

override fun onUserLeaveHint() {
super.onUserLeaveHint()
PictureInPictureHelper.enterPictureInPictureIfInCall(this)
}

override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "registerGreyscaleEffect") {
ProcessorProvider.addProcessor("grayscale", GrayScaleVideoFilterFactory())
result.success(null)
} else {
result.notImplemented()
}
}
}
}

class GrayScaleVideoFilterFactory : VideoFrameProcessorFactoryInterface {
override fun build(): VideoFrameProcessor {
return VideoFrameProcessorWithBitmapFilter {
GrayScaleFilter()
}
}
}
private class GrayScaleFilter : BitmapVideoFilter() {
override fun applyFilter(videoFrameBitmap: Bitmap) {
val canvas = Canvas(videoFrameBitmap)
val paint = Paint().apply {
val colorMatrix = ColorMatrix().apply {
// map the saturation of the color to grayscale
setSaturation(0f)
}
colorFilter = ColorMatrixColorFilter(colorMatrix)
}
canvas.drawBitmap(videoFrameBitmap, 0f, 0f, paint)
}
}
Binary file added dogfooding/assets/bg1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dogfooding/assets/bg2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added dogfooding/assets/bg3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
63 changes: 50 additions & 13 deletions dogfooding/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,38 +1,75 @@
import UIKit
import Flutter
import UIKit
import stream_video_flutter
import stream_video_push_notification
import stream_webrtc_flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {

private let CHANNEL = "io.getstream.video.flutter.dogfooding.channel"

override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)

// Register for push notifications.
StreamVideoPKDelegateManager.shared.registerForPushNotifications()
UNUserNotificationCenter.current().delegate = self


let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(
name: CHANNEL, binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler { [weak self] (call, result) in
self?.handleMethodCall(call: call, result: result)
}

return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}

// This method will be called when notification is received
override func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
override func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) ->
Void
) {
let streamDict = notification.request.content.userInfo["stream"] as? [String: Any]
if(streamDict?["sender"] as? String != "stream.video") {
if streamDict?["sender"] as? String != "stream.video" {
return completionHandler([])
}

if #available(iOS 14.0, *) {
completionHandler([.list, .banner, .sound])
} else {
completionHandler([.alert])
}
}



func handleMethodCall(call: FlutterMethodCall, result: @escaping FlutterResult) {
if call.method == "registerGreyscaleEffect" {
ProcessorProvider.addProcessor(GrayScaleVideoFrameProcessor(), forName: "grayscale")
result(nil)
} else {
result(FlutterMethodNotImplemented)
}
}
}

final class GrayScaleVideoFrameProcessor: VideoFilter {
@available(*, unavailable)
override public init(
filter: @escaping (Input) -> CIImage
) { fatalError() }
init() {
super.init(
filter: { input in
let filter = CIFilter(name: "CIPhotoEffectMono")
filter?.setValue(input.originalImage, forKey: kCIInputImageKey)
let outputImage: CIImage = filter?.outputImage ?? input.originalImage
return outputImage
}
)
}
}
1 change: 1 addition & 0 deletions dogfooding/ios/fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ platform :ios do
changelog: 'Lots of amazing new features to test out!',
reject_build_waiting_for_review: false,
skip_waiting_for_build_processing: false,
beta_app_description: 'Beta build of Stream Video Flutter Dogfoofing app for internal and external testers',
)
rescue Exception => e
if e.message.include? 'Another build is in review'
Expand Down
10 changes: 10 additions & 0 deletions dogfooding/lib/dogfooding_app_channel.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:flutter/services.dart';

class DogfoodingAppChannel {
static const platform =
MethodChannel('io.getstream.video.flutter.dogfooding.channel');

Future<void> registerGreyscaleEffect() async {
await platform.invokeMethod('registerGreyscaleEffect');
}
}
Loading

0 comments on commit 06ab616

Please sign in to comment.