MobileVLCKit and VLCKit, part 3

This is part of an article series covering VLC’s Objective-C framework, which we provide to allow inclusion of all its features in third party applications as well as VLC for iOS and Apple TV.

Previously published:

Today, we will discuss thumbnailing of video content. We need to differenciate two key aspects: saving still images of a currently playing video (snapshot) and previewing media stored somewhere without being played (thumbnail). While either way, VLCKit will open the resource, decode the bitstream and provide you with a image, performance and usability will differ.

Thumbnailing

Let’s start with thumbnailing a non playing media source, which can be stored locally or remotely.

@implementation DummyObject <VLCMediaThumbnailerDelegate>

- (void)workerMethod
{
    // 1
    NSURL *url = [NSURL urlWithString:@""];
    VLCMedia *media = [VLCMedia mediaWithURL:url];

    // 2
    VLCMediaThumbnailer *thumbnailer = [VLCMediaThumbnailer thumbnailerWithMedia:media delegate:self];

    // 3
    CGSize thumbSize = CGSizeMake(800.,600.);
    thumbnailer.thumbnailWidth = thumbSize.width;
    thumbnailer.thumbnailHeight = thumbSize.height;

    // 4
    [thumbnailer fetchThumbnail];
}

- (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail
{
    // 5
    if (thumbnail) {
        UIImage *thumbnailImage = [UIImage imageWithCGImage:thumbnail scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
        if (thumbnailImage) {
            // TODO: do something with the thumbnail!
        }
    }
}

- (void)mediaThumbnailerDidTimeOut:(VLCMediaThumbnailer *)mediaThumbnailer
{
     // TODO: Show a reaction
}

@end
  1. We need to create a NSURL instance along with its VLCMedia representation. Note that the URL may point to both a local or a remote resource.
  2. We create the thumbnailer instance for our media and point to ourselves as a delegate to receive the thumbnail.
  3. We define the size of the resulting thumbnail.  If width and height are set to zero, the video’s original size will be used. If you set either width or height to zero, the aspect-ratio is preserved.
  4. Finally, we call the thumbnailer’s worker function.
  5. Asynchronously, after about two to twenty seconds, we will receive a response from the thumbnailer to the delegate. It is important to check the thumbnail for NULL before trying to bridge it to a UIImage or NSImage as well as afterwards as the translation can fail. That’s all.

You might be wondering how the thumbnailer decides which frame to return. This is based on a more complex algorithm currently depending on the media’s duration and availability of key frames. Future versions may also analyze the image content.
You can overwrite this algorithm with the thumbnailer’s snapshotPosition property (with a 0.0 to 1.0 range).

Snapshots

The VLCMediaPlayer class includes a very basic API, which allows the creation of an infinite number of snapshots during playback, which will be asynchronously stored as local files. The size parameters follow the same pattern as for the thumbnailer.

- (void)workerMethod
{
    // ...
    [_mediaplayer saveVideoSnapshotAt:(NSString *)path withWidth:(int)width andHeight:(int)height];
    // ...
}

As soon as the snapshot was stored, a VLCMediaPlayerSnapshotTaken notification is emitted and mediaPlayerSnapshot: is called on the media player’s delegate. Note that the delegate call is available on iOS and tvOS only.
As a convenience starting in VLCKit 3.0 on iOS and tvOS, the media player class exposes the lastSnapshot and snapshots properties, which provide a UIImage instance of the last shot as well as a list of files of the taken shots.

That’s all for today. Enjoy using VLCKit!