Slide 1

Slide 1 text

NBD04Ծ૝ΧϝϥʮςϩοϓΧϜʯ ࣮૷ํ๏ͱͦͷઌ J04%$+BQBO ෰෦ஐ!TINEFWFMPQ

Slide 2

Slide 2 text

Ծ૝Χϝϥ 4OBQ$BNFSB NNINN

Slide 3

Slide 3 text

͜Ε͸ָ͍͠ʂ

Slide 4

Slide 4 text

ϓϩάϥϚͳΒҰ౓͸

Slide 5

Slide 5 text

ࣗ࡞ͨ͘͠ͳΓ·͢ΑͶʂ

Slide 6

Slide 6 text

ྑ͍͓஌Βͤ

Slide 7

Slide 7 text

ͳΜͱ

Slide 8

Slide 8 text

4XJGUͷΈͰ࣮૷Մೳʂ

Slide 9

Slide 9 text

5XJUUFSͰ(8όʔνϟϧΧϝϥ࡞੒νϟϨϯδͰ࡞੒աఔπΠʔτ͍ͯ͠·͢

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

ߏ੒ཁૉ

Slide 13

Slide 13 text

ߏ੒ཁૉ ɹ$PSF.FEJB*0%"-1MVHJO ɹίϯτϩʔϥΞϓϦ

Slide 14

Slide 14 text

$PSF.FEJB*0%"- 1MVHJO ίϯτϩʔϥΞϓϦ /41BTUFCPBSE -JCSBSZ$PSF.FEJB*01MVH*OT%"- Ծ૝Χϝϥͷ࣮ମ 6*Λ࣋ͨͳ͍1MVHJOʹ ஋Λ౉͢ΞϓϦ

Slide 15

Slide 15 text

ϓϩδΣΫτ࡞੒ͱΠϯλʔϑΣΠε࣮૷ $PSF.FEJB*0%"-1MVHJO

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

ࣗ෼Ͱࢦఆ͢Δ*%஋ɻ66*%ͳͲઃఆ

Slide 20

Slide 20 text

ΤϯτϦʔϙΠϯτGVODUJPO໊

Slide 21

Slide 21 text

Ծ૝Χϝϥ1MVH*Oݻఆ஋ ઌड़ͷ66*%஋

Slide 22

Slide 22 text

import Foundation import CoreMediaIO @_cdecl("VirtualCameraSampleMain") func VirtualCameraSampleMain(allocator: CFAllocator, requestedTypeUUID: CFUUID) -> CMIOHardwarePlugInRef { return pluginRef } Main.swift

Slide 23

Slide 23 text

import Foundation import CoreMediaIO @_cdecl("VirtualCameraSampleMain") func VirtualCameraSampleMain(allocator: CFAllocator, requestedTypeUUID: CFUUID) -> CMIOHardwarePlugInRef { return pluginRef } Main.swift ΤϯτϦʔϙΠϯτ ΠϯλʔϑΣΠεͷࢀরΛฦ٫

Slide 24

Slide 24 text

let pluginRef: CMIOHardwarePlugInRef = { let interfacePtr = UnsafeMutablePointer.allocate(capacity: 1) interfacePtr.pointee = createPluginInterface() let pluginRef = CMIOHardwarePlugInRef.allocate(capacity: 1) pluginRef.pointee = interfacePtr return pluginRef }() PluginInterface.swift (ൈਮ)

Slide 25

Slide 25 text

let pluginRef: CMIOHardwarePlugInRef = { let interfacePtr = UnsafeMutablePointer.allocate(capacity: 1) interfacePtr.pointee = createPluginInterface() let pluginRef = CMIOHardwarePlugInRef.allocate(capacity: 1) pluginRef.pointee = interfacePtr return pluginRef }() PluginInterface.swift (ൈਮ) ΠϯλʔϑΣΠεࢀরΛฦ٫

Slide 26

Slide 26 text

private func createPluginInterface() -> CMIOHardwarePlugInInterface { return CMIOHardwarePlugInInterface( _reserved: nil, QueryInterface: QueryInterface, AddRef: AddRef, Release: Release, Initialize: Initialize, InitializeWithObjectID: InitializeWithObjectID, Teardown: Teardown, ObjectShow: ObjectShow, ObjectHasProperty: ObjectHasProperty, ObjectIsPropertySettable: ObjectIsPropertySettable, ObjectGetPropertyDataSize: ObjectGetPropertyDataSize, ObjectGetPropertyData: ObjectGetPropertyData, ObjectSetPropertyData: ObjectSetPropertyData, DeviceSuspend: DeviceSuspend, DeviceResume: DeviceResume, DeviceStartStream: DeviceStartStream, DeviceStopStream: DeviceStopStream, DeviceProcessAVCCommand: DeviceProcessAVCCommand, DeviceProcessRS422Command: DeviceProcessRS422Command, StreamCopyBufferQueue: StreamCopyBufferQueue, StreamDeckPlay: StreamDeckPlay, StreamDeckStop: StreamDeckStop, StreamDeckJog: StreamDeckJog, StreamDeckCueTo: StreamDeckCueTo) } PluginInterface.swift (ൈਮ)

Slide 27

Slide 27 text

private func createPluginInterface() -> CMIOHardwarePlugInInterface { return CMIOHardwarePlugInInterface( _reserved: nil, QueryInterface: QueryInterface, AddRef: AddRef, Release: Release, Initialize: Initialize, InitializeWithObjectID: InitializeWithObjectID, Teardown: Teardown, ObjectShow: ObjectShow, ObjectHasProperty: ObjectHasProperty, ObjectIsPropertySettable: ObjectIsPropertySettable, ObjectGetPropertyDataSize: ObjectGetPropertyDataSize, ObjectGetPropertyData: ObjectGetPropertyData, ObjectSetPropertyData: ObjectSetPropertyData, DeviceSuspend: DeviceSuspend, DeviceResume: DeviceResume, DeviceStartStream: DeviceStartStream, DeviceStopStream: DeviceStopStream, DeviceProcessAVCCommand: DeviceProcessAVCCommand, DeviceProcessRS422Command: DeviceProcessRS422Command, StreamCopyBufferQueue: StreamCopyBufferQueue, StreamDeckPlay: StreamDeckPlay, StreamDeckStop: StreamDeckStop, StreamDeckJog: StreamDeckJog, StreamDeckCueTo: StreamDeckCueTo) } PluginInterface.swift (ൈਮ) ΠϯλʔϑΣΠε͕ظ଴͢Δ΋ͷΛฦ٫

Slide 28

Slide 28 text

PluginInterface.swift (ൈਮ) ৄࡉ͸ιʔεࢀর

Slide 29

Slide 29 text

Χϝϥө૾औಘͱग़ྗ

Slide 30

Slide 30 text

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, ɹɹɹɹɹɹɹɹɹɹɹ ɹɹfrom connection: AVCaptureConnection) { if output == cameraCapture.output { guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return } let cameraImage = CIImage(cvImageBuffer: imageBuffer) let compositedImage = compose(bgImage: cameraImage, overlayImage: self.textImage) var pixelBuffer: CVPixelBuffer? _ = CVPixelBufferCreate( kCFAllocatorDefault, Int(compositedImage.extent.size.width), Int(compositedImage.extent.height), kCVPixelFormatType_32BGRA, self.CVPixelBufferCreateOptions as CFDictionary, &pixelBuffer ) if let pixelBuffer = pixelBuffer { context.render(compositedImage, to: pixelBuffer) delegate?.videoComposer(self, didComposeImageBuffer: pixelBuffer) } } } VideoComposer.swift (ൈਮ)

