Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert frames to NTSC Drop Frame Timecode

I'm looking for a function that converts an integer value in frames to NTSC Drop Frame Timecode (hh:mm:ss.ff).

I'm using Delphi, but could be in any language.

Thanks

like image 512
Erick Sasse Avatar asked Sep 15 '25 14:09

Erick Sasse


2 Answers

There is a well-known classical solution for that problem...

  • the input frame-count nr is relative to the real framerate, which is allways 30000/1001 ~= 29.97 frames per second for NTSC
  • the calculated result frame-nr is to the nominal framerate of 30fps (and will exhibit a +2frames jump at each full minute, unless the minute is dividable by 10

(of course you may use a smaller int type if you know your value range is limited)

const uint FRAMES_PER_10min = 10*60 * 30000/1001;
const uint FRAMES_PER_1min  =  1*60 * 30000/1001;
const uint DISCREPANCY      = (1*60 * 30) - FRAMES_PER_1min;


/** reverse the drop-frame calculation
 * @param  frameNr raw frame number in 30000/1001 = 29.97fps
 * @return frame number using NTSC drop-frame encoding, nominally 30fps
 */
int64_t
calculate_drop_frame_number (int64_t frameNr)
{
  // partition into 10 minute segments
  lldiv_t tenMinFrames = lldiv (frameNr, FRAMES_PER_10min);

  // ensure the drop-frame incidents happen at full minutes;
  // at start of each 10-minute segment *no* drop incident happens,
  // thus we need to correct discrepancy between nominal/real framerate once: 
  int64_t remainingMinutes = (tenMinFrames.rem - DISCREPANCY) / FRAMES_PER_1min;

  int64_t dropIncidents = (10-1) * tenMinFrames.quot + remainingMinutes;
  return frameNr + 2*dropIncidents;
}                 // perform "drop"

From the resulting "drop" frameNumber, you can calculate the components as usual, using the nominal 30fps framerate...

frames  =    frameNumber % 30
seconds =   (frameNumber / 30) % 60

and so on...

like image 197
Ichthyo Avatar answered Sep 17 '25 08:09

Ichthyo


function FramesToNTSCDropFrameCode(Frames:Integer;FramesPerSecond:Double):string;
var
  iTH, iTM, iTS, iTF : word;
  MinCount, MFrameCount : word;
begin
  DivMod( Frames, Trunc(SecsPerMin * FramesPerSecond), MinCount, MFrameCount );
  DivMod( MinCount, MinsPerHour, iTH, iTM );
  DivMod( MFrameCount, Trunc(FramesPerSecond), ITS, ITF );
  Result := Format('%.2d:%.2d:%.2d.%.2d',[iTH,iTM,iTS,iTF]);
end;

You will need to copy the DivMod routine from the SysUtils unit, and also include the sysUtils unit in whatever implements this function.

like image 42
skamradt Avatar answered Sep 17 '25 06:09

skamradt