AV Foundation Layer Instruction

Download as pdf or txt
Download as pdf or txt
You are on page 1of 154
At a glance
Powered by AI
The key takeaways are about custom video compositing and debugging compositions in AV Foundation.

Some of the existing capabilities of AV Foundation mentioned are video editing, temporal composition, video composition and audio mixing.

Custom video compositing can be achieved in AV Foundation by creating custom video compositors and using AVVideoComposition instructions to blend or transform pixels from multiple video sources.

Advanced Editing

with AV Foundation

Session 612
Scott G. Johnston
AV Foundation Engineer

These are confidential sessions—please refrain from streaming, blogging, or taking pictures
Agenda

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Agenda

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Existing Architecture
AV Foundation editing today
• Available since iOS 4.0
and OS X Lion
• Used in video editing apps
from Apple and in the store
• Video editing
■ Temporal composition

■ Video composition

■ Audio mixing
Possible Today
Wipes, Dissolves, Transforms,…
New Opportunities
OpenGL and Everything Else
Custom Video Compositor
What Is a Video Compositor?

• Unit of video mixing code


• Receives multiple source frames
• Blends or transforms pixels
• Delivers single output frame
• Part of the composition architecture
Composition Model
AVComposition
Composition Model
AVComposition

A
B
Composition Model
AVComposition

AVVideoComposition
A B
A B
B A
A
Composition Model
AVComposition

AVVideoComposition
A B
A B
B A
A
Composition Model
AVComposition

AVVideoComposition
A B
A B
B A
A
Composition Model
AVComposition

AVVideoComposition
A B
A B
B A
A
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction


Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction


Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Simple mix
1 source track
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Complex mix
>1 source tracks
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Compositor
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Compositor
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Compositor
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Compositor
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Compositor
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Compositor
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Compositor
Video Instructions
AVVideoComposition
A B
A B
B A
A

Instruction Inst. Inst. Inst. Instruction

Compositor
Compositor
Compositor
Video Compositor

Compositor
Video Compositor

Instruction

Compositor
Video Compositor

Instruction

Compositor
Video Compositor

Instruction

Compositor
Video Compositor

Instruction
Instruction
Opacity Ramp 1 to 0
Compositor
Agenda

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Video Compositor

Instruction

Opacity Ramp 1 to 0
Built-In
Compositor
Video Compositor

Instruction

Opacity Ramp 1 to 0
Built-In
Compositor
Video Compositor

Instruction

Opacity Ramp 1 to 0
Built-in
Compositor
Custom Video Compositor

Instruction

Opacity Ramp 1 to 0
Your
Built-in
Code
Compositor
Here
Custom Video Compositor

Instruction

Opacity Ramp 1 to 0
Your
Code
Here
Custom Video Compositor

Instruction

Opacity
Your Ramp
Mixing 1 to 0
Parameters
Your
Code
Here
Custom Video Compositor

Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor

Request

Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor

Request

@protocol AVVideoCompositing
Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor
AVAsynchronousVideoCompositionRequest

Request

@protocol AVVideoCompositing
Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor
AVAsynchronousVideoCompositionRequest

Request
@protocol AVVideoCompositionInstruction
@protocol AVVideoCompositing
Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor

Request

Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor

Request

startVideoCompositionRequest:
Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor

Request

startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor

Request finishWithError:
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor

Request finishWithError:
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Your Mixing Parameters


Your
Code
Here
Custom Video Compositor
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here
Custom Video Compositor
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format


YUV 8-bit 4:2:0
YUV 8-bit 4:4:4
YUV 10-bit 4:2:2
YUV 10-bit 4:4:4
RGB 24-bit
BGRA 32-bit
BGR 24-bit
ARGB 32-bit
ABGR 32-bit
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format


YUV 8-bit 4:2:0
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format


YUV 8-bit 4:2:0

(NSDictionary *) sourcePixelBufferAttributes
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format


YUV 8-bit 4:2:0

(NSDictionary *) sourcePixelBufferAttributes

kCVPixelFormatType_32BGRA,...
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format


kCVPixelFormatType_32BGRA,...

(NSDictionary *) sourcePixelBufferAttributes
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format


Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format


BGRA 32-bit
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format


BGRA 32-bit
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format


BGRA 32-bit
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Source Pixel Format Output Pixel Format


BGRA 32-bit
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format

(NSDictionary *) requiredPixelBufferAttributesForRenderContext
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format

(NSDictionary *) requiredPixelBufferAttributesForRenderContext
kCVPixelFormatType_32BGRA,...
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format


kCVPixelFormatType_32BGRA,...

(NSDictionary *) requiredPixelBufferAttributesForRenderContext
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format


Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format


BGRA 32-bit
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format


