Example: Timeshift

After completing a zap into a channel, this example begins to record the channel using the media players timeshift functionality. The user can pause the TV, and when unpausing, playback resumes using the Timeshift buffer. It is possible to fastforward and rewind through this buffer.

Delaying the start of Timeshift recording

The timeshift recording is only activated 5 seconds after joining the channel. This is to prevent unintentional activity should the user go quickly zapping through the channels. Starting timeshift immediately on zapping into a channel, while possible, is not recommended for performance reasons.

Timeshift is started with a simple call to the media player. Just specify the length of the time shift buffer in seconds. An exception will be raised if the required capacity is not available. Note that the media player must be in STATE_PLAYING to successfully start timeshift buffering.

mediaPlayer.open(uri);
mediaPlayer.play(1000);

initialDelayID = setTimeout("startTimeshiftBuffering();", 5000);

The code string passed to the setTimeout() javascript function will be executed after 5000ms. The setTimeout call returns an ID number which is saved in the initialDelayID variable. This variable is used to cancel the timeout should the user zap to a new channel before the 5 seconds expires.

if (initialDelayID != -1) {
  clearTimeout(initialDelayID);
  initialDelayID = -1;
}

Events during Timeshift

When the timeshift recording has begun, the screen gets updated with information. This is done in two ways. The first uses a timer which runs every second. This timer updates the current status and calculates the remaining buffer size (relevant for non-circular buffers).

function updateState() {
  if (mediaPlayer.isTimeshiftPlayback()) {
    e_istimeshifting.textContent = "Timeshift playback";
  } else {
    e_istimeshifting.textContent = "Live playback";
  }

  var f = mediaPlayer.getTimeshiftInfo().bufferUsed * 100
            / mediaPlayer.getTimeshiftInfo().bufferCapacity;
  e_bufferremaining.textContent = Math.round((100-f)*100)/100 + "%";
  
  setTimeout("updateState();", 1000);
}

The mediaPlayer.getTimeshiftInfo() function returns a structure containing the timeshift state, buffer size (the requested size may be different from the size which is actually allocated) and the fullness of the buffer.

The second updating uses Events. Three event listeners are registered when the page loads:

mediaPlayer.addEventListener(mediaPlayer.ON_STATE_CHANGED,
                            onStateChanged);
mediaPlayer.addEventListener(mediaPlayer.ON_POSITION_CHANGED,
                            onPositionChanged);
mediaPlayer.addEventListener(mediaPlayer.ON_TIMESHIFT_STATE_CHANGED,
                            onTimeshiftStateChanged);

Each of these listeners displays the event information on screen.

Using the example

Zap into a channel. The video will start playing, and you will see the Media Player status change to STATE_PLAYING. No timeshifting activity occurs just yet, in case you zap onwards to the next channel.

After a few seconds, the timeshift buffering will begin, and the timeshift state can be observed changing to TIMESHIFT_STATE_BUFFERING. The Buffer Remaining time will start to decrease from the initial amount.

Press OK to pause the TV. The "Live playback" indicator will change to "Timeshift playback" to show that this is no longer Live TV. The video will freeze, but the Buffer remaining counter will continue to count downwards as the video is recorded into the timeshift buffer in the background.

Now press OK again to unpause. Playback resumes, but now it is playing from the timeshift buffer. You can also rewind and fast forward within the timeshift buffer now.

Pressing the BLUE button will stop the timeshift buffering, discard the buffer and return to Live playback.

While viewing video from the timeshift buffer, it is possible to fastforward to the end of the timeshift buffer, or play forwards to the end if the buffering was stopped. In this case, an OnStateChanged event with reason "PositionEnd" occurs. There are different ways to handle this situation, for this example I just zap into the current channel again (ie. a return to Live TV playback)

Zapping

The recommended process for zapping is as follows:

Using a circular buffer

You may wish to use a circular buffer. This is done by specifying the following in your boot image configuration file when building the boot image:

kreatv-option-timeshift-config:circular-buffer

See also the platform configuration object, cfg.media.timeshift.playbackpolicy

Note that when using a circular buffer, no TIMESHIFT_STATE_STOPPED is raised when reaching the end of the buffer. Instead, the bufferUsed value will be equal to bufferCapacity, but buffering will still continue.