SlideShare a Scribd company logo
1 of 88
iOS Media APIs
Chris Adamson ā€¢ @invalidname
MobiDevDay ā€¢ Detroit, MI ā€¢ May 4, 2013
Slides will be posted to slideshare.net/invalidname
Thursday, May 2, 13
Where do I start?
Thursday, May 2, 13
iOS Media APIs
ā€¢ AV Foundation
ā€¢ Core Media
ā€¢ Core Animation
ā€¢ Media Player
ā€¢ Core Audio
ā€¢ Audio Toolbox
ā€¢ Audio Units
ā€¢ Core MIDI
ā€¢ Open AL
Thursday, May 2, 13
Also!
ā€¢ UIKit
ā€¢ UIImagePickerController, remote control
events
ā€¢ AirPlay
ā€¢ HTTP Live Streaming
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
AV Foundation
Thursday, May 2, 13
AV Foundation
ā€¢ High-level Obj-C audio/video framework
ā€¢ Debuted in iPhone OS 2.3, not fully baked
until iOS 4
ā€¢ Consists of three distinct areas of
functionality with little overlap
Thursday, May 2, 13
AVAudioPlayer
AVAudioRecorder
AVAudioSession
AVAudioSessionChannelDescription
AVAudioSessionPortDescription
AVAudioSessionRouteDescription
AVCaptureAudioDataOutput
AVCaptureConnection
AVCaptureDevice
AVCaptureDeviceInput
AVCaptureFileOutput
AVCaptureInput
AVCaptureMetadataOutput
AVCaptureMovieFileOutput
AVCaptureOutput
AVCaptureSession
AVCaptureStillImageOutput
AVCaptureVideoDataOutput
AVCaptureVideoPreviewLayer
AVAsset
AVAssetExportSession
AVAssetImageGenerator
AVAssetReader
AVAssetReaderAudioMixOutput
AVAssetReaderOutput
AVAssetReaderTrackOutput
AVAssetReaderVideoCompositionOutput
AVAssetResourceLoader
AVAssetResourceLoadingRequest
AVAssetTrack
AVAssetTrackSegment
AVAssetWriter
AVAssetWriterInput
AVAssetWriterInputPixelBufferAdaptor
AVAudioMix
AVAudioMixInputParameters
AVComposition
AVCompositionTrack
AVCompositionTrackSegment
AVMediaSelectionGroup
AVMediaSelectionOption
AVMetadataFaceObject
AVMetadataItem
AVMetadataObject
AVMutableAudioMix
AVMutableAudioMixInputParameters
AVMutableComposition
AVMutableCompositionTrack
AVMutableMetadataItem
AVMutableTimedMetadataGroup
AVMutableVideoComposition
AVMutableVideoCompositionInstruction
AVMutableVideoCompositionLayerInstruction
AVPlayer
AVPlayerItem
AVPlayerItemAccessLog
AVPlayerItemAccessLogEvent
AVPlayerItemErrorLog
AVPlayerItemErrorLogEvent
AVPlayerItemOutput
AVPlayerItemTrack
AVPlayerItemVideoOutput
AVPlayerLayer
AVQueuePlayer
AVSynchronizedLayer
AVTextStyleRule
AVTimedMetadataGroup
AVURLAsset
AVVideoComposition
AVVideoCompositionCoreAnimationTool
AVVideoCompositionInstruction
AVVideoCompositionLayerInstruction
Audio
Capture
Editing / Export / Playback
Thursday, May 2, 13
AVF audio classes
ā€¢ AVAudioPlayer ā€“ plays ļ¬‚at ļ¬les or audio
from an NSData
ā€¢ AVAudioRecorder ā€“ records from most-
recently connected input device (built-in
mic, headset, etc.)
ā€¢ AVAudioSession ā€“ negotiates with system
for access to audio hardware
Thursday, May 2, 13
AVAudioPlayer
ā€¢ initWithContentsOfURL:error: or
initWithData:error:
ā€¢ URL must be local
ā€¢ Methods: play, playAtTime:, pause, stop
ā€¢ Properties: volume, pan, numberOfLoops,
etc.
Thursday, May 2, 13
Playing a song
NSURL *songURL = [[NSBundle mainBundle]
URLForResource:@"Bossa Lounger Long"
! ! ! ! ! ! ! withExtension:@"caf"];
// set up av audio player
NSError *err = nil;
self.player = [[AVAudioPlayer alloc]
initWithContentsOfURL:songURL
error:&err];
if (err) {
! NSLog (@"Error creating player: %@", err);
} else {
! [self.player play];
}
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
Video Playback
ā€¢ Two options:AVPlayer and
MPMoviePlayerController
ā€¢ Since weā€™re already talking about AV
Foundation, letā€™s do AVPlayer and friends
for now
Thursday, May 2, 13
AVF essentials
ā€¢ AVAsset ā€“ A time-based, playable item
(local or remote)
ā€¢ AVPlayer ā€“ Handles playback of one or
more AVPlayerItems
ā€¢ Each AVPlayerItem is associated with an
AVAsset
ā€¢ Player does play/pause, seekToTime:, etc.
Thursday, May 2, 13
AVPlayer video
ā€¢ AVPlayerLayer ā€“ A CALayer to present
video from an AVLayer
ā€¢ CALayer is not a UIResponder, doesnā€™t
handle touches.You need to provide your
own playback UI.
ā€¢ gravity property determines ā€œstretchingā€
of video to ļ¬t layerā€™s bounds
Thursday, May 2, 13
Playing a video
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url
! ! ! ! ! ! ! options:nil];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
self.player = [AVPlayer playerWithPlayerItem:playerItem];
NSArray *visualTracks = [asset tracksWithMediaCharacteristic:
AVMediaCharacteristicVisual];
if ([visualTracks count] > 0) {
! AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
! [playerView.layer addSublayer:playerLayer];
! playerLayer.frame = playerView.layer.bounds;
! playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
}
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
AVF Capture
ā€¢ AVCaptureSession ā€“ Coordinates capture
activities
ā€¢ Discover AVCaptureDevices (mics,
camera), create AVCaptureInputs from
them, connect to session
ā€¢ Create AVCaptureOutputs (ļ¬le, data
callbacks), connect to session
Thursday, May 2, 13
AVF Capture// create capture session, attach default video input
self.captureSession = [[AVCaptureSession alloc] init];
NSError *setUpError = nil;
AVCaptureDevice *videoDevice = [AVCaptureDevice
defaultDeviceWithMediaType: AVMediaTypeVideo];
if (videoDevice) {
! AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput
deviceInputWithDevice:videoDevice
! error:&setUpError];
! if (videoInput) {
! ! [captureSession addInput: videoInput];
! }
}
// create a preview layer from the session and add it to UI
AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer
layerWithSession:captureSession];
previewLayer.frame = captureView.layer.bounds;
previewLayer.videoGravity = AVLayerVideoGravityResizeAspect;
[captureView.layer addSublayer:previewLayer];
// start capture session and write to file
captureMovieOutput = [[AVCaptureMovieFileOutput alloc] init];
[captureSession addOutput:captureMovieOutput];
[captureSession startRunning];
[captureMovieOutput startRecordingToOutputFileURL:captureMovieURL
! ! ! ! ! ! recordingDelegate:self];
Thursday, May 2, 13
AVF Editing
ā€¢ AVMutableComposition ā€“Ā An AVAsset for a
multi-track movie you build from
references to other AVAssets
ā€¢ AVMutableCompositionTrack ā€“ Built up
with
insertTimeRange:ofTrack:atTime:error:
Thursday, May 2, 13
AVFVideo Effects
ā€¢ Create AVMutableMutableVideoInstruction
made up of
AVMutableVideoCompositionLayerInstructi
ons
ā€¢ Each instruction works with a video track
ā€¢ Instruction ramps opacity or afļ¬ne
transform over a time range
Thursday, May 2, 13
AVF Text/Image effects
ā€¢ Create an AVSynchronizedLayer to show
the composition
ā€¢ Create CALayers, CATextLayers and set
CAAnimations on them, then add as sub-
layers to the AVSynchronizedLayer
Thursday, May 2, 13
AVF Export
ā€¢ Create AVAssetExportSession with one of the
canned presets (audio only, or QuickTime .mov
at preset size or quality)
ā€¢ If you used layer-based animations, add an
AVVideoComposition, with an
AVVideoCompositionCoreAnimationTool
(yes, itā€™s as hard as it sounds)
ā€¢ Call
exportAsynchronouslyWithCompletionHandler:
Thursday, May 2, 13
AVF Editing
-(IBAction) handlePerformTapped: (id) sender {
! NSLog (@"handlePerformTapped");
! NSError *performError = nil;
! // create composition
! self.composition = [[AVMutableComposition alloc] init];
! // create video tracks a and b
! // note: mediatypes are defined in AVMediaFormat.h
! [trackA! release];
! trackA = [self.composition addMutableTrackWithMediaType:AVMediaTypeVideo
! ! ! ! ! ! ! ! ! !
preferredTrackID:kCMPersistentTrackID_Invalid];
! [trackB release];
! trackB = [self.composition addMutableTrackWithMediaType:AVMediaTypeVideo
! ! ! ! ! ! ! ! ! !
preferredTrackID:kCMPersistentTrackID_Invalid];
// create video instructions
NSMutableArray *videoInstructions = [[[NSMutableArray alloc] init] autorelease];
! // create music track
trackMusic = [self.composition addMutableTrackWithMediaType:AVMediaTypeAudio
preferredTrackID:kCMPersistentTrackID_Invalid];
! CMTimeRange musicTrackTimeRange = CMTimeRangeMake(kCMTimeZero,
musicTrackAudioAsset.duration);
! NSError *trackMusicError = nil;
! [trackMusic insertTimeRange:musicTrackTimeRange
! ! ! ! ! ! ofTrack:[musicTrackAudioAsset.tracks objectAtIndex:0]
! ! ! ! ! ! atTime:kCMTimeZero
! ! ! ! ! ! error:&trackMusicError];
! if (trackMusicError) {
! ! NSLog(@"couldn't create trackMusic: %@", trackMusicError);
! } else {
! ! NSLog (@"created trackMusic");
! }
!
! // setup the player
! [compositionPlayer release];
! compositionPlayer = [[AVPlayer playerWithPlayerItem: [AVPlayerItem playerItemWithAsset: composition]] retain];
! [compositionPlayerLayer removeFromSuperlayer];
! compositionPlayerLayer = [[AVPlayerLayer playerLayerWithPlayer:compositionPlayer] retain];
! [compositionView.layer addSublayer:compositionPlayerLayer];
! compositionPlayerLayer.frame = compositionView.layer.bounds;
! compositionPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
!
! [updateScrubberTimer invalidate];
! [updateScrubberTimer release];
! updateScrubberTimer = [[NSTimer scheduledTimerWithTimeInterval:0.1
! ! ! ! ! ! ! ! ! ! ! !
! ! target:self
! ! ! ! ! ! ! ! ! ! ! !
! ! selector:@selector(updateScrubber:)
! ! ! ! ! ! ! ! ! ! ! !
! ! userInfo:nil
! ! ! ! ! ! ! ! ! ! ! !
! ! repeats:YES]
! ! ! ! ! ! retain];
// the video tracks
AVAssetTrack *sourceVideoTrack = [[sourceVideoAsset tracksWithMediaType: AVMediaTypeVideo] objectAtIndex: 0];
! // pad out the opening with five seconds of blank
CMTime videoTracksTime = CMTimeMake(0, VIDEO_TIME_SCALE);
CMTime postEditTime = CMTimeAdd (videoTracksTime, CMTimeMakeWithSeconds(FIRST_CUT_TRACK_A_IN_TIME, VIDEO_TIME_SCALE));
[trackA insertEmptyTimeRange:CMTimeRangeMake(kCMTimeZero, postEditTime)];
videoTracksTime = postEditTime;
// first shot
postEditTime = CMTimeAdd (videoTracksTime, CMTimeMakeWithSeconds(FIRST_CUT_DURATION,VIDEO_TIME_SCALE));
CMTimeRange firstShotRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(FIRST_CUT_DURATION, VIDEO_TIME_SCALE));
! [trackA insertTimeRange:firstShotRange
! ! ! ! ! ofTrack:sourceVideoTrack
! ! ! ! ! atTime:videoTracksTime
! ! ! ! ! error:&performError];
videoTracksTime = postEditTime;
// track b needs to insert empty segment up to its first use
[trackB insertEmptyTimeRange:CMTimeRangeMake(kCMTimeZero, videoTracksTime)];
postEditTime = CMTimeAdd (videoTracksTime, CMTimeMakeWithSeconds(SECOND_CUT_TRACK_B_IN_TIME,VIDEO_TIME_SCALE));
CMTimeRange secondShotRange = CMTimeRangeMake(CMTimeMakeWithSeconds(SECOND_CUT_SOURCE_TIME, VIDEO_TIME_SCALE),
CMTimeMakeWithSeconds(SECOND_CUT_DURATION, VIDEO_TIME_SCALE));
[trackB insertTimeRange:secondShotRange
ofTrack:sourceVideoTrack
atTime:videoTracksTime
error:&performError];
videoTracksTime = postEditTime;
// TODO: later segments
// desperation cheese - works
AVMutableVideoCompositionInstruction *transitionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction];
transitionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, composition.duration);
AVMutableVideoCompositionLayerInstruction *aInstruction = [AVMutableVideoCompositionLayerInstruction
videoCompositionLayerInstructionWithAssetTrack: trackA];
[aInstruction setOpacityRampFromStartOpacity:0.0 toEndOpacity:1.0
timeRange:CMTimeRangeMake(CMTimeMakeWithSeconds(2.9, VIDEO_TIME_SCALE),
CMTimeMakeWithSeconds(6.0, VIDEO_TIME_SCALE))];
AVMutableVideoCompositionLayerInstruction *bInstruction = [AVMutableVideoCompositionLayerInstruction
videoCompositionLayerInstructionWithAssetTrack: trackB];
[bInstruction setOpacity:0 atTime:kCMTimeZero];
transitionInstruction.layerInstructions = [NSArray arrayWithObjects:aInstruction, bInstruction, nil];
[videoInstructions addObject: transitionInstruction];
// end of desperation cheese
// synchronized layer to own all the title layers
AVSynchronizedLayer *synchronizedLayer = [AVSynchronizedLayer synchronizedLayerWithPlayerItem:compositionPlayer.currentItem];
synchronizedLayer.frame = [compositionView frame];
[self.view.layer addSublayer:synchronizedLayer];
// main titles
CATextLayer *mainTitleLayer = [CATextLayer layer];
mainTitleLayer.string = NSLocalizedString(@"Running Start", nil);
mainTitleLayer.font = @"Verdana-Bold";
mainTitleLayer.fontSize = videoSize.height / 8;
mainTitleLayer.foregroundColor = [[UIColor yellowColor] CGColor];
mainTitleLayer.alignmentMode = kCAAlignmentCenter;
mainTitleLayer.frame = CGRectMake(0.0, 0.0, videoSize.width, videoSize.height);
mainTitleLayer.opacity = 0.0; // initially invisible
[synchronizedLayer addSublayer:mainTitleLayer];
// main title opacity animation
[CATransaction begin];
[CATransaction setDisableActions:YES];
CABasicAnimation *mainTitleInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
mainTitleInAnimation.fromValue = [NSNumber numberWithFloat: 0.0];
mainTitleInAnimation.toValue = [NSNumber numberWithFloat: 1.0];
mainTitleInAnimation.removedOnCompletion = NO;
mainTitleInAnimation.beginTime = AVCoreAnimationBeginTimeAtZero;
mainTitleInAnimation.duration = 5.0;
[mainTitleLayer addAnimation:mainTitleInAnimation forKey:@"in-animation"];
CABasicAnimation *mainTitleOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
mainTitleOutAnimation.fromValue = [NSNumber numberWithFloat: 1.0];
mainTitleOutAnimation.toValue = [NSNumber numberWithFloat: 0.0];
mainTitleOutAnimation.removedOnCompletion = NO;
mainTitleOutAnimation.beginTime = 5.0;
mainTitleOutAnimation.duration = 2.0;
[mainTitleLayer addAnimation:mainTitleOutAnimation forKey:@"out-animation"];
[CATransaction commit];
// TODO: end credits
// tell the player about our effects
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition];
videoComposition.instructions = videoInstructions;
videoComposition.renderSize = videoSize;
videoComposition.frameDuration = CMTimeMake(1, 30); // 30 fps
compositionPlayer.currentItem.videoComposition = videoComposition;
// set up the duration label at the right side of the scrubber
int durationSeconds = (int) CMTimeGetSeconds (composition.duration);
self.durationLabel.text = [NSString stringWithFormat: @"%02d:%02d",
durationSeconds / 60, durationSeconds % 60];
// reset rate field and play/pause button state
rateField.text = @"0.0";
playPauseButton.selected = NO;
! NSLog (@"bottom of handlePerformTapped");
!
}
No, thatā€™s not supposed to be legible.
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
HTTP Live Streaming
Thursday, May 2, 13
HTTP Live Streaming
ā€¢ Apple-led semi-standard streaming format
ā€¢ Only stream format allowed on App Store
ā€¢ Streams video as series of small (10 sec.)
ļ¬les, via ordinary web server on port 80
ā€¢ Create streams with command-line tools,
Pro apps (Compressor, Final Cut), server-
side transcoders (Wowza)
Thursday, May 2, 13
Thursday, May 2, 13
Thursday, May 2, 13
HLS Advantages
ā€¢ Mobile-friendly: works over spotty cellular
connections, stream can provide multiple
bitrates (client switches on the ļ¬‚y)
ā€¢ No special server software required: can
stream from Dropbox
ā€¢ Wide adoption: Roku, Xbox,Android,
GoogleTV, etc.
Thursday, May 2, 13
Client-side HLS
ā€¢ Create an AVPlayer or
MPMoviePlayerController with the
streamā€™s .m3u8 URL just like any other URL
ā€¢ There is no step 2
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
Media Player
Thursday, May 2, 13
Media Player
ā€¢ Allows access to the deviceā€™s iTunes library
ā€¢ Audio-only: songs, podcasts, audiobooks
ā€¢ Discover contents with MPMediaQuery, or
show a MPMediaPickerController
ā€¢ MPMediaItems have metadata (title, artist,
album, cover art, etc.)
ā€¢ Play with MPMusicPlayerController
Thursday, May 2, 13
MPMediaQuery
NSString *searchText = searchController.searchBar.text;
MPMediaQuery *query = [MPMediaQuery songsQuery];
MPMediaPropertyPredicate *titlePredicate =
[MPMediaPropertyPredicate predicateWithValue:searchText
! ! ! forProperty:MPMediaItemPropertyTitle
! ! ! comparisonType:
MPMediaPredicateComparisonContains];
[query addFilterPredicate:titlePredicate];
MPMusicPlayerController *iPodController =
! [MPMusicPlayerController iPodMusicPlayer];
[iPodController stop];
[iPodController setQueueWithQuery: query];
[iPodController play];
Thursday, May 2, 13
MPMoviePlayerController
ā€¢ Simple video player, alternative to AVPlayer
ā€¢ Provides its own view and controls
ā€¢ Lighter-weight than AVPlayer, which helps
on really old devices (iPhone 3GS)
Thursday, May 2, 13
MP novelties
ā€¢ MPNowPlayingInfoCenter ā€“ Access to
metadata shown on lock screen and
external media displays (e.g., in-car
entertainment systems)
ā€¢ MPVolumeView ā€“ System-wide volume
slider, with AirPlay button if available
Thursday, May 2, 13
Remote Controls
ā€¢ Receive play/pause, forward/back from
headset, dock keyboard, in-car systems,
other external devices
ā€¢ -[UIApplication
beginReceivingRemoteControlEvents]
ā€¢ Must be able to become ļ¬rst responder
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
AirPlay
Thursday, May 2, 13
AirPlay
ā€¢ Wireless audio/video streaming from iOS
device to Apple TV,AirPort Express, some
speakers
ā€¢ Unofļ¬cial third-party clients for Mac
(Reļ¬‚ector,Air Sharing), PC,Android, etc.
Thursday, May 2, 13
AirPlay API
ā€¢ There basically isnā€™t one
ā€¢ User either mirrors device, or uses
AirPlay menu on MPVolumeView or
MPMoviePlayerController
ā€¢ You can deny (but please donā€™t) with
allowsAirPlay (MPMovieController),
mediaPlaybackAllowsAirPlay (UIWebView),
allowsExternalPlayback (AVPlayer)
Thursday, May 2, 13
Second screens
ā€¢ If user connects toVGA/DVI via Dock/
Lightning adapter, or connects to AirPlay
without mirroring, your app will see a
second screen
ā€¢ Discover with -[UIScreen screens], create
new UIWindow for it
ā€¢ Chat on the device, video on the second
screen?
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
Core Audio
Thursday, May 2, 13
Core Audio
ā€¢ C frameworks for real-time audio
processing
ā€¢ Legendary performance, legendary
difļ¬culty
ā€¢ Basis of OS X pro audio apps like Logic
and GarageBand
Thursday, May 2, 13
Core Audio
ā€¢ Audio Queue
ā€¢ Audio Units
ā€¢ Open AL
ā€¢ Audio File Services
ā€¢ Audio Converter Svcs.
ā€¢ Extended Audio File
Svcs.
ā€¢ Audio File Stream Svcs.
ā€¢ Audio Session Svcs.
Thursday, May 2, 13
Core Audio
ā€¢ Small number of structures and functions
ā€¢ Most behavior is speciļ¬ed by getting and
setting properties
ā€¢ All functions return OSStatus, must check
for noErr before continuing
ā€¢ ā€œCreateā€-style functions take pointer as a
parameter and populate it
Thursday, May 2, 13
Audio Queue
ā€¢ Convenience API for play-out or capture
ā€¢ Wrapped by AV Foundationā€™s
AVAudioRecorder,AVAudioPlayer for ļ¬le-
only scenarios
ā€¢ For play-out, app provides buffers to play
ā€¢ For captuer, queue gives app with buffers of
capture data
Thursday, May 2, 13
Audio Queue
Thursday, May 2, 13
Audio Queue
Thursday, May 2, 13
Audio Queue
Thursday, May 2, 13
Audio Queue
Thursday, May 2, 13
Parsing Web Radio
Thursday, May 2, 13
Parsing Web Radio
NSData NSData
Packets Packets Packets Packets Packets
NSURLConnection delivers
NSData buffers, containing audio
and framing info.We pass it to
Audio File Services.
Thursday, May 2, 13
Parsing Web Radio
NSData NSData
Packets Packets Packets Packets Packets
Packets Packets
Packets Packets Packets
NSURLConnection delivers
NSData buffers, containing audio
and framing info.We pass it to
Audio File Services.
Audio File Services calls us back
with parsed packets of audio data.
Thursday, May 2, 13
Parsing Web Radio
NSData NSData
Packets Packets Packets Packets Packets
Packets Packets
Packets Packets Packets
012
Packets
Packets
Packets
Packets
Packets
Packets
NSURLConnection delivers
NSData buffers, containing audio
and framing info.We pass it to
Audio File Services.
Audio File Services calls us back
with parsed packets of audio data.
We create an AudioQueueBuffer
with those packets and enqueue it
for play-out.
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
Audio Units
Thursday, May 2, 13
Audio Units
ā€¢ Lowest level of audio processing available
to third parties
ā€¢ I/O, effects, mixing, ļ¬le player, synthesis
ā€¢ Extremely low latency I/O (< 10 ms)
Thursday, May 2, 13
Pull Model
AUSomething
Thursday, May 2, 13
Pull Model
AUSomething
AudioUnitRender()
Thursday, May 2, 13
Pull Model
AUSomethingAUSomethingElse
Thursday, May 2, 13
Buses (aka, Elements)
AUSomething
AUSomethingElse
AUSomethingElse
Thursday, May 2, 13
AUGraph
AUSomething
AUSomethingElse
AUSomethingElse
Thursday, May 2, 13
AURemoteIO Buses
AURemoteIO
Thursday, May 2, 13
AURemoteIO Buses
AURemoteIO
bus 0
to output H/W
Thursday, May 2, 13
AURemoteIO Buses
AURemoteIO
bus 0
to output H/W
bus 0
from app
Thursday, May 2, 13
AURemoteIO Buses
AURemoteIO
bus 0
to output H/W
bus 1
from input H/W
bus 0
from app
Thursday, May 2, 13
AURemoteIO Buses
AURemoteIO
bus 0
to output H/W
bus 1
from input H/W
bus 1
to app
bus 0
from app
Thursday, May 2, 13
Pass Through
AURemoteIO
bus 1
from input H/W
bus 0
to output H/W
Thursday, May 2, 13
Pass-Through with Effect
bus 0
to output H/W
AURemoteIO
AUEffect
bus 1
from input H/W
Thursday, May 2, 13
Core Audio code
-(void) setUpAUGraph {
! if (self.auGraph) {
! ! CheckError(AUGraphClose(self.auGraph),
! ! ! ! "Couldn't close old AUGraph");
! ! CheckError (DisposeAUGraph(self.auGraph),
! ! ! ! ! "Couldn't dispose old AUGraph");
! }
!
! CheckError(NewAUGraph(&_auGraph),
! ! ! "Couldn't create new AUGraph");
!
! CheckError(AUGraphOpen(self.auGraph),
! ! ! "Couldn't open AUGraph");
!
! AudioComponentDescription outputcd = {0};
! outputcd.componentType = kAudioUnitType_Output;
! outputcd.componentSubType = kAudioUnitSubType_RemoteIO;
! outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
!
! AUNode ioNode;
! CheckError(AUGraphAddNode(self.auGraph,
! ! ! ! &outputcd,
! ! ! ! &ioNode),
! ! ! "couldn't add remote io node");
!
! // get the remote io unit from the node
! CheckError(AUGraphNodeInfo(self.auGraph,
! ! ! ! ioNode,
! ! ! ! NULL,
! ! ! ! &_ioUnit),
! ! ! "couldn't get remote io unit");
!
!
! // effect unit here
! AudioComponentDescription effectcd = {0};
! effectcd.componentType = kAudioUnitType_FormatConverter;
! effectcd.componentSubType = kAudioUnitSubType_NewTimePitch;
! effectcd.componentManufacturer = kAudioUnitManufacturer_Apple;
!
! AUNode effectNode;
! CheckError(AUGraphAddNode(self.auGraph,
! ! ! ! &effectcd,
! ! ! ! &effectNode),
! ! ! "couldn't get effect node [time/pitch]");
!
! // get effect unit from the node
! CheckError(AUGraphNodeInfo(self.auGraph,
! ! ! ! effectNode,
! ! ! ! NULL,
! ! ! ! &_effectUnit),
! ! ! "couldn't get effect unit from node");
!
! // enable input on the remote io unit
UInt32 oneFlag = 1;
UInt32 busZero = 0;
! CheckError(AudioUnitSetProperty(self.ioUnit,
! ! ! ! kAudioOutputUnitProperty_EnableIO,
! ! ! ! kAudioUnitScope_Output,
! ! ! ! busZero,
! ! ! ! &oneFlag,
! ! ! ! sizeof(oneFlag)),
! ! ! "Couldn't enable output on bus 0");
! UInt32 busOne = 1;
! CheckError(AudioUnitSetProperty(self.ioUnit,
! ! ! ! kAudioOutputUnitProperty_EnableIO,
! ! ! ! kAudioUnitScope_Input,
! ! ! ! busOne,
! ! ! ! &oneFlag,
! ! ! ! sizeof(oneFlag)),
! ! ! "Couldn't enable input on bus 1");
!
! // set stream format that the effect wants
! AudioStreamBasicDescription streamFormat;
! UInt32 propertySize = sizeof (streamFormat);
! CheckError(AudioUnitGetProperty(self.effectUnit,
kAudioUnitProperty_StreamFormat,
! ! ! ! ! kAudioUnitScope_Input,
! ! ! ! ! 0,
! ! ! ! ! &streamFormat,
! ! ! ! ! &propertySize),
! ! ! "Couldn't get effect unit stream format");
!
! CheckError(AudioUnitSetProperty(self.ioUnit,
kAudioUnitProperty_StreamFormat,
! ! ! ! ! kAudioUnitScope_Output,
! ! ! ! ! busOne,
! ! ! ! ! &streamFormat,
! ! ! ! ! sizeof(streamFormat)),
! ! ! "couldn't set stream format on iounit bus 1 output");
! CheckError(AudioUnitSetProperty(self.ioUnit,
! kAudioUnitProperty_StreamFormat,
! ! ! ! kAudioUnitScope_Input,
! ! ! ! ! busZero,
! ! ! ! ! &streamFormat,
! ! ! ! ! sizeof(streamFormat)),
! ! ! "couldn't set stream format on iounit bus 0 input");
! !
!
! CheckError(AUGraphConnectNodeInput(self.auGraph,
! ! ! ! ! ioNode,
! ! ! 1,
! ! ! ! ! effectNode,
! ! ! ! ! 0),
! ! ! "couldn't connect remoteio bus 1 output to effect bus 0 input");
!
! CheckError(AUGraphConnectNodeInput(self.auGraph,
! ! ! ! ! effectNode,
! ! ! ! ! 0,
! ! ! ! ! ioNode,
! ! ! ! ! 0),
! ! ! "couldn't connect effect bus 0 output to remoteio bus 0 input");
!
!
! CheckError(AUGraphInitialize(self.auGraph),
! ! ! "Couldn't initialize AUGraph");
!
! CheckError(AUGraphStart(self.auGraph),
! ! ! "Couldn't start AUGraph");
!
!
!
! NSLog (@"bottom of setUpAUGraph");
}
No, this isnā€™t supposed to be readable either
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
Core MIDI
Thursday, May 2, 13
Core MIDI
ā€¢ Handles MIDI events from external devices
ā€¢ Connect via Dock/Lightning connectors
or Camera Connection Kit (USB)
ā€¢ Only provides callbacks on events (key up,
key down, pitch bend, etc.) ā€” up to you do
something with it
Thursday, May 2, 13
MIDI Packets
ā€¢ High nybble of status is command, low is
channel number
ā€¢ Data 1 & 2 depend on command
STATUS DATA 1 DATA 2
Thursday, May 2, 13
Handling MIDI packetsstatic void! MyMIDIReadProc(const MIDIPacketList *pktlist, void *refCon, void
*connRefCon) {
! SNFMasterViewController *myVC = (__bridge SNFMasterViewController*) refCon;
! MIDIPacket *packet = (MIDIPacket *)pktlist->packet;!
! for (int i=0; i < pktlist->numPackets; i++) {
! ! Byte midiStatus = packet->data[0];
! ! Byte midiCommand = midiStatus >> 4;
! ! // is it a note-on or note-off
! ! if ((midiCommand == 0x09) ||
! ! ! (midiCommand == 0x08)) {
! ! ! Byte note = packet->data[1] & 0x7F;
! ! ! Byte velocity = packet->data[2] & 0x7F;
! ! ! printf("midiCommand=%d. Note=%d, Velocity=%dn",
midiCommand, note, velocity);
! ! !
! ! ! // send to augraph
! ! ! CheckError(MusicDeviceMIDIEvent (myVC.auSampler,
! ! ! ! ! ! ! ! ! ! ! midiStatus,
! ! ! ! ! ! ! ! ! ! ! note,
! ! ! ! ! ! ! ! ! ! ! velocity,
! ! ! ! ! ! ! ! ! ! ! 0),
! ! ! ! ! "Couldn't send MIDI event");
! ! !
! ! }
! ! packet = MIDIPacketNext(packet);
! }
}
Thursday, May 2, 13
How Do I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
OpenAL
Thursday, May 2, 13
OpenAL
ā€¢ Cross-platform C API to create positional
sound
ā€¢ Designed to resemble OpenGL
ā€¢ Low latency, ideal for games
ā€¢ Calls set an error ļ¬‚ag, must check with
alGetError() after every AL call
Thursday, May 2, 13
AL example
// set up OpenAL source
alGenSources(1, player.sources);
alSourcei(player.sources[0], AL_LOOPING, AL_TRUE);
alSourcef(player.sources[0], AL_GAIN, AL_MAX_GAIN);
updateSourceLocation(player);
// connect buffer to source
alSourcei(player.sources[0], AL_BUFFER, buffers[0]);
// set up listener
alListener3f (AL_POSITION, 0.0, 0.0, 0.0);
// start playing
alSourcePlay(player.sources[0]);
Note: error checking removed for clarity
Thursday, May 2, 13
OpenAL Concepts
ā€¢ ALListener ā€“ The listener, who has an x,y,z
position, orientation, etc.
ā€¢ ALSource ā€“ A sound producing object in
the space. Has position, orientation,
motion, sound cone, much more
ā€¢ ALBuffer ā€“ Buffers of sound attached to a
source. Source can loop one buffer or
receive a stream of buffers
Thursday, May 2, 13
How Did I?
ā€¢ Play music on my title
screen?
ā€¢ Play a video in my app?
ā€¢ Capture, edit, and
export video?
ā€¢ Play streaming video
from my web site?
ā€¢ Play userā€™s iTunes music?
ā€¢ Play a video on an
AppleTV?
ā€¢ Play web radio?
ā€¢ Mix and perform effects
on audio?
ā€¢ Use MIDI devices?
ā€¢ Create in-game sounds
for a 3D game?
Thursday, May 2, 13
iOS Media APIs
ā€¢ There are a LOT of them!
ā€¢ Each ļ¬lls a speciļ¬c role, not a lot of overlap
ā€¢ Simple stuff is easy, complex stuff is possible
Thursday, May 2, 13
Questions?
ā€¢ ā€œAudio andVideo Starting Pointā€ in Apple
developer documentation
ā€¢ http://devforums.apple.com
ā€¢ coreaudio-api@lists.apple.com
Thursday, May 2, 13
iOS Media APIs
Chris Adamson ā€¢ @invalidname
MobiDevDay ā€¢ Detroit, MI ā€¢ May 4, 2013
Slides will be posted to slideshare.net/invalidname
Thursday, May 2, 13