Slide 31

Slide 31 text

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, ɹɹɹɹɹɹɹɹɹɹɹ ɹɹfrom connection: AVCaptureConnection) { if output == cameraCapture.output { guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return } let cameraImage = CIImage(cvImageBuffer: imageBuffer) let compositedImage = compose(bgImage: cameraImage, overlayImage: self.textImage) var pixelBuffer: CVPixelBuffer? _ = CVPixelBufferCreate( kCFAllocatorDefault, Int(compositedImage.extent.size.width), Int(compositedImage.extent.height), kCVPixelFormatType_32BGRA, self.CVPixelBufferCreateOptions as CFDictionary, &pixelBuffer ) if let pixelBuffer = pixelBuffer { context.render(compositedImage, to: pixelBuffer) delegate?.videoComposer(self, didComposeImageBuffer: pixelBuffer) } } } VideoComposer.swift (ൈਮ) ผ్ੜ੒ͨ͠ΦʔόʔϨΠςΩετը૾ͱ߹੒ EFMFHBUFܦ༝ͰQJYFM#V⒎FSΛ౉͢

Slide 32

Slide 32 text

private func enqueueBuffer() { (தུ) var sampleBufferUnmanaged: Unmanaged? = nil error = CMIOSampleBufferCreateForImageBuffer( kCFAllocatorDefault, pixelBuffer, formatDescription, &timing, sequenceNumber, UInt32(kCMIOSampleBufferNoDiscontinuities), &sampleBufferUnmanaged ) guard error == noErr else { log("CMIOSampleBufferCreateForImageBuffer Error: \(error)") return } CMSimpleQueueEnqueue(queue, element: sampleBufferUnmanaged!.toOpaque()) queueAlteredProc?(objectID, sampleBufferUnmanaged!.toOpaque(), queueAlteredRefCon) sequenceNumber += 1 } Stream.swift (ൈਮ)

