Getting Attached to Video

November 10th, 2009

One of the areas I’ve been refining in this last round of work on MemoryMiner 2.0 is the way that video is displayed in the attachment viewer. Most consumer point-and-shoot cameras take video, so I often shoot short videos that don’t need editing and attach them to photos. One of my favorites is of my son sending a bowl of oatmeal off the edge of his high chair when he was a toddler.

At any rate, the video I had shot was 640 X 480 pixels, and thus when viewed in the MemoryMiner 1.x attachment viewer (which uses a WebView to display all attachments) would have scrollers:

In order to see the playback controls you’d have to scroll. Ugly.

In 2.0 I wanted to fix this, so at first I thought I’d use a QTMovieView, thinking I could have better control over sizing and scaling. This turned out to be a bad solution for two reasons. First is that the video is scaled up in size as the view is resized: chunky ugly video sucks. Secondly, the playback controls aren’t nearly as slick looking as in the QuickTime web browser plugin. Have a look here:

Since I was already using a WebView to display all attachments (because I’m lazy, and for the most part the WebView does a spectacular job of doing the right thing) I thought maybe I could make the HTML to display the video smarter. After some help from Schmichael Padullah (name changed to protect the guilty) I learned about the magic of the max-width/max-height CSS attribute. I created this HTML test:

<html>
<body style=”background-color: rgb(38,38,38);”>
<video controls=”" autoplay=”"
style=”margin: auto; position: absolute; top: 0; right: 0; bottom: 0; left: 0;
max-width:90%; max-height:90%;” name=”media” src=”file:///Users/johnfox/Movies/PieOatmeal.mov”>
</body>
</html>

Works like a champ! So now, for video attachments I programmatically create an HTML string using NSString stringWithFormat so I can set the max-width, max-height and src values then load that into the WebView. The result?

It’s About Time!

November 3rd, 2009

It’s been so long since I last posted, I’m truly embarrassed. However, it’s not without reason. I’ve been so heads down with getting MemoryMiner 2.0 ready for sale, that I’ve simply been ignoring the blog.

Since MemoryMiner is very very nearly ready to ship (Fabio, you’re going to have that beautiful new web site ready for me, right?) I thought it would be nice to add another sneak preview, which is the totally revamped time slider. The time slider in the current 1.x version of MemoryMiner only allows you to search with a resolution of one month:

MM 1.x date range slider

The biggest problem with this time slider is that it doesn’t change resolution as the date range does (i.e. you want to see months and days for a time span of just a few months, or decades and years for a longer time span). Further, at a certain point, you can’t cram in all the markers on a traditional slider: the user never gets accurate results.

This is not an easy problem to solve, but I think I’ve come up with a pretty elegant solution. Behold the new multi-resolution time slider, shown here measuring in decades and years:

MM 2.0 Decades/Years Date range slider

…shown here, measuring in years and months:

MM 2.0 Years/Months Date range slider

…and shown here, measuring in months and days:

MM 2.0 Years/Months Date range slider

It took a tremendous effort to get this all working correctly, and there’s a still a bit graphical tweaking to do, but it’s a world of improvement over the prior solution.

I have tons of ideas for new things to do with timelines, but first I have to ship 2.0, so back to the time machine (I mean coal mine).