More Related Content

What's hot

Building A Streaming Apple TV App (CocoaConf DC, Sept 2016)
Building A Streaming Apple TV App (CocoaConf DC, Sept 2016)Building A Streaming Apple TV App (CocoaConf DC, Sept 2016)
Building A Streaming Apple TV App (CocoaConf DC, Sept 2016)Chris Adamson
Ā 
Effective HTML5 game audio
Effective HTML5 game audioEffective HTML5 game audio
Effective HTML5 game audioChris Khoo
Ā 
Building Modern Audio Apps with AVAudioEngine
Building Modern Audio Apps with AVAudioEngineBuilding Modern Audio Apps with AVAudioEngine
Building Modern Audio Apps with AVAudioEngineBob McCune
Ā 
Core Audio Cranks It Up
Core Audio Cranks It UpCore Audio Cranks It Up
Core Audio Cranks It UpChris Adamson
Ā 
Introduction to AV Foundation
Introduction to AV FoundationIntroduction to AV Foundation
Introduction to AV FoundationChris Adamson
Ā 
Mastering Media with AV Foundation
Mastering Media with AV FoundationMastering Media with AV Foundation
Mastering Media with AV FoundationChris Adamson
Ā 
HTML5 Audio & Video
HTML5 Audio & VideoHTML5 Audio & Video
HTML5 Audio & VideoAaron Gustafson
Ā 
Composing and Editing Media with AV Foundation
Composing and Editing Media with AV FoundationComposing and Editing Media with AV Foundation
Composing and Editing Media with AV FoundationBob McCune
Ā 
Core audio
Core audioCore audio
Core audioscussen
Ā 
Master Video with AV Foundation
Master Video with AV FoundationMaster Video with AV Foundation
Master Video with AV FoundationBob McCune
Ā 
Stupid Video Tricks, CocoaConf Las Vegas
Stupid Video Tricks, CocoaConf Las VegasStupid Video Tricks, CocoaConf Las Vegas
Stupid Video Tricks, CocoaConf Las VegasChris Adamson
Ā 
AVFoundation @ TACOW 2013 05 14
AVFoundation @ TACOW 2013 05 14AVFoundation @ TACOW 2013 05 14
AVFoundation @ TACOW 2013 05 14Ryder Mackay
Ā 
Stupid Video Tricks (CocoaConf DC, March 2014)
Stupid Video Tricks (CocoaConf DC, March 2014)Stupid Video Tricks (CocoaConf DC, March 2014)
Stupid Video Tricks (CocoaConf DC, March 2014)Chris Adamson
Ā 
Introduction to AV Foundation (CocoaConf, Aug '11)
Introduction to AV Foundation (CocoaConf, Aug '11)Introduction to AV Foundation (CocoaConf, Aug '11)
Introduction to AV Foundation (CocoaConf, Aug '11)Chris Adamson
Ā 
Managing Eclipse Preferences for Teams (EclipseCon 2011)
Managing Eclipse Preferences for Teams (EclipseCon 2011)Managing Eclipse Preferences for Teams (EclipseCon 2011)
Managing Eclipse Preferences for Teams (EclipseCon 2011)Netcetera
Ā 
Chaione Ember.js Training
Chaione Ember.js TrainingChaione Ember.js Training
Chaione Ember.js Trainingaortbals
Ā 
The Next-Gen Dynamic Sound System of Killzone Shadow Fall
The Next-Gen Dynamic Sound System of Killzone Shadow FallThe Next-Gen Dynamic Sound System of Killzone Shadow Fall
The Next-Gen Dynamic Sound System of Killzone Shadow FallGuerrilla
Ā 
Understanding open max il
Understanding open max ilUnderstanding open max il
Understanding open max ilChethan Pchethan
Ā 
Integrating Voice Through Adhearsion
Integrating Voice Through AdhearsionIntegrating Voice Through Adhearsion
Integrating Voice Through AdhearsionMojo Lingo
Ā 

What's hot (20)

Building A Streaming Apple TV App (CocoaConf DC, Sept 2016)
Building A Streaming Apple TV App (CocoaConf DC, Sept 2016)Building A Streaming Apple TV App (CocoaConf DC, Sept 2016)
Building A Streaming Apple TV App (CocoaConf DC, Sept 2016)
Ā 
Effective HTML5 game audio
Effective HTML5 game audioEffective HTML5 game audio
Effective HTML5 game audio
Ā 
Building Modern Audio Apps with AVAudioEngine
Building Modern Audio Apps with AVAudioEngineBuilding Modern Audio Apps with AVAudioEngine
Building Modern Audio Apps with AVAudioEngine
Ā 
Core Audio Cranks It Up
Core Audio Cranks It UpCore Audio Cranks It Up
Core Audio Cranks It Up
Ā 
Introduction to AV Foundation
Introduction to AV FoundationIntroduction to AV Foundation
Introduction to AV Foundation
Ā 
Mastering Media with AV Foundation
Mastering Media with AV FoundationMastering Media with AV Foundation
Mastering Media with AV Foundation
Ā 
HTML5 Audio & Video
HTML5 Audio & VideoHTML5 Audio & Video
HTML5 Audio & Video
Ā 
Composing and Editing Media with AV Foundation
Composing and Editing Media with AV FoundationComposing and Editing Media with AV Foundation
Composing and Editing Media with AV Foundation
Ā 
Core audio
Core audioCore audio
Core audio
Ā 
Master Video with AV Foundation
Master Video with AV FoundationMaster Video with AV Foundation
Master Video with AV Foundation
Ā 
Stupid Video Tricks, CocoaConf Las Vegas
Stupid Video Tricks, CocoaConf Las VegasStupid Video Tricks, CocoaConf Las Vegas
Stupid Video Tricks, CocoaConf Las Vegas
Ā 
Studio track1
Studio track1Studio track1
Studio track1
Ā 
AVFoundation @ TACOW 2013 05 14
AVFoundation @ TACOW 2013 05 14AVFoundation @ TACOW 2013 05 14
AVFoundation @ TACOW 2013 05 14
Ā 
Stupid Video Tricks (CocoaConf DC, March 2014)
Stupid Video Tricks (CocoaConf DC, March 2014)Stupid Video Tricks (CocoaConf DC, March 2014)
Stupid Video Tricks (CocoaConf DC, March 2014)
Ā 
Introduction to AV Foundation (CocoaConf, Aug '11)
Introduction to AV Foundation (CocoaConf, Aug '11)Introduction to AV Foundation (CocoaConf, Aug '11)
Introduction to AV Foundation (CocoaConf, Aug '11)
Ā 
Managing Eclipse Preferences for Teams (EclipseCon 2011)
Managing Eclipse Preferences for Teams (EclipseCon 2011)Managing Eclipse Preferences for Teams (EclipseCon 2011)
Managing Eclipse Preferences for Teams (EclipseCon 2011)
Ā 
Chaione Ember.js Training
Chaione Ember.js TrainingChaione Ember.js Training
Chaione Ember.js Training
Ā 
The Next-Gen Dynamic Sound System of Killzone Shadow Fall
The Next-Gen Dynamic Sound System of Killzone Shadow FallThe Next-Gen Dynamic Sound System of Killzone Shadow Fall
The Next-Gen Dynamic Sound System of Killzone Shadow Fall
Ā 
Understanding open max il
Understanding open max ilUnderstanding open max il
Understanding open max il
Ā 
Integrating Voice Through Adhearsion
Integrating Voice Through AdhearsionIntegrating Voice Through Adhearsion
Integrating Voice Through Adhearsion
Ā 

Similar to iOS Media APIs (MobiDevDay Detroit, May 2013)

Core Audio in iOS 6 (CocoaConf San Jose, April 2013)
Core Audio in iOS 6 (CocoaConf San Jose, April 2013) Core Audio in iOS 6 (CocoaConf San Jose, April 2013)
Core Audio in iOS 6 (CocoaConf San Jose, April 2013) Chris Adamson
Ā 
Web Audio Made Easy with Howler.js
Web Audio Made Easy with Howler.jsWeb Audio Made Easy with Howler.js
Web Audio Made Easy with Howler.jsJames Simpson
Ā 
Deep dive into Androidā€™s audio latency problem
Deep dive into Androidā€™s audio latency problemDeep dive into Androidā€™s audio latency problem
Deep dive into Androidā€™s audio latency problemSirawat Pitaksarit
Ā 
Android Multimedia Player Project Presentation
Android Multimedia Player Project PresentationAndroid Multimedia Player Project Presentation
Android Multimedia Player Project PresentationRashmi Gupta
Ā 
Media hardware
Media hardwareMedia hardware
Media hardwarecoralprout
Ā 
Q6
Q6Q6
Q6aa57304
Ā 
Multi mediapresentation2012
Multi mediapresentation2012Multi mediapresentation2012
Multi mediapresentation2012afavia
Ā 
Core Audio: Don't Be Afraid to Play it LOUD! [360iDev, San Jose 2010]
Core Audio: Don't Be Afraid to Play it LOUD! [360iDev, San Jose 2010]Core Audio: Don't Be Afraid to Play it LOUD! [360iDev, San Jose 2010]
Core Audio: Don't Be Afraid to Play it LOUD! [360iDev, San Jose 2010]Chris Adamson
Ā 
Heroes of Paragon: publishing Unity WebGL game on Facebook
Heroes of Paragon: publishing Unity WebGL game on FacebookHeroes of Paragon: publishing Unity WebGL game on Facebook
Heroes of Paragon: publishing Unity WebGL game on FacebookDevGAMM Conference
Ā 
Multimedia on the web - HTML5 video and audio
Multimedia on the web - HTML5 video and audioMultimedia on the web - HTML5 video and audio
Multimedia on the web - HTML5 video and audioChristian Heilmann
Ā 
Android Multimedia Support
Android Multimedia SupportAndroid Multimedia Support
Android Multimedia SupportJussi Pohjolainen
Ā 
Core Audio in iOS 6 (CocoaConf Portland, Oct. '12)
Core Audio in iOS 6 (CocoaConf Portland, Oct. '12)Core Audio in iOS 6 (CocoaConf Portland, Oct. '12)
Core Audio in iOS 6 (CocoaConf Portland, Oct. '12)Chris Adamson
Ā 
Video and Audio in Learning
Video and Audio in LearningVideo and Audio in Learning
Video and Audio in LearningYum Studio
Ā 
Joshfire Framework 0.9 Technical Overview
Joshfire Framework 0.9 Technical OverviewJoshfire Framework 0.9 Technical Overview
Joshfire Framework 0.9 Technical OverviewSylvain Zimmer
Ā 
Media hardware and softwares used to create my media product
Media hardware and softwares used to create my media product Media hardware and softwares used to create my media product
Media hardware and softwares used to create my media product coralprout
Ā 

Similar to iOS Media APIs (MobiDevDay Detroit, May 2013) (20)

Core Audio in iOS 6 (CocoaConf San Jose, April 2013)
Core Audio in iOS 6 (CocoaConf San Jose, April 2013) Core Audio in iOS 6 (CocoaConf San Jose, April 2013)
Core Audio in iOS 6 (CocoaConf San Jose, April 2013)
Ā 
Q4
Q4Q4
Q4
Ā 
Web Audio Made Easy with Howler.js
Web Audio Made Easy with Howler.jsWeb Audio Made Easy with Howler.js
Web Audio Made Easy with Howler.js
Ā 
Deep dive into Androidā€™s audio latency problem
Deep dive into Androidā€™s audio latency problemDeep dive into Androidā€™s audio latency problem
Deep dive into Androidā€™s audio latency problem
Ā 
Jsconf 2011-us
Jsconf 2011-usJsconf 2011-us
Jsconf 2011-us
Ā 
Android Multimedia Player Project Presentation
Android Multimedia Player Project PresentationAndroid Multimedia Player Project Presentation
Android Multimedia Player Project Presentation
Ā 
Media hardware
Media hardwareMedia hardware
Media hardware
Ā 
Q6
Q6Q6
Q6
Ā 
Q6
Q6Q6
Q6
Ā 
Video & podcasting slideshow
Video & podcasting slideshowVideo & podcasting slideshow
Video & podcasting slideshow
Ā 
Multi mediapresentation2012
Multi mediapresentation2012Multi mediapresentation2012
Multi mediapresentation2012
Ā 
Core Audio: Don't Be Afraid to Play it LOUD! [360iDev, San Jose 2010]
Core Audio: Don't Be Afraid to Play it LOUD! [360iDev, San Jose 2010]Core Audio: Don't Be Afraid to Play it LOUD! [360iDev, San Jose 2010]
Core Audio: Don't Be Afraid to Play it LOUD! [360iDev, San Jose 2010]
Ā 
Heroes of Paragon: publishing Unity WebGL game on Facebook
Heroes of Paragon: publishing Unity WebGL game on FacebookHeroes of Paragon: publishing Unity WebGL game on Facebook
Heroes of Paragon: publishing Unity WebGL game on Facebook
Ā 
Multimedia on the web - HTML5 video and audio
Multimedia on the web - HTML5 video and audioMultimedia on the web - HTML5 video and audio
Multimedia on the web - HTML5 video and audio
Ā 
Android Multimedia Support
Android Multimedia SupportAndroid Multimedia Support
Android Multimedia Support
Ā 
Imovie techpd
Imovie techpdImovie techpd
Imovie techpd
Ā 
Core Audio in iOS 6 (CocoaConf Portland, Oct. '12)
Core Audio in iOS 6 (CocoaConf Portland, Oct. '12)Core Audio in iOS 6 (CocoaConf Portland, Oct. '12)
Core Audio in iOS 6 (CocoaConf Portland, Oct. '12)
Ā 
Video and Audio in Learning
Video and Audio in LearningVideo and Audio in Learning
Video and Audio in Learning
Ā 
Joshfire Framework 0.9 Technical Overview
Joshfire Framework 0.9 Technical OverviewJoshfire Framework 0.9 Technical Overview
Joshfire Framework 0.9 Technical Overview
Ā 
Media hardware and softwares used to create my media product
Media hardware and softwares used to create my media product Media hardware and softwares used to create my media product
Media hardware and softwares used to create my media product
Ā 

More from Chris Adamson

Whatever Happened to Visual Novel Anime? (AWA/Youmacon 2018)
Whatever Happened to Visual Novel Anime? (AWA/Youmacon 2018)Whatever Happened to Visual Novel Anime? (AWA/Youmacon 2018)
Whatever Happened to Visual Novel Anime? (AWA/Youmacon 2018)Chris Adamson
Ā 
Whatever Happened to Visual Novel Anime? (JAFAX 2018)
Whatever Happened to Visual Novel Anime? (JAFAX 2018)Whatever Happened to Visual Novel Anime? (JAFAX 2018)
Whatever Happened to Visual Novel Anime? (JAFAX 2018)Chris Adamson
Ā 
Media Frameworks Versus Swift (Swift by Northwest, October 2017)
Media Frameworks Versus Swift (Swift by Northwest, October 2017)Media Frameworks Versus Swift (Swift by Northwest, October 2017)
Media Frameworks Versus Swift (Swift by Northwest, October 2017)Chris Adamson
Ā 
Fall Premieres: Media Frameworks in iOS 11, macOS 10.13, and tvOS 11 (CocoaCo...
Fall Premieres: Media Frameworks in iOS 11, macOS 10.13, and tvOS 11 (CocoaCo...Fall Premieres: Media Frameworks in iOS 11, macOS 10.13, and tvOS 11 (CocoaCo...
Fall Premieres: Media Frameworks in iOS 11, macOS 10.13, and tvOS 11 (CocoaCo...Chris Adamson
Ā 
CocoaConf Chicago 2017: Media Frameworks and Swift: This Is Fine
CocoaConf Chicago 2017: Media Frameworks and Swift: This Is FineCocoaConf Chicago 2017: Media Frameworks and Swift: This Is Fine
CocoaConf Chicago 2017: Media Frameworks and Swift: This Is FineChris Adamson
Ā 
Forward Swift 2017: Media Frameworks and Swift: This Is Fine
Forward Swift 2017: Media Frameworks and Swift: This Is FineForward Swift 2017: Media Frameworks and Swift: This Is Fine
Forward Swift 2017: Media Frameworks and Swift: This Is FineChris Adamson
Ā 
Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...
Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...
Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...Chris Adamson
Ā 
Firebase: Totally Not Parse All Over Again (Unless It Is)
Firebase: Totally Not Parse All Over Again (Unless It Is)Firebase: Totally Not Parse All Over Again (Unless It Is)
Firebase: Totally Not Parse All Over Again (Unless It Is)Chris Adamson
Ā 
Revenge of the 80s: Cut/Copy/Paste, Undo/Redo, and More Big Hits (CocoaConf C...
Revenge of the 80s: Cut/Copy/Paste, Undo/Redo, and More Big Hits (CocoaConf C...Revenge of the 80s: Cut/Copy/Paste, Undo/Redo, and More Big Hits (CocoaConf C...
Revenge of the 80s: Cut/Copy/Paste, Undo/Redo, and More Big Hits (CocoaConf C...Chris Adamson
Ā 
Core Image: The Most Fun API You're Not Using, CocoaConf Atlanta, December 2014
Core Image: The Most Fun API You're Not Using, CocoaConf Atlanta, December 2014Core Image: The Most Fun API You're Not Using, CocoaConf Atlanta, December 2014
Core Image: The Most Fun API You're Not Using, CocoaConf Atlanta, December 2014Chris Adamson
Ā 
Core Image: The Most Fun API You're Not Using (CocoaConf Columbus 2014)
Core Image: The Most Fun API You're Not Using (CocoaConf Columbus 2014)Core Image: The Most Fun API You're Not Using (CocoaConf Columbus 2014)
Core Image: The Most Fun API You're Not Using (CocoaConf Columbus 2014)Chris Adamson
Ā 
Stupid Video Tricks
Stupid Video TricksStupid Video Tricks
Stupid Video TricksChris Adamson
Ā 
Glitch-Free A/V Encoding (CocoaConf Boston, October 2013)
Glitch-Free A/V Encoding (CocoaConf Boston, October 2013)Glitch-Free A/V Encoding (CocoaConf Boston, October 2013)
Glitch-Free A/V Encoding (CocoaConf Boston, October 2013)Chris Adamson
Ā 
Core Audio in iOS 6 (CocoaConf DC, March 2013)
Core Audio in iOS 6 (CocoaConf DC, March 2013)Core Audio in iOS 6 (CocoaConf DC, March 2013)
Core Audio in iOS 6 (CocoaConf DC, March 2013)Chris Adamson
Ā 
Mobile Movies with HTTP Live Streaming (CocoaConf DC, March 2013)
Mobile Movies with HTTP Live Streaming (CocoaConf DC, March 2013)Mobile Movies with HTTP Live Streaming (CocoaConf DC, March 2013)
Mobile Movies with HTTP Live Streaming (CocoaConf DC, March 2013)Chris Adamson
Ā 
Core Audio in iOS 6 (CocoaConf Chicago, March 2013)
Core Audio in iOS 6 (CocoaConf Chicago, March 2013)Core Audio in iOS 6 (CocoaConf Chicago, March 2013)
Core Audio in iOS 6 (CocoaConf Chicago, March 2013)Chris Adamson
Ā 
Core Audio Intro (Detroit Mobile City 2013)
Core Audio Intro (Detroit Mobile City 2013)Core Audio Intro (Detroit Mobile City 2013)
Core Audio Intro (Detroit Mobile City 2013)Chris Adamson
Ā 
Objective-C Is Not Java
Objective-C Is Not JavaObjective-C Is Not Java
Objective-C Is Not JavaChris Adamson
Ā 
Core Audio in iOS 6 (CocoaConf Raleigh, Dec. '12)
Core Audio in iOS 6 (CocoaConf Raleigh, Dec. '12)Core Audio in iOS 6 (CocoaConf Raleigh, Dec. '12)
Core Audio in iOS 6 (CocoaConf Raleigh, Dec. '12)Chris Adamson
Ā 

More from Chris Adamson (19)

Whatever Happened to Visual Novel Anime? (AWA/Youmacon 2018)
Whatever Happened to Visual Novel Anime? (AWA/Youmacon 2018)Whatever Happened to Visual Novel Anime? (AWA/Youmacon 2018)
Whatever Happened to Visual Novel Anime? (AWA/Youmacon 2018)
Ā 
Whatever Happened to Visual Novel Anime? (JAFAX 2018)
Whatever Happened to Visual Novel Anime? (JAFAX 2018)Whatever Happened to Visual Novel Anime? (JAFAX 2018)
Whatever Happened to Visual Novel Anime? (JAFAX 2018)
Ā 
Media Frameworks Versus Swift (Swift by Northwest, October 2017)
Media Frameworks Versus Swift (Swift by Northwest, October 2017)Media Frameworks Versus Swift (Swift by Northwest, October 2017)
Media Frameworks Versus Swift (Swift by Northwest, October 2017)
Ā 
Fall Premieres: Media Frameworks in iOS 11, macOS 10.13, and tvOS 11 (CocoaCo...
Fall Premieres: Media Frameworks in iOS 11, macOS 10.13, and tvOS 11 (CocoaCo...Fall Premieres: Media Frameworks in iOS 11, macOS 10.13, and tvOS 11 (CocoaCo...
Fall Premieres: Media Frameworks in iOS 11, macOS 10.13, and tvOS 11 (CocoaCo...
Ā 
CocoaConf Chicago 2017: Media Frameworks and Swift: This Is Fine
CocoaConf Chicago 2017: Media Frameworks and Swift: This Is FineCocoaConf Chicago 2017: Media Frameworks and Swift: This Is Fine
CocoaConf Chicago 2017: Media Frameworks and Swift: This Is Fine
Ā 
Forward Swift 2017: Media Frameworks and Swift: This Is Fine
Forward Swift 2017: Media Frameworks and Swift: This Is FineForward Swift 2017: Media Frameworks and Swift: This Is Fine
Forward Swift 2017: Media Frameworks and Swift: This Is Fine
Ā 
Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...
Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...
Firebase: Totally Not Parse All Over Again (Unless It Is) (CocoaConf San Jose...
Ā 
Firebase: Totally Not Parse All Over Again (Unless It Is)
Firebase: Totally Not Parse All Over Again (Unless It Is)Firebase: Totally Not Parse All Over Again (Unless It Is)
Firebase: Totally Not Parse All Over Again (Unless It Is)
Ā 
Revenge of the 80s: Cut/Copy/Paste, Undo/Redo, and More Big Hits (CocoaConf C...
Revenge of the 80s: Cut/Copy/Paste, Undo/Redo, and More Big Hits (CocoaConf C...Revenge of the 80s: Cut/Copy/Paste, Undo/Redo, and More Big Hits (CocoaConf C...
Revenge of the 80s: Cut/Copy/Paste, Undo/Redo, and More Big Hits (CocoaConf C...
Ā 
Core Image: The Most Fun API You're Not Using, CocoaConf Atlanta, December 2014
Core Image: The Most Fun API You're Not Using, CocoaConf Atlanta, December 2014Core Image: The Most Fun API You're Not Using, CocoaConf Atlanta, December 2014
Core Image: The Most Fun API You're Not Using, CocoaConf Atlanta, December 2014
Ā 
Core Image: The Most Fun API You're Not Using (CocoaConf Columbus 2014)
Core Image: The Most Fun API You're Not Using (CocoaConf Columbus 2014)Core Image: The Most Fun API You're Not Using (CocoaConf Columbus 2014)
Core Image: The Most Fun API You're Not Using (CocoaConf Columbus 2014)
Ā 
Stupid Video Tricks
Stupid Video TricksStupid Video Tricks
Stupid Video Tricks
Ā 
Glitch-Free A/V Encoding (CocoaConf Boston, October 2013)
Glitch-Free A/V Encoding (CocoaConf Boston, October 2013)Glitch-Free A/V Encoding (CocoaConf Boston, October 2013)
Glitch-Free A/V Encoding (CocoaConf Boston, October 2013)
Ā 
Core Audio in iOS 6 (CocoaConf DC, March 2013)
Core Audio in iOS 6 (CocoaConf DC, March 2013)Core Audio in iOS 6 (CocoaConf DC, March 2013)
Core Audio in iOS 6 (CocoaConf DC, March 2013)
Ā 
Mobile Movies with HTTP Live Streaming (CocoaConf DC, March 2013)
Mobile Movies with HTTP Live Streaming (CocoaConf DC, March 2013)Mobile Movies with HTTP Live Streaming (CocoaConf DC, March 2013)
Mobile Movies with HTTP Live Streaming (CocoaConf DC, March 2013)
Ā 
Core Audio in iOS 6 (CocoaConf Chicago, March 2013)
Core Audio in iOS 6 (CocoaConf Chicago, March 2013)Core Audio in iOS 6 (CocoaConf Chicago, March 2013)
Core Audio in iOS 6 (CocoaConf Chicago, March 2013)
Ā 
Core Audio Intro (Detroit Mobile City 2013)
Core Audio Intro (Detroit Mobile City 2013)Core Audio Intro (Detroit Mobile City 2013)
Core Audio Intro (Detroit Mobile City 2013)
Ā 
Objective-C Is Not Java
Objective-C Is Not JavaObjective-C Is Not Java
Objective-C Is Not Java
Ā 
Core Audio in iOS 6 (CocoaConf Raleigh, Dec. '12)
Core Audio in iOS 6 (CocoaConf Raleigh, Dec. '12)Core Audio in iOS 6 (CocoaConf Raleigh, Dec. '12)
Core Audio in iOS 6 (CocoaConf Raleigh, Dec. '12)
Ā 

Recently uploaded

08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
Ā 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
Ā 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
Ā 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
Ā 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
Ā 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
Ā 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
Ā 
šŸ¬ The future of MySQL is Postgres šŸ˜
šŸ¬  The future of MySQL is Postgres   šŸ˜šŸ¬  The future of MySQL is Postgres   šŸ˜
šŸ¬ The future of MySQL is Postgres šŸ˜RTylerCroy
Ā 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
Ā 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
Ā 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
Ā 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
Ā 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
Ā 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
Ā 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
Ā 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel AraĆŗjo
Ā 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
Ā 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
Ā 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
Ā 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
Ā 

Recently uploaded (20)

08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
Ā 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
Ā 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
Ā 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
Ā 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
Ā 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Ā 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
Ā 
šŸ¬ The future of MySQL is Postgres šŸ˜
šŸ¬  The future of MySQL is Postgres   šŸ˜šŸ¬  The future of MySQL is Postgres   šŸ˜
šŸ¬ The future of MySQL is Postgres šŸ˜
Ā 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
Ā 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
Ā 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
Ā 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
Ā 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Ā 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
Ā 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
Ā 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Ā 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Ā 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Ā 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
Ā 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Ā 

iOS Media APIs (MobiDevDay Detroit, May 2013)

  • 1. iOS Media APIs Chris Adamson ā€¢ @invalidname MobiDevDay ā€¢ Detroit, MI ā€¢ May 4, 2013 Slides will be posted to slideshare.net/invalidname Thursday, May 2, 13
  • 2. Where do I start? Thursday, May 2, 13
  • 3. iOS Media APIs ā€¢ AV Foundation ā€¢ Core Media ā€¢ Core Animation ā€¢ Media Player ā€¢ Core Audio ā€¢ Audio Toolbox ā€¢ Audio Units ā€¢ Core MIDI ā€¢ Open AL Thursday, May 2, 13
  • 4. Also! ā€¢ UIKit ā€¢ UIImagePickerController, remote control events ā€¢ AirPlay ā€¢ HTTP Live Streaming Thursday, May 2, 13
  • 5. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 6. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 8. AV Foundation ā€¢ High-level Obj-C audio/video framework ā€¢ Debuted in iPhone OS 2.3, not fully baked until iOS 4 ā€¢ Consists of three distinct areas of functionality with little overlap Thursday, May 2, 13
  • 9. AVAudioPlayer AVAudioRecorder AVAudioSession AVAudioSessionChannelDescription AVAudioSessionPortDescription AVAudioSessionRouteDescription AVCaptureAudioDataOutput AVCaptureConnection AVCaptureDevice AVCaptureDeviceInput AVCaptureFileOutput AVCaptureInput AVCaptureMetadataOutput AVCaptureMovieFileOutput AVCaptureOutput AVCaptureSession AVCaptureStillImageOutput AVCaptureVideoDataOutput AVCaptureVideoPreviewLayer AVAsset AVAssetExportSession AVAssetImageGenerator AVAssetReader AVAssetReaderAudioMixOutput AVAssetReaderOutput AVAssetReaderTrackOutput AVAssetReaderVideoCompositionOutput AVAssetResourceLoader AVAssetResourceLoadingRequest AVAssetTrack AVAssetTrackSegment AVAssetWriter AVAssetWriterInput AVAssetWriterInputPixelBufferAdaptor AVAudioMix AVAudioMixInputParameters AVComposition AVCompositionTrack AVCompositionTrackSegment AVMediaSelectionGroup AVMediaSelectionOption AVMetadataFaceObject AVMetadataItem AVMetadataObject AVMutableAudioMix AVMutableAudioMixInputParameters AVMutableComposition AVMutableCompositionTrack AVMutableMetadataItem AVMutableTimedMetadataGroup AVMutableVideoComposition AVMutableVideoCompositionInstruction AVMutableVideoCompositionLayerInstruction AVPlayer AVPlayerItem AVPlayerItemAccessLog AVPlayerItemAccessLogEvent AVPlayerItemErrorLog AVPlayerItemErrorLogEvent AVPlayerItemOutput AVPlayerItemTrack AVPlayerItemVideoOutput AVPlayerLayer AVQueuePlayer AVSynchronizedLayer AVTextStyleRule AVTimedMetadataGroup AVURLAsset AVVideoComposition AVVideoCompositionCoreAnimationTool AVVideoCompositionInstruction AVVideoCompositionLayerInstruction Audio Capture Editing / Export / Playback Thursday, May 2, 13
  • 10. AVF audio classes ā€¢ AVAudioPlayer ā€“ plays ļ¬‚at ļ¬les or audio from an NSData ā€¢ AVAudioRecorder ā€“ records from most- recently connected input device (built-in mic, headset, etc.) ā€¢ AVAudioSession ā€“ negotiates with system for access to audio hardware Thursday, May 2, 13
  • 11. AVAudioPlayer ā€¢ initWithContentsOfURL:error: or initWithData:error: ā€¢ URL must be local ā€¢ Methods: play, playAtTime:, pause, stop ā€¢ Properties: volume, pan, numberOfLoops, etc. Thursday, May 2, 13
  • 12. Playing a song NSURL *songURL = [[NSBundle mainBundle] URLForResource:@"Bossa Lounger Long" ! ! ! ! ! ! ! withExtension:@"caf"]; // set up av audio player NSError *err = nil; self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:songURL error:&err]; if (err) { ! NSLog (@"Error creating player: %@", err); } else { ! [self.player play]; } Thursday, May 2, 13
  • 13. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 14. Video Playback ā€¢ Two options:AVPlayer and MPMoviePlayerController ā€¢ Since weā€™re already talking about AV Foundation, letā€™s do AVPlayer and friends for now Thursday, May 2, 13
  • 15. AVF essentials ā€¢ AVAsset ā€“ A time-based, playable item (local or remote) ā€¢ AVPlayer ā€“ Handles playback of one or more AVPlayerItems ā€¢ Each AVPlayerItem is associated with an AVAsset ā€¢ Player does play/pause, seekToTime:, etc. Thursday, May 2, 13
  • 16. AVPlayer video ā€¢ AVPlayerLayer ā€“ A CALayer to present video from an AVLayer ā€¢ CALayer is not a UIResponder, doesnā€™t handle touches.You need to provide your own playback UI. ā€¢ gravity property determines ā€œstretchingā€ of video to ļ¬t layerā€™s bounds Thursday, May 2, 13
  • 17. Playing a video AVURLAsset *asset = [AVURLAsset URLAssetWithURL:url ! ! ! ! ! ! ! options:nil]; AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset]; self.player = [AVPlayer playerWithPlayerItem:playerItem]; NSArray *visualTracks = [asset tracksWithMediaCharacteristic: AVMediaCharacteristicVisual]; if ([visualTracks count] > 0) { ! AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:player]; ! [playerView.layer addSublayer:playerLayer]; ! playerLayer.frame = playerView.layer.bounds; ! playerLayer.videoGravity = AVLayerVideoGravityResizeAspect; } Thursday, May 2, 13
  • 18. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 19. AVF Capture ā€¢ AVCaptureSession ā€“ Coordinates capture activities ā€¢ Discover AVCaptureDevices (mics, camera), create AVCaptureInputs from them, connect to session ā€¢ Create AVCaptureOutputs (ļ¬le, data callbacks), connect to session Thursday, May 2, 13
  • 20. AVF Capture// create capture session, attach default video input self.captureSession = [[AVCaptureSession alloc] init]; NSError *setUpError = nil; AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; if (videoDevice) { ! AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice ! error:&setUpError]; ! if (videoInput) { ! ! [captureSession addInput: videoInput]; ! } } // create a preview layer from the session and add it to UI AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession]; previewLayer.frame = captureView.layer.bounds; previewLayer.videoGravity = AVLayerVideoGravityResizeAspect; [captureView.layer addSublayer:previewLayer]; // start capture session and write to file captureMovieOutput = [[AVCaptureMovieFileOutput alloc] init]; [captureSession addOutput:captureMovieOutput]; [captureSession startRunning]; [captureMovieOutput startRecordingToOutputFileURL:captureMovieURL ! ! ! ! ! ! recordingDelegate:self]; Thursday, May 2, 13
  • 21. AVF Editing ā€¢ AVMutableComposition ā€“Ā An AVAsset for a multi-track movie you build from references to other AVAssets ā€¢ AVMutableCompositionTrack ā€“ Built up with insertTimeRange:ofTrack:atTime:error: Thursday, May 2, 13
  • 22. AVFVideo Effects ā€¢ Create AVMutableMutableVideoInstruction made up of AVMutableVideoCompositionLayerInstructi ons ā€¢ Each instruction works with a video track ā€¢ Instruction ramps opacity or afļ¬ne transform over a time range Thursday, May 2, 13
  • 23. AVF Text/Image effects ā€¢ Create an AVSynchronizedLayer to show the composition ā€¢ Create CALayers, CATextLayers and set CAAnimations on them, then add as sub- layers to the AVSynchronizedLayer Thursday, May 2, 13
  • 24. AVF Export ā€¢ Create AVAssetExportSession with one of the canned presets (audio only, or QuickTime .mov at preset size or quality) ā€¢ If you used layer-based animations, add an AVVideoComposition, with an AVVideoCompositionCoreAnimationTool (yes, itā€™s as hard as it sounds) ā€¢ Call exportAsynchronouslyWithCompletionHandler: Thursday, May 2, 13
  • 25. AVF Editing -(IBAction) handlePerformTapped: (id) sender { ! NSLog (@"handlePerformTapped"); ! NSError *performError = nil; ! // create composition ! self.composition = [[AVMutableComposition alloc] init]; ! // create video tracks a and b ! // note: mediatypes are defined in AVMediaFormat.h ! [trackA! release]; ! trackA = [self.composition addMutableTrackWithMediaType:AVMediaTypeVideo ! ! ! ! ! ! ! ! ! ! preferredTrackID:kCMPersistentTrackID_Invalid]; ! [trackB release]; ! trackB = [self.composition addMutableTrackWithMediaType:AVMediaTypeVideo ! ! ! ! ! ! ! ! ! ! preferredTrackID:kCMPersistentTrackID_Invalid]; // create video instructions NSMutableArray *videoInstructions = [[[NSMutableArray alloc] init] autorelease]; ! // create music track trackMusic = [self.composition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid]; ! CMTimeRange musicTrackTimeRange = CMTimeRangeMake(kCMTimeZero, musicTrackAudioAsset.duration); ! NSError *trackMusicError = nil; ! [trackMusic insertTimeRange:musicTrackTimeRange ! ! ! ! ! ! ofTrack:[musicTrackAudioAsset.tracks objectAtIndex:0] ! ! ! ! ! ! atTime:kCMTimeZero ! ! ! ! ! ! error:&trackMusicError]; ! if (trackMusicError) { ! ! NSLog(@"couldn't create trackMusic: %@", trackMusicError); ! } else { ! ! NSLog (@"created trackMusic"); ! } ! ! // setup the player ! [compositionPlayer release]; ! compositionPlayer = [[AVPlayer playerWithPlayerItem: [AVPlayerItem playerItemWithAsset: composition]] retain]; ! [compositionPlayerLayer removeFromSuperlayer]; ! compositionPlayerLayer = [[AVPlayerLayer playerLayerWithPlayer:compositionPlayer] retain]; ! [compositionView.layer addSublayer:compositionPlayerLayer]; ! compositionPlayerLayer.frame = compositionView.layer.bounds; ! compositionPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect; ! ! [updateScrubberTimer invalidate]; ! [updateScrubberTimer release]; ! updateScrubberTimer = [[NSTimer scheduledTimerWithTimeInterval:0.1 ! ! ! ! ! ! ! ! ! ! ! ! ! ! target:self ! ! ! ! ! ! ! ! ! ! ! ! ! ! selector:@selector(updateScrubber:) ! ! ! ! ! ! ! ! ! ! ! ! ! ! userInfo:nil ! ! ! ! ! ! ! ! ! ! ! ! ! ! repeats:YES] ! ! ! ! ! ! retain]; // the video tracks AVAssetTrack *sourceVideoTrack = [[sourceVideoAsset tracksWithMediaType: AVMediaTypeVideo] objectAtIndex: 0]; ! // pad out the opening with five seconds of blank CMTime videoTracksTime = CMTimeMake(0, VIDEO_TIME_SCALE); CMTime postEditTime = CMTimeAdd (videoTracksTime, CMTimeMakeWithSeconds(FIRST_CUT_TRACK_A_IN_TIME, VIDEO_TIME_SCALE)); [trackA insertEmptyTimeRange:CMTimeRangeMake(kCMTimeZero, postEditTime)]; videoTracksTime = postEditTime; // first shot postEditTime = CMTimeAdd (videoTracksTime, CMTimeMakeWithSeconds(FIRST_CUT_DURATION,VIDEO_TIME_SCALE)); CMTimeRange firstShotRange = CMTimeRangeMake(kCMTimeZero, CMTimeMakeWithSeconds(FIRST_CUT_DURATION, VIDEO_TIME_SCALE)); ! [trackA insertTimeRange:firstShotRange ! ! ! ! ! ofTrack:sourceVideoTrack ! ! ! ! ! atTime:videoTracksTime ! ! ! ! ! error:&performError]; videoTracksTime = postEditTime; // track b needs to insert empty segment up to its first use [trackB insertEmptyTimeRange:CMTimeRangeMake(kCMTimeZero, videoTracksTime)]; postEditTime = CMTimeAdd (videoTracksTime, CMTimeMakeWithSeconds(SECOND_CUT_TRACK_B_IN_TIME,VIDEO_TIME_SCALE)); CMTimeRange secondShotRange = CMTimeRangeMake(CMTimeMakeWithSeconds(SECOND_CUT_SOURCE_TIME, VIDEO_TIME_SCALE), CMTimeMakeWithSeconds(SECOND_CUT_DURATION, VIDEO_TIME_SCALE)); [trackB insertTimeRange:secondShotRange ofTrack:sourceVideoTrack atTime:videoTracksTime error:&performError]; videoTracksTime = postEditTime; // TODO: later segments // desperation cheese - works AVMutableVideoCompositionInstruction *transitionInstruction = [AVMutableVideoCompositionInstruction videoCompositionInstruction]; transitionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, composition.duration); AVMutableVideoCompositionLayerInstruction *aInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack: trackA]; [aInstruction setOpacityRampFromStartOpacity:0.0 toEndOpacity:1.0 timeRange:CMTimeRangeMake(CMTimeMakeWithSeconds(2.9, VIDEO_TIME_SCALE), CMTimeMakeWithSeconds(6.0, VIDEO_TIME_SCALE))]; AVMutableVideoCompositionLayerInstruction *bInstruction = [AVMutableVideoCompositionLayerInstruction videoCompositionLayerInstructionWithAssetTrack: trackB]; [bInstruction setOpacity:0 atTime:kCMTimeZero]; transitionInstruction.layerInstructions = [NSArray arrayWithObjects:aInstruction, bInstruction, nil]; [videoInstructions addObject: transitionInstruction]; // end of desperation cheese // synchronized layer to own all the title layers AVSynchronizedLayer *synchronizedLayer = [AVSynchronizedLayer synchronizedLayerWithPlayerItem:compositionPlayer.currentItem]; synchronizedLayer.frame = [compositionView frame]; [self.view.layer addSublayer:synchronizedLayer]; // main titles CATextLayer *mainTitleLayer = [CATextLayer layer]; mainTitleLayer.string = NSLocalizedString(@"Running Start", nil); mainTitleLayer.font = @"Verdana-Bold"; mainTitleLayer.fontSize = videoSize.height / 8; mainTitleLayer.foregroundColor = [[UIColor yellowColor] CGColor]; mainTitleLayer.alignmentMode = kCAAlignmentCenter; mainTitleLayer.frame = CGRectMake(0.0, 0.0, videoSize.width, videoSize.height); mainTitleLayer.opacity = 0.0; // initially invisible [synchronizedLayer addSublayer:mainTitleLayer]; // main title opacity animation [CATransaction begin]; [CATransaction setDisableActions:YES]; CABasicAnimation *mainTitleInAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; mainTitleInAnimation.fromValue = [NSNumber numberWithFloat: 0.0]; mainTitleInAnimation.toValue = [NSNumber numberWithFloat: 1.0]; mainTitleInAnimation.removedOnCompletion = NO; mainTitleInAnimation.beginTime = AVCoreAnimationBeginTimeAtZero; mainTitleInAnimation.duration = 5.0; [mainTitleLayer addAnimation:mainTitleInAnimation forKey:@"in-animation"]; CABasicAnimation *mainTitleOutAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; mainTitleOutAnimation.fromValue = [NSNumber numberWithFloat: 1.0]; mainTitleOutAnimation.toValue = [NSNumber numberWithFloat: 0.0]; mainTitleOutAnimation.removedOnCompletion = NO; mainTitleOutAnimation.beginTime = 5.0; mainTitleOutAnimation.duration = 2.0; [mainTitleLayer addAnimation:mainTitleOutAnimation forKey:@"out-animation"]; [CATransaction commit]; // TODO: end credits // tell the player about our effects AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoComposition]; videoComposition.instructions = videoInstructions; videoComposition.renderSize = videoSize; videoComposition.frameDuration = CMTimeMake(1, 30); // 30 fps compositionPlayer.currentItem.videoComposition = videoComposition; // set up the duration label at the right side of the scrubber int durationSeconds = (int) CMTimeGetSeconds (composition.duration); self.durationLabel.text = [NSString stringWithFormat: @"%02d:%02d", durationSeconds / 60, durationSeconds % 60]; // reset rate field and play/pause button state rateField.text = @"0.0"; playPauseButton.selected = NO; ! NSLog (@"bottom of handlePerformTapped"); ! } No, thatā€™s not supposed to be legible. Thursday, May 2, 13
  • 26. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 28. HTTP Live Streaming ā€¢ Apple-led semi-standard streaming format ā€¢ Only stream format allowed on App Store ā€¢ Streams video as series of small (10 sec.) ļ¬les, via ordinary web server on port 80 ā€¢ Create streams with command-line tools, Pro apps (Compressor, Final Cut), server- side transcoders (Wowza) Thursday, May 2, 13
  • 31. HLS Advantages ā€¢ Mobile-friendly: works over spotty cellular connections, stream can provide multiple bitrates (client switches on the ļ¬‚y) ā€¢ No special server software required: can stream from Dropbox ā€¢ Wide adoption: Roku, Xbox,Android, GoogleTV, etc. Thursday, May 2, 13
  • 32. Client-side HLS ā€¢ Create an AVPlayer or MPMoviePlayerController with the streamā€™s .m3u8 URL just like any other URL ā€¢ There is no step 2 Thursday, May 2, 13
  • 33. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 35. Media Player ā€¢ Allows access to the deviceā€™s iTunes library ā€¢ Audio-only: songs, podcasts, audiobooks ā€¢ Discover contents with MPMediaQuery, or show a MPMediaPickerController ā€¢ MPMediaItems have metadata (title, artist, album, cover art, etc.) ā€¢ Play with MPMusicPlayerController Thursday, May 2, 13
  • 36. MPMediaQuery NSString *searchText = searchController.searchBar.text; MPMediaQuery *query = [MPMediaQuery songsQuery]; MPMediaPropertyPredicate *titlePredicate = [MPMediaPropertyPredicate predicateWithValue:searchText ! ! ! forProperty:MPMediaItemPropertyTitle ! ! ! comparisonType: MPMediaPredicateComparisonContains]; [query addFilterPredicate:titlePredicate]; MPMusicPlayerController *iPodController = ! [MPMusicPlayerController iPodMusicPlayer]; [iPodController stop]; [iPodController setQueueWithQuery: query]; [iPodController play]; Thursday, May 2, 13
  • 37. MPMoviePlayerController ā€¢ Simple video player, alternative to AVPlayer ā€¢ Provides its own view and controls ā€¢ Lighter-weight than AVPlayer, which helps on really old devices (iPhone 3GS) Thursday, May 2, 13
  • 38. MP novelties ā€¢ MPNowPlayingInfoCenter ā€“ Access to metadata shown on lock screen and external media displays (e.g., in-car entertainment systems) ā€¢ MPVolumeView ā€“ System-wide volume slider, with AirPlay button if available Thursday, May 2, 13
  • 39. Remote Controls ā€¢ Receive play/pause, forward/back from headset, dock keyboard, in-car systems, other external devices ā€¢ -[UIApplication beginReceivingRemoteControlEvents] ā€¢ Must be able to become ļ¬rst responder Thursday, May 2, 13
  • 40. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 42. AirPlay ā€¢ Wireless audio/video streaming from iOS device to Apple TV,AirPort Express, some speakers ā€¢ Unofļ¬cial third-party clients for Mac (Reļ¬‚ector,Air Sharing), PC,Android, etc. Thursday, May 2, 13
  • 43. AirPlay API ā€¢ There basically isnā€™t one ā€¢ User either mirrors device, or uses AirPlay menu on MPVolumeView or MPMoviePlayerController ā€¢ You can deny (but please donā€™t) with allowsAirPlay (MPMovieController), mediaPlaybackAllowsAirPlay (UIWebView), allowsExternalPlayback (AVPlayer) Thursday, May 2, 13
  • 44. Second screens ā€¢ If user connects toVGA/DVI via Dock/ Lightning adapter, or connects to AirPlay without mirroring, your app will see a second screen ā€¢ Discover with -[UIScreen screens], create new UIWindow for it ā€¢ Chat on the device, video on the second screen? Thursday, May 2, 13
  • 45. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 47. Core Audio ā€¢ C frameworks for real-time audio processing ā€¢ Legendary performance, legendary difļ¬culty ā€¢ Basis of OS X pro audio apps like Logic and GarageBand Thursday, May 2, 13
  • 48. Core Audio ā€¢ Audio Queue ā€¢ Audio Units ā€¢ Open AL ā€¢ Audio File Services ā€¢ Audio Converter Svcs. ā€¢ Extended Audio File Svcs. ā€¢ Audio File Stream Svcs. ā€¢ Audio Session Svcs. Thursday, May 2, 13
  • 49. Core Audio ā€¢ Small number of structures and functions ā€¢ Most behavior is speciļ¬ed by getting and setting properties ā€¢ All functions return OSStatus, must check for noErr before continuing ā€¢ ā€œCreateā€-style functions take pointer as a parameter and populate it Thursday, May 2, 13
  • 50. Audio Queue ā€¢ Convenience API for play-out or capture ā€¢ Wrapped by AV Foundationā€™s AVAudioRecorder,AVAudioPlayer for ļ¬le- only scenarios ā€¢ For play-out, app provides buffers to play ā€¢ For captuer, queue gives app with buffers of capture data Thursday, May 2, 13
  • 56. Parsing Web Radio NSData NSData Packets Packets Packets Packets Packets NSURLConnection delivers NSData buffers, containing audio and framing info.We pass it to Audio File Services. Thursday, May 2, 13
  • 57. Parsing Web Radio NSData NSData Packets Packets Packets Packets Packets Packets Packets Packets Packets Packets NSURLConnection delivers NSData buffers, containing audio and framing info.We pass it to Audio File Services. Audio File Services calls us back with parsed packets of audio data. Thursday, May 2, 13
  • 58. Parsing Web Radio NSData NSData Packets Packets Packets Packets Packets Packets Packets Packets Packets Packets 012 Packets Packets Packets Packets Packets Packets NSURLConnection delivers NSData buffers, containing audio and framing info.We pass it to Audio File Services. Audio File Services calls us back with parsed packets of audio data. We create an AudioQueueBuffer with those packets and enqueue it for play-out. Thursday, May 2, 13
  • 59. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 61. Audio Units ā€¢ Lowest level of audio processing available to third parties ā€¢ I/O, effects, mixing, ļ¬le player, synthesis ā€¢ Extremely low latency I/O (< 10 ms) Thursday, May 2, 13
  • 68. AURemoteIO Buses AURemoteIO bus 0 to output H/W Thursday, May 2, 13
  • 69. AURemoteIO Buses AURemoteIO bus 0 to output H/W bus 0 from app Thursday, May 2, 13
  • 70. AURemoteIO Buses AURemoteIO bus 0 to output H/W bus 1 from input H/W bus 0 from app Thursday, May 2, 13
  • 71. AURemoteIO Buses AURemoteIO bus 0 to output H/W bus 1 from input H/W bus 1 to app bus 0 from app Thursday, May 2, 13
  • 72. Pass Through AURemoteIO bus 1 from input H/W bus 0 to output H/W Thursday, May 2, 13
  • 73. Pass-Through with Effect bus 0 to output H/W AURemoteIO AUEffect bus 1 from input H/W Thursday, May 2, 13
  • 74. Core Audio code -(void) setUpAUGraph { ! if (self.auGraph) { ! ! CheckError(AUGraphClose(self.auGraph), ! ! ! ! "Couldn't close old AUGraph"); ! ! CheckError (DisposeAUGraph(self.auGraph), ! ! ! ! ! "Couldn't dispose old AUGraph"); ! } ! ! CheckError(NewAUGraph(&_auGraph), ! ! ! "Couldn't create new AUGraph"); ! ! CheckError(AUGraphOpen(self.auGraph), ! ! ! "Couldn't open AUGraph"); ! ! AudioComponentDescription outputcd = {0}; ! outputcd.componentType = kAudioUnitType_Output; ! outputcd.componentSubType = kAudioUnitSubType_RemoteIO; ! outputcd.componentManufacturer = kAudioUnitManufacturer_Apple; ! ! AUNode ioNode; ! CheckError(AUGraphAddNode(self.auGraph, ! ! ! ! &outputcd, ! ! ! ! &ioNode), ! ! ! "couldn't add remote io node"); ! ! // get the remote io unit from the node ! CheckError(AUGraphNodeInfo(self.auGraph, ! ! ! ! ioNode, ! ! ! ! NULL, ! ! ! ! &_ioUnit), ! ! ! "couldn't get remote io unit"); ! ! ! // effect unit here ! AudioComponentDescription effectcd = {0}; ! effectcd.componentType = kAudioUnitType_FormatConverter; ! effectcd.componentSubType = kAudioUnitSubType_NewTimePitch; ! effectcd.componentManufacturer = kAudioUnitManufacturer_Apple; ! ! AUNode effectNode; ! CheckError(AUGraphAddNode(self.auGraph, ! ! ! ! &effectcd, ! ! ! ! &effectNode), ! ! ! "couldn't get effect node [time/pitch]"); ! ! // get effect unit from the node ! CheckError(AUGraphNodeInfo(self.auGraph, ! ! ! ! effectNode, ! ! ! ! NULL, ! ! ! ! &_effectUnit), ! ! ! "couldn't get effect unit from node"); ! ! // enable input on the remote io unit UInt32 oneFlag = 1; UInt32 busZero = 0; ! CheckError(AudioUnitSetProperty(self.ioUnit, ! ! ! ! kAudioOutputUnitProperty_EnableIO, ! ! ! ! kAudioUnitScope_Output, ! ! ! ! busZero, ! ! ! ! &oneFlag, ! ! ! ! sizeof(oneFlag)), ! ! ! "Couldn't enable output on bus 0"); ! UInt32 busOne = 1; ! CheckError(AudioUnitSetProperty(self.ioUnit, ! ! ! ! kAudioOutputUnitProperty_EnableIO, ! ! ! ! kAudioUnitScope_Input, ! ! ! ! busOne, ! ! ! ! &oneFlag, ! ! ! ! sizeof(oneFlag)), ! ! ! "Couldn't enable input on bus 1"); ! ! // set stream format that the effect wants ! AudioStreamBasicDescription streamFormat; ! UInt32 propertySize = sizeof (streamFormat); ! CheckError(AudioUnitGetProperty(self.effectUnit, kAudioUnitProperty_StreamFormat, ! ! ! ! ! kAudioUnitScope_Input, ! ! ! ! ! 0, ! ! ! ! ! &streamFormat, ! ! ! ! ! &propertySize), ! ! ! "Couldn't get effect unit stream format"); ! ! CheckError(AudioUnitSetProperty(self.ioUnit, kAudioUnitProperty_StreamFormat, ! ! ! ! ! kAudioUnitScope_Output, ! ! ! ! ! busOne, ! ! ! ! ! &streamFormat, ! ! ! ! ! sizeof(streamFormat)), ! ! ! "couldn't set stream format on iounit bus 1 output"); ! CheckError(AudioUnitSetProperty(self.ioUnit, ! kAudioUnitProperty_StreamFormat, ! ! ! ! kAudioUnitScope_Input, ! ! ! ! ! busZero, ! ! ! ! ! &streamFormat, ! ! ! ! ! sizeof(streamFormat)), ! ! ! "couldn't set stream format on iounit bus 0 input"); ! ! ! ! CheckError(AUGraphConnectNodeInput(self.auGraph, ! ! ! ! ! ioNode, ! ! ! 1, ! ! ! ! ! effectNode, ! ! ! ! ! 0), ! ! ! "couldn't connect remoteio bus 1 output to effect bus 0 input"); ! ! CheckError(AUGraphConnectNodeInput(self.auGraph, ! ! ! ! ! effectNode, ! ! ! ! ! 0, ! ! ! ! ! ioNode, ! ! ! ! ! 0), ! ! ! "couldn't connect effect bus 0 output to remoteio bus 0 input"); ! ! ! CheckError(AUGraphInitialize(self.auGraph), ! ! ! "Couldn't initialize AUGraph"); ! ! CheckError(AUGraphStart(self.auGraph), ! ! ! "Couldn't start AUGraph"); ! ! ! ! NSLog (@"bottom of setUpAUGraph"); } No, this isnā€™t supposed to be readable either Thursday, May 2, 13
  • 75. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 77. Core MIDI ā€¢ Handles MIDI events from external devices ā€¢ Connect via Dock/Lightning connectors or Camera Connection Kit (USB) ā€¢ Only provides callbacks on events (key up, key down, pitch bend, etc.) ā€” up to you do something with it Thursday, May 2, 13
  • 78. MIDI Packets ā€¢ High nybble of status is command, low is channel number ā€¢ Data 1 & 2 depend on command STATUS DATA 1 DATA 2 Thursday, May 2, 13
  • 79. Handling MIDI packetsstatic void! MyMIDIReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon) { ! SNFMasterViewController *myVC = (__bridge SNFMasterViewController*) refCon; ! MIDIPacket *packet = (MIDIPacket *)pktlist->packet;! ! for (int i=0; i < pktlist->numPackets; i++) { ! ! Byte midiStatus = packet->data[0]; ! ! Byte midiCommand = midiStatus >> 4; ! ! // is it a note-on or note-off ! ! if ((midiCommand == 0x09) || ! ! ! (midiCommand == 0x08)) { ! ! ! Byte note = packet->data[1] & 0x7F; ! ! ! Byte velocity = packet->data[2] & 0x7F; ! ! ! printf("midiCommand=%d. Note=%d, Velocity=%dn", midiCommand, note, velocity); ! ! ! ! ! ! // send to augraph ! ! ! CheckError(MusicDeviceMIDIEvent (myVC.auSampler, ! ! ! ! ! ! ! ! ! ! ! midiStatus, ! ! ! ! ! ! ! ! ! ! ! note, ! ! ! ! ! ! ! ! ! ! ! velocity, ! ! ! ! ! ! ! ! ! ! ! 0), ! ! ! ! ! "Couldn't send MIDI event"); ! ! ! ! ! } ! ! packet = MIDIPacketNext(packet); ! } } Thursday, May 2, 13
  • 80. How Do I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 82. OpenAL ā€¢ Cross-platform C API to create positional sound ā€¢ Designed to resemble OpenGL ā€¢ Low latency, ideal for games ā€¢ Calls set an error ļ¬‚ag, must check with alGetError() after every AL call Thursday, May 2, 13
  • 83. AL example // set up OpenAL source alGenSources(1, player.sources); alSourcei(player.sources[0], AL_LOOPING, AL_TRUE); alSourcef(player.sources[0], AL_GAIN, AL_MAX_GAIN); updateSourceLocation(player); // connect buffer to source alSourcei(player.sources[0], AL_BUFFER, buffers[0]); // set up listener alListener3f (AL_POSITION, 0.0, 0.0, 0.0); // start playing alSourcePlay(player.sources[0]); Note: error checking removed for clarity Thursday, May 2, 13
  • 84. OpenAL Concepts ā€¢ ALListener ā€“ The listener, who has an x,y,z position, orientation, etc. ā€¢ ALSource ā€“ A sound producing object in the space. Has position, orientation, motion, sound cone, much more ā€¢ ALBuffer ā€“ Buffers of sound attached to a source. Source can loop one buffer or receive a stream of buffers Thursday, May 2, 13
  • 85. How Did I? ā€¢ Play music on my title screen? ā€¢ Play a video in my app? ā€¢ Capture, edit, and export video? ā€¢ Play streaming video from my web site? ā€¢ Play userā€™s iTunes music? ā€¢ Play a video on an AppleTV? ā€¢ Play web radio? ā€¢ Mix and perform effects on audio? ā€¢ Use MIDI devices? ā€¢ Create in-game sounds for a 3D game? Thursday, May 2, 13
  • 86. iOS Media APIs ā€¢ There are a LOT of them! ā€¢ Each ļ¬lls a speciļ¬c role, not a lot of overlap ā€¢ Simple stuff is easy, complex stuff is possible Thursday, May 2, 13
  • 87. Questions? ā€¢ ā€œAudio andVideo Starting Pointā€ in Apple developer documentation ā€¢ http://devforums.apple.com ā€¢ coreaudio-api@lists.apple.com Thursday, May 2, 13
  • 88. iOS Media APIs Chris Adamson ā€¢ @invalidname MobiDevDay ā€¢ Detroit, MI ā€¢ May 4, 2013 Slides will be posted to slideshare.net/invalidname Thursday, May 2, 13