iPhone App Video Mirroring

How can you show your app to a large group? What if you want to show an app to a client, an investor, or at a trade show? Extensive Googling reveals lots of people asking the question, but no good answer.

I’m the organizer of the Raleigh iPhone Developer’s Meetup and it’s basically impossible for our group’s members to demo their apps. The “crowd people around a phone” method breaks at around four people. And our last meetup had 20 people!

Why can’t we be like Steve, using our apps on our phone, with the display projected for all to see?

I have a solution, if you’re willing to make a special build of your app that’s not meant for the app store. No jailbreaking required! Although a willingness to use private methods is.

Inside the iPhone SDK exists a private API for video output. A class called MPTVOutWindow will display whatever it contains via the video output dock connector. (Thanks to Erica Sadun who discovered this class and figured out how to use it!)

I created a UIApplication category (that is to say, an extension to the existing UIApplication class) that uses MPTVOutWindow to mirror the device display onto the TV display. The goal was to make it seamless — drop the file into a project, recompile, and go. And it’s really just that easy, with a couple of caveats.

Caveat #1: apps that use this won’t be allowed into the App Store. That’s because it uses a couple of private APIs (the MPTVOutWindow class and UIGetScreenImage()). But since you’re already an iPhone application developer, creating a private build for your own use is normal.

Caveat #2: it doesn’t copy parts of the screen that belong to OpenGL. The class could be extended to do that, if you needed to.

Update: actually, it works fine with OpenGL. I demoed an OpenGL game using this at about 20 fps.

Getting Started

First, get a video out cable. It’s the same cable you’d use to watch videos from your iPhone on a TV using the dock connector (note: headphone-jack video cables from older iPods do not work). Apple’s official cable, Apple Component AV Cable, is $50 for composite video. A similar cable is only $14.18 at MonoPrice.com. Component cables are also available.`

Somewhere in your code you need to call start. Anytime after your app’s primary window has been created, call startTVOut:

[[UIApplication] sharedApplication] startTVOut];

That’s about all you need to do. The application category handles everything necessary to mirror the device’s display. The startTVOut method creates the MPTVoutWindow, adds the necessary subviews, rotates them to match your app’s orientation, and centers them to appear properly on the TV. A background thread copies the bits from your main display into a view in the MPTVOutWindow. (You can configure the frames per second in the #define at the top of the file. 12 fps works well for me.)

iPhone app displaying its output on a TV

In my test app, I call it from applicationDidFinishLaunching:. One thing to remember about applicationDidFinishLaunching: is that it gets called before the runloop starts, so your primary window isn’t on screen yet. I call it with a brief delay to give the runloop a chance to get going.

And actually, you don’t even need to call startTVOut. The category can start itself. The code includes an override for a private method called reportAppLaunchFinished:. This undocumented method seems to get called after the app has finished loading. (Being undocumented, I’m not really sure what it does, or what the negative consequences of overriding it has. As far as I can tell, it’s only used to clean up the Default.png display.) I’ve commented out that method, since it’s a bit mysterious. But if you uncomment the method, it will automatically start the TV out display for you. No changes to your code needed!

Mirroring Other Apps?

Since this code runs as part of your app, it stops running when your app stops running. So it’s not a general purpose full-time video mirroring solution.

However, using other private methods, it’s possible to launch other apps while your app remains running, thus mirroring whatever app is in front. I’ve managed to mirror Safari (launched using the private openURL:asPanel: method). I’m sure you can figure ways to mirror other apps using some of the private app launching methods.

Not for Public Consumption!

Since this uses private methods, it would almost certainly not survive Apple’s app review process. To avoid getting your app rejected, you should remove this code from your release builds. This is pretty easy — set the current target to Release and uncheck the checkbox next to the file’s name. Also, if you call startTVOut manually, you’ll need to put some #ifdefs around that call, so it won’t get compiled into release builds.

21 Responses to “iPhone App Video Mirroring”

[...] to pull the video off the iPhone to be displayed on a monitor or projector. To quote Rob’s original article, we can “be like Steve, using our apps on our phone, with the display projected for all to [...]

In fact, it’s possible to do video-out purely via QuartzCore.framework, without linking to MediaPlayer.framework.

(Please forgive any inaccuracies in the following explanation; it has been several months since I last worked on this.)

At the QuartzCore level, every UIWindow is backed by a CAContextImpl, which itself contains a CALayer. CAContextImpl takes a list of options at initialization, one of which lets you select which output display to use: LCD or TVOut.

In my TVOut extension I hook the creation of the CAContextImpl so that the application’s main window appears via video-out (instead of the LCD):

Just wondering, did you work on this for 3.0? I’ve seen online that others have done this for 2.2, and if you’ve worked this on the 3.0 SDK, that would be wonderful. I assume it did, since you worked this after the 3.0 release, but just checking!

yes, it works on 3.0. Thanks a lot for the great code. It can’t be any simpler than this. And I have managed to mirror Safari, but not other apps. Safari gets mirrored fine because safari is embeddable component (UIWebView), but when I launch other apps, my original app closes and stopping the video out.

has anyone successfully able to mirror other apps ? If so, could you share your trick please ?

Rob,
Thanks a bunch for this code, it’s come in handy when developing a prototype app to illustrate the possibilities brought by the iPhone platform.
It certainly works brilliantly when presenting on stage!

I have modify the code to allow for on-the-fly UI orientation changes and touch indicators which show where the user is touching the screen.
I’d be happy to contribute the changes back to you, but embarrassingly wasn’t able to locate your e-mail address. If you’re interested in my changes, please send me an e-mail.

As a side note, the extra CPU power of the iPhone 3GS allows me to run at 20 frames per second with no issues.

wow thats pretty amazing, to have a code for that,…
I am not a coder and have no clue how to program,
but i have a question that i cannot get out of my head,
and after reading your post i even more surprised…
Why does apple not want to output video signals on apps or even better why do they not programm an app for video out? it is possible, the code is here and then the app will not survive Apple’s app review process. Why does apple do that? have you an answer? really sucks… i mean they are forcing people to jailbrake their ipods…

@momo: I completely agree. I can’t believe that I’ve now spent longer on trying to record a high-quality demo video of my app than I did in coding the major functionality in it.

Enabling universal TV Out for iPhones makes makes perfect sense for apple as higher quality demo videos will translate to more sales and thus a higher income for Apple itself from its percentage of those sales.

By the way, contrary to what I wrote above, this code DOES work with OpenGL. I have demoed games written with Unity 3D and Cocos2D using this. If you use a 3GS you can set the TVOut framerate to over 20 fps and it’s very acceptable.

[...] in Cocoa and I was wondering if I cout get some help or a brief tutorial on implementing the UIApplication+TVOut.m in a small project and I am trying to build please any and all help would greatly be [...]