PS Another excuse for the lack of blog posts is that I’ve been podcasting regularly on the Mac Developer Network (http://www.mac-developer-network.com/category/shows/). I even did two video podcasts, one of which can be seen here: http://www.pixelcorps.tv/mbkd_031

MDN Episode 4 Now Live

July 15th, 2009

It’s Wednesday, so that can only mean one thing: Scotty has been lax about getting the latest MDN Show podcast edited and ready for the world.

Complaints about the excess time needed to make my crummy audio sound good no longer hold water, since I went out and spent my son’s college education fund on a new mic.

Give a listen:

MDN Show Episode 4

PS Don’t tell anyone that Borris’ real name is Todor.

MDN Episode 3 Now Live

July 8th, 2009

I’m really starting to love this podcasting gig. My friend Borris (not his real name, or is it?) will doubtlessly bitch and moan about the audio quality of my voice (I’m getting a proper mic, I swear), but the witty repartee between me and Scotty is getting better all the time.

Give a listen here:

MDN Episode 3

Don’t forget to leave comments for us.

Would it kill you to hire competent translators?

July 8th, 2009

Having an Italian wife means spending lots of time in Italy. I really enjoy collecting examples of crummy translations, so I couldn’t pass this one up.

Click on the image to see the note in Flickr (created with MemoryMiner, natch).

Be Lazy! (Another Geeky Tale)

June 30th, 2009

A fair number of years writing software has taught me that it pays to be lazy.

While at WWDC a few weeks ago, I showed the current build of MemoryMiner 2.0 to an Apple engineer who happened to have written IKImageBrowser, the gloriously easy-to-use view for displaying scalable thumbnail images. I would have lovvvvvvvvvvved to have used this class, but like many Apple goodies, it simply didn’t exist four years ago when I first began work on MemoryMiner.

He complimented me on the scaling and scrolling speed of the contact sheet view I had painstakingly created. He also pointed out that the initial load time for a given library has a few seconds of lag as it caches thumbnails. To be precise, MemoryMiner caches the NSCachedBitmapImageRep objects that are drawn when the contact sheet’s thumbnails are being scaled or the user is scrolling. There’s a fair amount of overhead in decompressing a JPEG image before it cn be drawn on screen, which is why I bother to cache this data on disk.

The advantage of this approach is that there’s no need for “placeholder” images for when the thumbnails are first being rendered on screen. IKImageBrowser uses such placeholders, which is one of the reasons why I haven’t switched over to using it. At any rate, last week, I decided to bite the bullet and see what I could do to speed up the caching process. As many people will tell you, you can’t optimize what you haven’t measured, so the first thing I did was create a simple tester application. My tester application let me select a given MemoryMiner library and precisely measure the time it takes to go through the various phases of building up the cache.

A MemoryMiner library stores NSCachedBitmapImageRep data as individual files on disk using the NSArchiver class. In version 1.x of the software, each one of these files is loaded from disk as an NSData object before being un-archived and then subsequently stuffed into an NSDictionary. After launch, the application wasn’t ready for use until the entire cache had been populated. If you’ve got several thousand photos, this could add a few seconds to the launch time: not good. Since there are two separate tasks at hand (reading the NSData objects from disk the and un-archiving the data) I wanted to see which took longer: the test app made short work of this. It turns out that the bottleneck here was the actual un-archiving operation, which didn’t really surprise me.

OS X Leopard introduced the handy dandy NSOperationQueue and NSOperation classes which make it quite easy to break a large task into individual operations (e.g. un archiving some data), throw them on a queue and let the OS figure out how to get the job done using one or more background threads. Lazy. With the release of OS X 10.5.7, you can even uses these classes without your app crashing so I decided to give it a try.

Now, when MemoryMiner is launched I create one NSOperation for each archive file. To do this with even tens of thousands of files takes no time, since I create my NSData objects using the wonderfully lazy NSData method “dataWithContentsOfMappedFile:”. This method doesn’t actually read data from disk until the moment it’s actually needed. Lazy. When you create your NSOperationQueue, you have the opportunity to specify the number of threads that will be created using the “setMaxConcurrentOperationCount:” method. Disk bound operations such as reading data from a file can’t really be parallelized.

The end result: MemoryMiner 2.0 now loads the same library 33% faster than in 1.x. and can load libraries with tens of thousands of images which would otherwise cause a spinning beach ball at launch time in version 1.x. All the caching is done in a background thread so the user can get to the fun stuff right away.

Speaking of fun stuff, it’s time for the Daily Show, so off I go.

New Podcasts on Mac Developer Network

June 15th, 2009

One of the greatest things about Apple World Wide Developer Conference (which took place last week) is the chance to catch up in person with one’s friends and colleagues. One such person is Steve Scott (better known as Scotty) on whose most excellent Mac Developer Network I had the great fun of appearing.

Here are two new ones:

http://www.mac-developer-network.com/shows/podcasts/mdnshow/mdn001/

http://www.mac-developer-network.com/shows/podcasts/mdnshow/mdnwwdc09/

During WWDC I also got to record two episodes for the Mac Break Dev show, a quite popular Video Podcast that’s shot in front of a green screen. Look for these links soon.

Fun with Hulu.com

May 13th, 2009



Hulu Offended

Originally uploaded by j4johnfox

Like millions of people, I found the recent Saturday Night Live digital short called “Mother Lover” to be utterly hilarious. I wanted to share it with some family members so went to use Hulu’s share by email functionality.

However, I discovered that the use of the word “piss” (as in “piss in my pants funny”) is too offensive a term to use when describing the video, which, after all, is about two friends agreeing to f*ck each other’s mother as a Mother’s Day gift.

Hilarious.

Fort Collins Memory Project

May 4th, 2009

I love seeing examples of MemoryMiner in use. Here’s an ongoing project (inspired by the Magnes Memory Lab), that’s going on at the Fort Collins Museum & Discovery Science Center:

http://fcmdsc.wordpress.com/2009/05/04/second-installment-of-the-fort-collins-memory-project/

More background on the project can be found here:

http://fcmdsc.wordpress.com/2009/04/01/fort-collins-memory-project/

An interesting point that they brought up in their description of the the project is that they purposefully limited the amount of time that could be used for each story so as to “gently encourage” the participants to think carefully about which items to use as “entry points” into their life stories.

I’m very much looking forward to seeing more of their work.

More Fun with Cappuccino

April 20th, 2009

I’ve been playing with the Cappuccino Framework since it first came out. In the last 2 months, I’ve been working on a secret app, and wondering just how close I could get to the desktop experience in a web browser. Since the app in question works with images (who would have guessed?), and I’m used to working with Apple’s Core Animation framework, I didn’t have very high expectations for deploying in a browser. My initial experiments bore that out: working with images > ~1000 pixels in a browser is not too swift, to put it mildly.

I then started experimenting with a hybrid approach: using Flash for the image display (the Flash player has been hardware accelerated for some time now) and Cappuccino for all the rest.

So far, this approach works quite a bit better than I would have imagined, and I’m about ready to say it’s a game changer, development-wise.