Slide 33

Slide 33 text

private func enqueueBuffer() { (தུ) var sampleBufferUnmanaged: Unmanaged? = nil error = CMIOSampleBufferCreateForImageBuffer( kCFAllocatorDefault, pixelBuffer, formatDescription, &timing, sequenceNumber, UInt32(kCMIOSampleBufferNoDiscontinuities), &sampleBufferUnmanaged ) guard error == noErr else { log("CMIOSampleBufferCreateForImageBuffer Error: \(error)") return } CMSimpleQueueEnqueue(queue, element: sampleBufferUnmanaged!.toOpaque()) queueAlteredProc?(objectID, sampleBufferUnmanaged!.toOpaque(), queueAlteredRefCon) sequenceNumber += 1 } Stream.swift (ൈਮ) QJYFM#V⒎FS͔Βੜ੒ͨ͠ $.4BNQMF#V⒎FSΛRVFVFʹ௥Ճ

Slide 34

Slide 34 text

QMVHJOϑΝΠϧͷ഑ஔ

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

-JCSBSZ$PSF.FEJB*01MVH*OT%"-

Slide 37

Slide 37 text

දࣔ͞Εͨʂ

Slide 38

Slide 38 text

ίϯτϩʔϥΞϓϦ

Slide 39

Slide 39 text

$PSF.FEJB*0%"- 1MVHJO ίϯτϩʔϥΞϓϦ /41BTUFCPBSE -JCSBSZ$PSF.FEJB*01MVH*OT%"- Ծ૝Χϝϥͷ࣮ମ 6*Λ࣋ͨͳ͍1MVHJOʹ ஋Λ౉͢ΞϓϦ

Slide 40

Slide 40 text

1BTUFCPBSEʹ஋Λஔ͘໾ׂ

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

/41BTUFCPBSEͰσʔλڞ༗

Slide 43

Slide 43 text

