dvbcss-synckit-ios
SyncController Framework

This library provides SyncController classes that can be used to synchronise a native media player to a given timeline. Currently, a SyncController class is provided for each media player/web kit.

It is planned to coalesce these into a single implementation in the future.

SyncController objects must be initialised with at least the following objects: * a media player (player objects, or player ViewController objects, from the AudioPlayerEngine or [../VideoPlayer) frameworks or in the case of a web view, a UIWebView instance) * a timeline to synchronise to (e.g. the Synchronisation Timeline - our local estimate of the TV’s timeline) * a correlation timestamp (a pair of timestamps) describing the relationship between the media timeline and the Synchronisation Timeline

Dependencies

This framework requires the following dynamic libraries (iOS frameworks) (found in SyncKit):

Overview

TODO (Matt): write something here summarising what is in this library and how it works, once Rajiv has updated the more detailed stuff below.

How to use

1. Add the framework and its dependencies to your project

A Cocoa Pod version of this library is not currently available. To use this library, you must add it and its dependencies to your project.

You will need the following projects from this repository:

Either include them in your workspace and build them; or build them in this repository’s synckit.xcworkspace

Then add them under Linked Frameworks and libraries in your project’s target configuration:

  • SyncKitConfiguration.framework
  • SimpleLogger.framework
  • VideoPlayer.framework
  • AudioPlayerEngine.framework
  • ClockTimelines.framework

If you have two XCode instances running you can drag and drop the framework files from their respective project in SyncKit to your own project.

2. Import the header files

Import this header file into your source file:


#import <SyncController/SyncController.h>

Create and configure a video SyncController object

When a Synchronisation Timeline is available, a VideoPlayerSyncController can be initialised with a video player, the Synchronisation Timeline and a correlation timestamp and then started. The change in the available property is observed using Key-Value-Observer pattern.

A SyncController object uses a timer to trigger a resync operation (reevaluating the media player’s current time w.r.t. the expected media time).

The resync algorithm uses a simple strategy to catchup - if the asynchrony between the media player and the TV is more than reSyncJitterThreshold seconds, it requests the media player to seek to the new time position. The default value is 0.02s for the reSyncJitterThreshold of a VideoPlayerSyncController object is 0,02s.

...
@property(nonatomic, readwrite) VideoPlayerSyncController * vSyncController;
...

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    if (context == WallClockContext) {
        if ([keyPath isEqualToString:kAvailableKey])
        {
            NSNumber *newAvailability = [change objectForKey:@"new"];

            NSLog(@"ViewController: WallClock is synchronised.");

            // only start timeline sync when wallclock is in sync
            if (([newAvailability boolValue] == YES) && (_tvTimelineSyncer==nil)){
                NSLog(@"ViewController: synchronising timeline");
                [self startTimelineSync];
            }

        }
     }
    else if (context == TVTimelineContext) {

      if ([keyPath isEqualToString:kAvailableKey]) {

            BOOL oldTVTimelineAvailable = [[change objectForKey:@"old"]boolValue];
            BOOL newTVTimelineAvailable = [[change objectForKey:@"new"]boolValue];

            if (newTVTimelineAvailable){

                // start the video player
                [self startVideo];

                // setup a sync controller for video player
                Correlation corel = [CorrelationFactory create:0 Correlation:0];

                self.vSyncController = [VideoPlayerSyncController
                                        syncControllerWithVideoPlayer:self.videoPlayer
                                                        SyncTimeline:self.tvTimeline
                                                CorrelationTimestamp:&corel
                                                        SyncInterval:4.0
                                                        AndDelegate:self];
                [self.vSyncController start];
            }
        }
    }
}

Observe the SyncController status

Each SyncController object can have a delegate that conforms SyncControllerDelegate protocol. The delegate will then receive callbacks when the SyncController changes state. Possible SyncController states are:


typedef NS_ENUM(NSUInteger, VideoSyncControllerState)
{
    VideoSyncCrtlInitialised = 1,
    VideoSyncCrtlRunning,
    VideoSyncCrtlStopped,
    VideoSyncCrtlPaused,
    VideoSyncCrtlSynchronising,
    VideoSyncCrtlSyncTimelineUnavailable,
    VideoSyncCrtlSyncTimelineAvailable
};

