简体   繁体   中英

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

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...

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM