Skip to content

Retiming

On user level retiming is used to change playback speed of strips.

In summary, this is done in 2 ways: - Linear interpolation for changing speed or stopping playback - Ramp curve to make transition between 2 speeds

Retiming data

Retimed strip range, also called segment is deliminated by retiming keys SeqRetimingKey. Data is owned by Strip.

Member strip_frame_index is retiming key position in number of frames from the strip start. This value is in time domain of strip content.

Member retiming_factor represents a frame of content. This value has range from 0 to 1, where 0 is first content frame and 1 is last content frame.

Member flag defines key type, remaining members are used as backup to simplify transition rebuilding.

Note: strip_frame_index of last retiming key defines strip length.

Time domains

While linear interpolation sounds very simple, reality is bit more complicated. Strip length and offsets are stored in content time domain. This is to preserve playback speed of movies, when scene frame rate is changed, Strip::media_playback_rate is used to scale strips to correct proportions.

Since retiming key position is relative to strip, their position must also scale with the strip.

In this image you can see a sample strip in 60fps timeline which retimes a 30fps movie.

Middle layer - "Strip in content domain" is what is stored in .blend file, while bottom layer - "Strip in timeline domain" is presented to the user and interacted with.

This means, that there is a lot of code converting one domain to another, which may easily be a source of bugs.

In addition, this is why strip_frame_index is not plain integer. It would be sometimes impossible to place retiming key to exact timeline frame, or retiming could produce different result, if timeline frame rate changes.

Retiming key types

Default type

Is evaluated by linear interpolation between 2 retiming factor values.

Freeze frame

These are same as default type, but both key have same retiming factor value. However having specific type allows the code to differentiate this key type from default one.

Speed transition

Speed transitions always consist of 2 retiming keys between 2 retimed segments. These are evaluated by finding Y value of circular arc tangential to 2 lines defined by neighboring segments.

This makes it possible to resize transtion while frame mapping of neighboring segments remains unchanged and at the same time the transition itself remains smooth.

However this also means, that changing speed of any neighboring segment requires transition to be rebuilt. For this, original_strip_frame_index and original_retiming_factor are used.

Evaluation

Once value of retiming factor is evaluated from retiming data, this is simply multiplied by content length to get content frame.

This image is an example of strip with 2 linear segments and speed transition. Dashed line signifies how normal playback at 1x speed would be evaluated.

Sound retiming

Sound retiming requires special considerations, because sound playback is handled by external library - Audaspace. This library does not support scheme with frame interpolation, but it requires a buffer with playback speed defined on per-frame basis. For this functions BKE_sound_set_scene_sound_pitch_constant_range and BKE_sound_set_scene_sound_pitch_at_frame are used to make this as fast as possible.

RetimingRangeData is a helper struct that holds vector of RetimingRange which defines a speed for each retimed segment of sound strip. In case of speed transition, speed of each frame is evaluated. Audaspace then further interpolates playback speed between individual "samples" it feeds to actual sound device buffer.

Therefore sound retiming is not exact and there could be minor deviations.

Meta strip retiming

It is possible to retime meta strips while strips inside of meta strip are retimed.

For image producing strips, this works simply by first evaluating meta strip retiming to its content frame range following by another retiming evaluation of child strip.

With sound strips this is not possible and RetimingRangeData produced by meta must be combined with RetimingRangeData produced by sound strip.