Here is an example of a state change callback handler:


- (void) SyncController:(id) controller DidChangeState:(NSUInteger) state
{
    if (state == VideoSyncCrtlSyncTimelineAvailable) {

        if (![self.videoPlayer isPlaying])
        {
            [self.videoPlayer play];
        }
    }
}

Run the example apps

Three demo apps are included with this library: * VideoSyncDemoApp - synchronising an HLS stream or a file-based video asset to a DVB-CSS TV * AudioSyncDemoApp - synchronising an audio stream (mp3, aac, etc.) to a DVB-CSS TV * WebViewSyncDemoApp - synchronising a web page animation to a DVB-CSS TV

To run these demo apps, you’ll need the companion and TV assets. You can download them here.

In each demo app project, you will need to specify the following constants:


NSString *serverAddress     = @"192.168.1.74";    // TV's IP address
NSString *contentId         = @"http://127.0.0.1:8123/channel_B_video.mp4";  // contentId of TV asset
NSString *timelineSelector  = @"tag:rd.bbc.co.uk,2015-12-08:dvb:css:timeline:simple-elapsed-time:5000";
NSString *tsEndpointURL     = @"ws://192.168.1.74:7681/ts";
int tick_rate = 5000;

To discover valid values for the contentId, timelineSelector and tsEndpointURL, you may use a CII client to connect to your TV.

$ python examples/CIIClient.py ws:/<TV_IP_ADDRESS>:7681/cii

What the received CII info may look like:


RD000400:pydvbcss rajivr$ python examples/CIIClient.py ws://10.5.11.163:7681/cii
INFO:CIIClient:connected
INFO:CIIClient:change to presentationStatus property. Value is now: [u'okay']
INFO:CIIClient:change to protocolVersion property. Value is now: 1.1
INFO:CIIClient:change to mrsUrl property. Value is now: None
INFO:CIIClient:change to timelines property. Value is now: [TimelineOption(timelineSelector="tag:rd.bbc.co.uk,2015-12-08:dvb:css:timeline:simple-elapsed-time:5000", unitsPertick=1, unitsPerSecond=5000, accuracy=OMIT private=OMIT), TimelineOption(timelineSelector="tag:rd.bbc.co.uk,2015-12-08:dvb:css:timeline:simple-elapsed-time:1000", unitsPertick=1, unitsPerSecond=1000, accuracy=OMIT private=OMIT)]
INFO:CIIClient:change to tsUrl property. Value is now: ws://10.5.11.163:7681/ts
INFO:CIIClient:change to wcUrl property. Value is now: udp://10.5.11.163:6677
INFO:CIIClient:change to contentIdStatus property. Value is now: final
INFO:CIIClient:change to contentId property. Value is now: http://127.0.0.1:8123/channel_B_video.mp4
INFO:CIIClient:CII is now: CII(presentationStatus=[u'okay'], protocolVersion=u'1.1', mrsUrl=None, timelines=[TimelineOption(timelineSelector="tag:rd.bbc.co.uk,2015-12-08:dvb:css:timeline:simple-elapsed-time:5000", unitsPertick=1, unitsPerSecond=5000, accuracy=OMIT private=OMIT), TimelineOption(timelineSelector="tag:rd.bbc.co.uk,2015-12-08:dvb:css:timeline:simple-elapsed-time:1000", unitsPertick=1, unitsPerSecond=1000, accuracy=OMIT private=OMIT)], tsUrl=u'ws://10.5.11.163:7681/ts', wcUrl=u'udp://10.5.11.163:6677', contentIdStatus=u'final', contentId=u'http://127.0.0.1:8123/channel_B_video.mp4')

  • The contentId in this example is http://127.0.0.1:8123/channel_B_video.mp4
  • The timelineSelector is tag:rd.bbc.co.uk,2015-12-08:dvb:css:timeline:simple-elapsed-time:5000,
  • The timeline synchronisation server (tsURL) is ws://10.5.11.163:7681/ts

Licence

The SyncController iOS Framework is developed by BBC R&D and distributed under Licensed under the Apache License, Version 2.0.

© Copyright 2016 BBC R&D. All Rights Reserved