BGRA 32-bit

[request.renderContext newPixelBuffer]
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format


BGRA 32-bit

[request.renderContext newPixelBuffer]
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format


BGRA 32-bit

[request.renderContext newPixelBuffer]
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format


BGRA 32-bit
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format


BGRA 32-bit
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here

Output Pixel Format


BGRA 32-bit
Choosing Pixel Formats
finishWithError:
Request
finishCancelledRequest:
startVideoCompositionRequest: finishWithComposedVideoFrame:
Instruction

Mixing Parameters
Your
Code
Here
Demo
CPU and GPU custom compositors
Agenda

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Tweening
AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

Compositor
Tweening
AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

Compositor
Tweening
AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

Compositor
Tweening
Tweening
AVVideoComposition
A
B

Instruction

Compositor
Tweening
AVVideoComposition
A
B

Compositor
Tweening
AVVideoComposition
A
B

Opacity Ramp 100% to 0%

Compositor
Tweening
AVVideoComposition
A
B

Opacity Ramp 100% to 0%

MyInstruction.timeRange = { start 5, duration 10/30 secs }


MyInstruction.opacityRamp = { 100% to 0% }
Compositor
Tweening
elapsed = 0 secs
AVVideoComposition
A
B

Opacity Ramp 100% to 0%

Compositor
Tweening
elapsed = 0 secs
AVVideoComposition
A
B
opacity = 100%
Opacity Ramp 100% to 0%

Compositor
Tweening
elapsed = 0 secs
AVVideoComposition
A
B
opacity = 100%
Opacity Ramp 100% to 0%

tween = elapsed / duration = 0.0 Compositor


Tweening
elapsed = 1/30 secs
AVVideoComposition
A
B
opacity = 90%
Opacity Ramp 100% to 0%

Calculate how far through the animation we are;


tween = elapsed / duration = 0.1 Compositor Subtract the start time, divide by the duration
Tweening
elapsed = .. secs
AVVideoComposition
A
B
opacity = ..%
Opacity Ramp 100% to 0%

tween = elapsed / duration = .. Compositor


Tweening
elapsed = .. secs
AVVideoComposition
A
B

Opacity Ramp 100% to 0%


opacity = ..%

Compositor tween = elapsed / duration = ..


Tweening
elapsed = 10/30 secs
AVVideoComposition
A
B

Opacity Ramp 100% to 0%


opacity = 0%

Compositor tween = elapsed / duration = 1.0


Agenda

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
iOS Apps

Foreground Background

CPU CPU


Performance
Instruction properties
@protocol AVVideoCompositionInstruction<NSObject>
{
@property CMPersistentTrackID passthroughTrackID;
@property NSArray *requiredSourceTrackIDs;
@property BOOL containsTweening;
}
Performance
Instruction properties
@protocol AVVideoCompositionInstruction<NSObject>
{
@property CMPersistentTrackID passthroughTrackID;
@property NSArray *requiredSourceTrackIDs;
@property BOOL containsTweening;
}
Performance
passthroughTrackID

AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

1 source 1 source 1 source

2 sources 2 sources
Performance
passthroughTrackID

AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

passthroughTrackID = A; // bypass compositor


Performance
passthroughTrackID

AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

passthroughTrackID = A; // bypass compositor


Performance
Instruction properties
@protocol AVVideoCompositionInstruction<NSObject>
{
@property CMPersistentTrackID passthroughTrackID;
@property NSArray *requiredSourceTrackIDs;
@property BOOL containsTweening;
}
Performance
requiredSourceTrackIDs

AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

requiredSourceTrackIDs = @[ A ];
Performance
requiredSourceTrackIDs

AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

requiredSourceTrackIDs = @[ A ];
Performance
requiredSourceTrackIDs

AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

requiredSourceTrackIDs = nil
Performance
requiredSourceTrackIDs

AVVideoComposition
A B
A B
B A
A

Instruction Instruction Instruction Instruction Instruction

requiredSourceTrackIDs = nil Deliver Frames from ALL Tracks


Performance
Instruction properties
@protocol AVVideoCompositionInstruction<NSObject>
{
@property CMPersistentTrackID passthroughTrackID;
@property NSArray *requiredSourceTrackIDs;
@property BOOL containsTweening;
}
Performance
containsTweening

Moving picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = YES;

Moving picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = YES;
Performance
containsTweening

containsTweening = YES;

Static picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = YES;

Frame #0

Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = YES;

Frame #0 Frame #1

Custom Compositor Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = YES;

Frame #0 Frame #1 Frame #2

Custom Compositor Custom Compositor Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = YES;

Frame #0 Frame #1 Frame #2

Custom Compositor Custom Compositor Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening
Re-render identical output!