extension NSPasteboard.Name { static let main = NSPasteboard.Name(Config.mainAppBundleIdentifier) } extension NSPasteboard.PasteboardType { static let plain = NSPasteboard.PasteboardType(rawValue: "public.utf8-plain-text") } class SettingsPasteboard { static let shared = SettingsPasteboard() open var settings = [String: Any]() open func current() -> [String: Any] { let pasteboard = NSPasteboard(name: .main) if let element = pasteboard.pasteboardItems?.last, let str = element.string(forType: .plain), let data = str.data(using: .utf8) { do { let json = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as! [String: Any] settings = json } catch { print("can't convert json") } } return settings } open func update() { let jsonStr = stringify(json: settings) let pasteboard = NSPasteboard(name: .main) pasteboard.declareTypes([.string], owner: nil) pasteboard.setString(jsonStr, forType: .string) } ... } SettingsPasteboard.swift (ൈਮ)

Slide 44

Slide 44 text

extension NSPasteboard.Name { static let main = NSPasteboard.Name(Config.mainAppBundleIdentifier) } extension NSPasteboard.PasteboardType { static let plain = NSPasteboard.PasteboardType(rawValue: "public.utf8-plain-text") } class SettingsPasteboard { static let shared = SettingsPasteboard() open var settings = [String: Any]() open func current() -> [String: Any] { let pasteboard = NSPasteboard(name: .main) if let element = pasteboard.pasteboardItems?.last, let str = element.string(forType: .plain), let data = str.data(using: .utf8) { do { let json = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as! [String: Any] settings = json } catch { print("can't convert json") } } return settings } open func update() { let jsonStr = stringify(json: settings) let pasteboard = NSPasteboard(name: .main) pasteboard.declareTypes([.string], owner: nil) pasteboard.setString(jsonStr, forType: .string) } ... } SettingsPasteboard.swift (ൈਮ)

Slide 45

Slide 45 text

$PSF.FEJB*0%"- 1MVHJO ίϯτϩʔϥΞϓϦ /41BTUFCPBSE -JCSBSZ$PSF.FEJB*01MVH*OT%"- Ծ૝Χϝϥͷ࣮ମ 6*Λ࣋ͨͳ͍1MVHJOʹ ஋Λ౉͢ΞϓϦ

Slide 46

Slide 46 text

׬੒

Slide 47

Slide 47 text

ίϯτϩʔϥΞϓϦ͔Β஋Λૹ৴

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

࣮૷ํ๏ͱʮͦͷઌʯ

Slide 52

Slide 52 text

'BDFUJNFDBNFSB BVEJPJOQVU TIBEFSF⒎FDU "1* LFZCPBSEJOQVU ,FZOPUF FUD ֎෦ Ծ૝Χϝϥ ೖग़ྗՃ޻ػߏ ݱ࣮֦ுͱͯ͠ͷԾ૝Χϝϥ ֤छೖྗ

Slide 53

Slide 53 text

ϚΠϯυϚοϓ

Slide 54

Slide 54 text

δΣωϨΠςΟϒදݱ

Slide 55

Slide 55 text

ελϯϓϦΞΫγϣϯ

Slide 56

Slide 56 text

Ի੠ೝࣝͱ຋༁

Slide 57

Slide 57 text

ݱ࣮֦ுͱͯ͠ͷԾ૝Χϝϥ

Slide 58

Slide 58 text

ࢀߟ IUUQTEFWFMPQFSBQQMFDPNMJCSBSZBSDIJWFTBNQMFDPEF$PSF.FEJB*0*OUSPEVDUJPO*OUSPIUNM IUUQTHJUIVCDPNKPIOCPJMFTDPSFNFEJBJPEBMNJOJNBMFYBNQMF IUUQTHJUIVCDPNTFBODIBT4JNQMF%"-1MVHJO IUUQTTQFBLFSEFDLDPNLJTIJLBXBLBUTVNJWJSUVBMXFCDBNFSBXP[VPSPV

Slide 59

Slide 59 text

5XJUUFSͰ࠷৽৘ใൃ৴த !TINEFWFMPQ Ծ૝Χϝϥ࣮૷αϯϓϧ IUUQTHJUIVCDPNTBUPTIJ7JSUVBM$BNFSB4BNQMF