Ich bin auf der Suche nach einer Funktion, die einen Integer-Wert in Frames in NTSC Drop Frame Timecode (hh: mm: ss.ff) konvertiert.Konvertieren von Frames zu NTSC Drop Frame Timecode
Ich benutze Delphi, könnte aber in jeder Sprache sein.
Dank
Ich bin auf der Suche nach einer Funktion, die einen Integer-Wert in Frames in NTSC Drop Frame Timecode (hh: mm: ss.ff) konvertiert.Konvertieren von Frames zu NTSC Drop Frame Timecode
Ich benutze Delphi, könnte aber in jeder Sprache sein.
Dank
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;
Sie müssen die divmod Routine von der Unit SysUtils kopieren, und auch die Unit SysUtils in welcher diese Funktion implementiert.
Es gibt eine gut bekannt ist klassische Lösung für dieses Problem ...
(natürlich können Sie einen kleineren int-Typen verwenden, wenn Sie Ihren Wertebereich begrenzt ist weiß)
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"
Aus dem resultierenden „drop“ framenumber, können Sie die Komponenten wie üblich berechnen, die nominal 30 fps Framerate verwenden. ..
frames = frameNumber % 30
seconds = (frameNumber/30) % 60
und so weiter ...
Ich sollte hinzufügen ... dieser Code ist C/C++ '%' ist Modulo (Rest) '/' ist Integral Division (Abschneiden) 'lldiv' berechnet sowohl Quotienten als auch Rest – Ichthyo
Das ist immer noch nicht richtig. Es gibt zwei Probleme, die nicht behoben werden: 1) In Drop-Frames mit 30 Bildern pro Sekunde haben Sie KEINE 30 Bilder pro Sekunde. Einige Sekunden haben nur 28 Frames, und diejenigen, die übersprungen werden, sind die Frames 0 und 1. 2) Aus diesem Grund ist es möglich, dass ausgelassene Frames die Anzahl von Sekunden, Minuten oder sogar Stunden erhöhen (wenn die Anzahl groß genug ist). . Es scheint, dass JEDER diesen subtilen Fehler macht. –
Hier ist ein bisschen mehr: Ich arbeite gerade an genau dem gleichen Problem (Konvertieren der Frame-Anzahl in Smpte-Zeit mit Drop-Frames). Wird meinen Algorithmus veröffentlichen, sobald ich sicher bin, dass er korrekt ist. –
+1, aber IMO sollte das Format String '% .2d:% 2d:% 2d% 2d....' - Entfernen der ersten drei Ziffern, weil sie nicht notwendig sind, und das Hinzufügen der letzten, weil ansonsten Einzelbilder in einer Sekunde nicht korrekt formatiert sind. – mghie
Korrigiert, Ursprünglich hatte ich die letzte Ziffer für die Formatierung offen gelassen, um größere Frames in der Sekunde verarbeiten zu können ... was im Nachhinein unwahrscheinlich ist. – skamradt
NTSC Drop Frame Timecode ist 29,97 fps, aber Sie Code akzeptiert nur fps als Integer, also glaube ich nicht, dass es richtig ist. –