Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ライブ配信アプリのアイテム再生をMetalで実装する事になった話
Search
noppefoxwolf
September 02, 2018
Technology
12k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ライブ配信アプリのアイテム再生をMetalで実装する事になった話
noppefoxwolf
September 02, 2018
More Decks by noppefoxwolf
See All by noppefoxwolf
High performance GIF playback/iOSDC25
noppefoxwolf
1
590
Spice up your notifications/try!Swift25
noppefoxwolf
3
830
iOSの隠されたAPIを解明し、開発効率を向上させる方法/iOSDC24
noppefoxwolf
2
1.3k
今から理解するApp Intentエコシステム/WWDC24Recap
noppefoxwolf
0
71
既存アプリをvisionOS対応してリリースした話/visionOS LT vol5
noppefoxwolf
0
230
UIのブラックボックスを探る/iOSDC23
noppefoxwolf
3
5.1k
CoreGraphicsでドット絵を描こう/iOSDC22
noppefoxwolf
0
3.2k
ランタイムデバッグのススメ/iOSDC21
noppefoxwolf
1
5.6k
google/mediapipe で始めるARアプリ開発/iOSDC2020
noppefoxwolf
1
1.7k
Other Decks in Technology
See All in Technology
Deep Data Security 機能解説
oracle4engineer
PRO
2
230
元・セキュリティ学習経験0大学生による業務紹介 / An Introduction to the Job by a Former College Student with Zero Security Training Experience
nttcom
0
870
はてなのサービス基盤を支える Kubernetes《足腰》
masayoshimaezawa
0
160
40代で“やっとエンジニアになれた”――閉じた学びを開き、空の青さを知る / 20260628 Naoki Takahashi
shift_evolve
PRO
4
1.1k
スタートアップにAmazon EKSは早すぎる? マルチプロダクト戦略を加速する Platform Engineeringの実践 / Is Amazon EKS Too Soon for Startups? Practical Platform Engineering to Accelerate a Multi-Product Strategy
elmodev09
1
1.9k
10年間のブログ発信を振り返って見えたWebアプリケーションエンジニアとしての軌跡
stefafafan
0
190
AIチャット検索改善の3週間
kworkdev
PRO
2
200
AIペネトレーションテスト・ セキュリティ検証「AgenticSec」紹介資料
laysakura
2
7.7k
“詰む”前に仕組みを作れ 〜技術の波に溺れないためのキャッチアップ術〜
takasyou
7
4.2k
Microsoft のサポートとフィードバック総まとめ
murachiakira
PRO
0
110
【FinOps】データドリブンな意思決定を目指して
z63d
2
480
MySQL & MySQL HeatWave Report - June 2026
freshdaz
0
190
Featured
See All Featured
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
How to build a perfect <img>
jonoalderson
1
5.7k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
540
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
400
Un-Boring Meetings
codingconduct
0
320
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
65
56k
My Coaching Mixtape
mlcsv
0
150
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.7k
Tell your own story through comics
letsgokoyo
1
980
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
How STYLIGHT went responsive
nonsquared
100
6.2k
Transcript
ϥΠϒ৴ΞϓϦͷΞΠςϜ࠶ੜΛ .FUBMͰ࣮͢Δࣄʹͳͬͨ J04%$+BQBO5SBDL# JPTEDC TIBSF
OPQQF ! גࣜձࣾσΟʔɾΤψɾΤʔ " ͖ͭͶ͔Θ͍͍ # ΞϓϦ։ൃ̎̌̍̌ʙ JPTEDC TIBSF
ࠓͷ ɾ1PDPDIBͷհ ɾΞΠςϜΤϑΣΫτͷ࠶ੜख๏ ɾ࠶ੜख๏ͷ࣮ൺֱ ɾ·ͱΊ JPTEDC TIBSF
ϥΠϒ৴ΞϓϦ1PDPDIBͷհ JPTEDC TIBSF
1PDPDIB w ϥΠϒ৴ΞϓϦ w ʙ w ߴੑೳͳඒഽɾඒإϑΟϧλʔ w ΞΠςϜʹΑΔίϛϡχέʔ γϣϯ
JPTEDC TIBSF
ΞΠςϜͷΤϑΣΫτͷ࠶ੜख๏ JPTEDC TIBSF
JPTEDC TIBSF
ΞΠςϜͷΤϑΣΫτ w º w GQT w ಁա৭͋Γ w ඵ JPTEDC
TIBSF
ΞΠςϜͷΤϑΣΫτΛJ04্Ͱ࠶ੜ͢Δʹ JPTEDC TIBSF
ᶃ"71MBZFSͰ࠶ੜ͢Δ let url = Bundle.main.url(forResource: "item_effect", withExtension: "mov")! let asset
= AVURLAsset(url: url) let item = AVPlayerItem(asset: asset) let player = AVPlayer(playerItem: item) let playerLayer = AVPlayerLayer(player: player) playerLayer.backgroundColor = UIColor.clear.cgColor view.layer.addSubLayer(playerLayer) player.play() JPTEDC TIBSF
"71MBZFS-BZFSͰɺಁաใͷ ͋ΔಈըΛѻ͏ࣄ͕Ͱ͖ͳ͍ɻ *NQPSUBOU 5IFWBMVFPGBQMBZFSMBZFS`T JOIFSJUFEDPOUFOUTQSPQFSUZJT PQBRVFBOETIPVMEOPUCF VTFE "71-BZFS-BZFSυΩϡϝ ϯτΑΓ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPO
BWGPVOEBUJPOBWQMBZFSMBZFS JPTEDC TIBSF
ᶄ6**NBHF7JFXͰ࠶ੜ͢Δ let imageView = UIImageView() let images = (0...300).compactMap({ UIImage(named:
"\($0).png") }) imageView.animationImages = images imageView.startAnimating() JPTEDC TIBSF
ᶄ6**NBHF7JFXͰ࠶ੜ͢Δ $ ffmpeg -i input.mov images/output_%04d.png JPTEDC TIBSF
ᶄ6**NBHF7JFXͰ࠶ੜ͢Δ $ ffmpeg -i input.mov images/output_%04d.png $ du -sh ./images
302M ./images ☺ JPTEDC TIBSF
ᶄ6**NBHF7JFXͰ࠶ੜ͢Δ JPTEDC TIBSF
ᶄ6**NBHF7JFXͰ࠶ੜ͢Δ Message from debugger: Terminated due to memory issue ͰΫϥογϡ
JPTEDC TIBSF
ݕূ͔Β͔ͬͨ̎ͭͷ՝ײ w ಈըࣗମͷ༰ྔ w ࠶ੜύϑΥʔϚϯε JPTEDC TIBSF
ಈըࣗମͷ༰ྔ ඇѹॖNPWϑΝΠϧ .# ࿈൪1/(ϑΝΠϧ .# ѹॖ͢Δඞཁ͕͋Δ JPTEDC TIBSF
ϑΝΠϧͷѹॖͰඞਢͳཁ݅ w ಁաใΛ͍࣋ͬͯΔ w GQTΛམͱ͞ͳ͍ w ॎԣͷαΠζΛมߋ͠ͳ͍ JPTEDC TIBSF
ϑΥʔϚοτ ಁա ѹॖ σίʔυෛՙ BQOH ˓ .# º XFCQ ˓
.# º TG XFCN ˓ ,# º NQ º .# ˓ I "1/(༰ྔͷ࣌Ͱෆ࠾༻ͩͬͨͷͰະଌఆɻ8&#.σίʔμ͕ແͦ͞͏ͳͷͰະଌఆ WQXJUIBMQIB JPTEDC TIBSF
NQΛͳΜͱ͔ಁաʹରԠग़དྷͳ͍͔ ͜͜ͰɺੲήʔϜΛ࡞͍ͬͯͨ࣌ͷ͜ͱΛࢥ͍ग़͢ JPTEDC TIBSF
JPTEDC TIBSF
JPTEDC TIBSF
ಁա߹ͱඳը ͔͜͜ΒɺಁաಈըϓϨʔϠʔΛ࣮͍ͯ͘͠ w $PSF*NBHF w 0QFO(-&4 w .FUBM ΛͦΕͧΕͬͯ࡞ͬͨ݁ՌΛൺֱ͠·͢ɻ JPTEDC
TIBSF
ಁա߹ͱඳը w º w GQT w ಁա৭ͳ͠ w ඵ w
NQ JPTEDC TIBSF
$*'JMUFSΛͬͨ߹ $*'JMUFS J04 Ҏ্ͷϓϦηοτϑΟϧλ $16͔(16Ͱॲཧ JPTEDC TIBSF
$*'JMUFSΛͬͨ߹ $*'JMUFS J04 Ҏ্ͷϓϦηοτϑΟϧλ $16͔(16Ͱॲཧ $*#MFOE8JUI.BTL ΞϧϑΝͷը૾Λͬͯಁա IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPO DPSFJNBHFDJpMUFS JPTEDC
TIBSF
$*'JMUFSΛͬͨ߹ let filter = CIFilter(name: "CIBlendWithMask")! filter.setValue(baseCIImage, forKey: kCIInputImageKey) filter.setValue(alphaCIImage,
forKey: kCIInputMaskImageKey) let filteredImage = filter.outputImage! let image = UIImage(ciImage: filteredImage) imageView.image = image JPTEDC TIBSF
J1IPOFDGQT JPTEDC TIBSF
0QFO(-&4Λͬͨ߹ͱඳը $"&"(--BZFS J04r (16Ͱॲཧ JPTEDC TIBSF
0QFO(-&45*14 JPTEDC TIBSF
0QFO(-&45*14 &"(-$POUFYU ςΫενϟΤϥʔঢ়ଶͳͲΛཧ JPTEDC TIBSF
0QFO(-&45*14 // ͲͷίϯςΩετͰಈ࡞͢Δ͔ෆఆ glDisable(GLenum(GL_DEPTH_TEST)) // ར༻͢ΔcontextΛઃఆ EAGLContext.setCurrent(context) // ↑Ͱࢦఆͨ͠contextͰ࣮ߦ͞ΕΔ glDisable(GLenum(GL_DEPTH_TEST))
JPTEDC TIBSF
0QFO(-&45*14 glGetError() ྫɿGL_INVALID_ENUM ແޮͳFOVNΛࢦఆ͍ͯ͠Δɻ JPTEDC TIBSF
0QFO(-&45*14 9DPEFͰϒϨʔΫϙΠϯτΛࠐΉ͜ͱՄ JPTEDC TIBSF
0QFO(-&4Λͬͨ߹ͱඳը $PSF*NBHF 0QFO(-&4 $**NBHF ςΫενϟ $*'JMUFS ϑϥάϝϯτγΣʔμ 6**NBHF7JFX Ϩϯμϥ $"&"(--BZFS
JPTEDC TIBSF
0QFO(-&4Λͬͨ߹ͱඳը varying lowp vec2 textureCoordinate; uniform sampler2D videoFrame; void main()
{ // ϕʔεͷ৭ͷx lowp float x = textureCoordinate.x / 2.0; // ϕʔε৭ͷऔಘ lowp vec2 baseCoord = vec2(x, textureCoordinate.y); lowp vec4 baseColor = texture2D(videoFrame, baseCoord); // alphaͷऔಘ lowp vec2 alphaCoord = vec2(x + 0.5, textureCoordinate.y); lowp vec4 alphaColor = texture2D(videoFrame, alphaCoord); // RGBϕʔε৭ɺAalphaΛར༻͢Δ gl_FragColor = vec4(baseColor.r, baseColor.g, baseColor.b, alphaColor.r); } JPTEDC TIBSF
HM@'SBH$PMPSWFD CBTF$PMPSS CBTF$PMPSH CBTF$PMPSC BMQIB$PMPSS JPTEDC TIBSF
0QFO(-&4Λͬͨ߹ͱඳը J1IPOFD㲈GQT JPTEDC TIBSF
͔͠͠ʜ JPTEDC TIBSF
JPTEDC TIBSF
88%$Ͱಥવͷ%FQSFDBUFEɻ ϥΠϒ৴ΞϓϦͷΞΠςϜ࠶ੜΛ.FUBMͰ࣮͢Δ ࣄʹͳͬͨ ແࣄλΠτϧճऩ ☺ JPTEDC TIBSF
.FUBMͰॻ͍ͯΈ·ͨ͠ JPTEDC TIBSF
.FUBMͷར w γΣʔμʔͷࣄલίϯύΠϧ w (16$16ͷڞ༗ϝϞϦۭؒ w (16ͷ໋ྩΛ·ͱΊͯૹΕΔ FUD %ΛΰϦΰϦʹ͏ਓ͘Β͍͔͠تͳ͍ʜ JPTEDC
TIBSF
.FUBMΛͬͯΈͯײͨ͡ར (16ϓϩάϥϛϯάॳ৺ऀʹ༏͍͠.FUBM w (16Λ৮Δ্Ͱॻ͖͍͢*' w ཧղΛਂΊΔ্ͰॏཁͳσόοΨʔ JPTEDC TIBSF
.FUBMΛͬͯΈͯײͨ͡ར let desc = MTLRenderPipelineDescriptor() desc.vertexFunction = library.makeFunction(name: vertexFunctionName) desc.fragmentFunction
= library.makeFunction(name: fragmentFunctionName) desc.colorAttachments[0].pixelFormat = pixelFormat 4XJGU0CK$Ͱॻ͖͍͢Ϟμϯͳ*' ίϯύΠϧ࣌ʹ͕ൃ͍֮͢͠ɻ JPTEDC TIBSF
.FUBMΛͬͯΈͯײͨ͡ར γΣʔμʔͷΤϥʔίϯύΠϧ࣌ʹڭ͑ͯ͘ΕΔ JPTEDC TIBSF
.FUBMΛͬͯΈͯײͨ͡ར w (16Λ৮Δ্Ͱॻ͖͍͢*' w ཧղΛਂΊΔ্ͰॏཁͳσόοΨʔ σόοΨʔʹ͍ͭͯ͜ͷޙհ͠·͢ɻ JPTEDC TIBSF
.FUBMͰॻ͍ͯΈ·ͨ͠ ͜ΕΒͷརΛ౿·͑ͯɺ.FUBMͰ ॻ͍ͯΈ·ͨ͠ɻ అ͞Μͷ.FUBMೖ͕ಡΈ͘͢ ͓ͯ͢͢ΊͰ͢ɻ JPTEDC TIBSF
J1IPOFT㲈GQT JPTEDC TIBSF
.FUBMͰॻ͍ͯΈ·ͨ͠ (16'SBNF$BQUVSF w ΧϝϥϚʔΫͷϘλϯ JPTEDC TIBSF
JPTEDC TIBSF
֤ςΫενϟΛQOHUJ⒎Ͱॻ͖ग़͢ࣄͰ͖·͢ɻ JPTEDC TIBSF
JPTEDC TIBSF
0QFO(-&4൛ͷ(16'SBNF$BQUSVF*OTUSVNFOUT ɺࣗͷڥͰಈ͔ͳ͘ͳ͍ͬͯ·ͨ͠ JPTEDC TIBSF
.FUBMͷ*OTUSVNFOUTવར༻Ͱ͖·͢ɻ JPTEDC TIBSF
·ͱΊ JPTEDC TIBSF
ΞϓϦΤϯδχΞ.FUBM৮Δ͖͔ w ࢥͬͨΑΓ͘͠ແ͘ɺཧղ͍͢͠ੈք w "3,JU$PSF.-ʹܨ͕Δٕज़ JPTEDC TIBSF
.FUBMͰ࣮͢Δඞཁ͋Δͷ͔ w ը૾ฤूͳΒ$*'JMUFSΛ·ͣݕ౼ w .FUBMͷσϝϦοτΛཧղ্ͨ͠Ͱ࠾༻͢Δ͖ JPTEDC TIBSF
.FUBMͰ࣮͢Δ্Ͱͷҙ w J04ະຬͷσόΠεʹ.FUBMඇରԠͷ͕͋Γ ·͢ w γϛϡϨʔλ.FUBMඇରԠͰ͢ MTLCreateSystemDefaultDevice() != nil JPTEDC
TIBSF
.FUBMͰ࣮͢Δ্Ͱͷҙ γϛϡϨʔλͰϏϧυͰ͖ͳ͍ࣄ͋Γ·͢ Ұ෦ͷϔϧύʔγϛϡϨʔλ4%,ʹؚ·Ε·ͤΜ w $".FUBM%SBXBCMF w $".FUBM-BZFS IUUQTHJTUHJUIVCDPNOPQQFGPYXPMGGBBBDCCEECG JPTEDC TIBSF
1PDPDIBͰ .FUBMͰ࣮͠·͕ͨ͠ʜ w ࠓ0QFO(-&4൛Λ͍ͬͯ·͢ w J04αϙʔτ͢ΔͨΊ w γϛϡϨʔλ͍ͬͯΔ 0QFO(-&4͕ഇࢭ͞ΕͨΒͲ͏͢Δͷʁ ˠͦͷࠒʹJ04ରԠ͠ͳ͍ͩΖ͏͠ɺγϛϡϨʔλͰ.FUBM͕ಈ͘Α͏ʹ
ͳ͍ͬͯ·͢ʂʂʢଟͶʣ JPTEDC TIBSF
4PVSDF$PEF ಁաॲཧΛࢪͯ͠࠶ੜ͢ΔϓϨʔϠʔϥΠϒϥϦΛ࡞͍ͬͯ·͢ JPTEDC TIBSF
4PVSDF$PEF w OPQQFGPYXPMG,JUTVOFCJ w OPQQFGPYXPMG,
[email protected]
! " !
JPTEDC TIBSF
! ͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ "TLUIFTQFBLFS %F/"4QFBLFS-PVOHF JPTEDC TIBSF