containsTweening = YES;

Frame #0 Frame #1 Frame #2

Custom Compositor Custom Compositor Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening

Frame #0 Frame #1 Frame #2

Custom Compositor Custom Compositor Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening
I’m not animating

containsTweening = NO;

Frame #0 Frame #1 Frame #2

Custom Compositor Custom Compositor Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = NO;

Static picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = NO;

Frame #0

Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = NO;

Frame #0 Frame #1

Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening

containsTweening = NO;

Frame #0 Frame #1 Frame #2

Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
containsTweening
Reuse identical output

containsTweening = NO;

Frame #0 Frame #1 Frame #2

Custom Compositor

Static picture-in-picture,
same source frames every time
Performance
Pixel buffer formats
• Performance hit converting sources
■ H.264 decodes to YUV 4:2:0
■ Best performance, work in YUV 4:2:0

• Output format less critical


■ BGRA or YUV 4:2:0 out
Performance
Pixel buffer formats
• Performance hit converting sources
■ H.264 decodes to YUV 4:2:0
■ Best performance, work in YUV 4:2:0

• Output format less critical


■ BGRA or YUV 4:2:0 out
Sample Code
Custom compositor
• AVCustomEdit
• GPU compositor
• Materials available at:
https://developer.apple.com/wwdc/schedule/details.php?id=612
Agenda

• Custom video compositing


■ Existing architecture
■ New Custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Debugging Compositions
Debugging Compositions
Common pitfalls
• Gaps between segments
• Misaligned track segments
• Misaligned layer instructions
• Misaligned opacity/audio ramps
• Bogus layer transforms
Debugging Compositions
Common pitfalls
• Gaps between segments
• Misaligned track segments
• Misaligned layer instructions
• Misaligned opacity/audio ramps Oops!
• Bogus layer transforms

A B
B A
B A
Debugging Compositions
Common pitfalls
• Gaps between segments
• Misaligned track segments
• Misaligned layer instructions
So close :-(
• Misaligned opacity/audio ramps
• Bogus layer transforms Whale.m4v

Otters.m4v

Sea.m4v Waves.m4v
Debugging Compositions
Common pitfalls
• Gaps between segments
Not the alignment
• Misaligned track segments we’re looking for!
• Misaligned layer instructions
• Misaligned opacity/audio ramps
• Bogus layer transforms
Sea.m4v

Waves.m4v

B
A
A
Debugging Compositions
Common pitfalls
• Gaps between segments
• Misaligned track segments
• Misaligned layer instructions Overshoot!
• Misaligned opacity/audio ramps
• Bogus layer transforms

B
B
A
Debugging Compositions
Common pitfalls
• Gaps between segments
• Misaligned track segments
• Misaligned layer instructions
• Misaligned opacity/audio ramps
• Bogus layer transforms
Debugging Compositions
Common pitfalls
• Gaps between segments
• Misaligned track segments
• Misaligned layer instructions
• Misaligned opacity/audio ramps
• Bogus layer transforms ?*#!
Demo
AVCompositionDebugViewer
Sample Code
Debugging compositions
• AVCompositionDebugViewer
• Materials available at:
https://developer.apple.com/wwdc/schedule/details.php?id=612
Debugging Compositions

• Drop AVCompositionDebugView into your own app


• Extend it to draw your own video instructions
• Spot overlaps and gaps; tracks, video instructions, and audio mix
• Don’t forget the composition validation API
■ @protocol AVVideoCompositionValidationHandling
Summary

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Summary

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Summary

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions @protocol AVVideoCompositing


@protocol AVVideoCompositionInstruction
■ Common pitfalls AVAsynchronousVideoCompositionRequest
Summary

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Summary

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Summary

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Summary

• Custom video compositing


■ Existing architecture
■ New custom video compositing

■ Choosing pixel formats

■ Tweening

■ Performance

• Debugging compositions
■ Common pitfalls
Custom Compositors
Effects, Transitions, Generators
Custom Compositors
Effects, Transitions, Generators
More Information

John Geleynse
Director, Technology Evangelist
[email protected]

Documentation
AVFoundation
http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG

Apple Developer Forums


http://devforums.apple.com
Related Sessions

Pacific Heights
Moving to AV Kit and AV Foundation Tuesday 4:30PM

Nob Hill
Preparing and Presenting Media for Accessibility Wednesday 10:15AM

Nob Hill
What's New in Camera Capture Wednesday 11:30AM
Labs

Media Lab B
OS X and iOS Capture Lab Thursday 9:00AM

Media Lab B
AV Foundation Lab Thursday 2:00PM

Media Lab B
AV Foundation Lab Friday 9:00AM

You might also like