]> git.sesse.net Git - kdenlive/commitdiff
Fix timecode calculation
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 31 Jul 2010 23:54:22 +0000 (23:54 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 31 Jul 2010 23:54:22 +0000 (23:54 +0000)
svn path=/trunk/kdenlive/; revision=4673

src/timecode.cpp
src/timecode.h
src/timecodedisplay.cpp
src/timecodedisplay.h

index 6973e81eeaa4e08eaa4003f9be37cf5fd577235f..251d3c62911e9eb02f5eb6cf54fea07b9ffdebbe 100644 (file)
@@ -37,6 +37,7 @@ void Timecode::setFormat(double framesPerSecond, bool dropFrame, Formats format)
     m_dropFrame = dropFrame;
     m_format = format;
     m_realFps = framesPerSecond;
+    m_dropFrames = round(m_realFps * .066666); //Number of frames to drop on the minute marks is the nearest integer to 6% of the framerate
     QRegExp regExp;
     if (m_dropFrame)
         regExp.setPattern("^\\d{2}:\\d{2}:\\d{2};\\d{2}$");
@@ -76,6 +77,11 @@ int Timecode::getDisplayFrameCount(const QString duration, bool frameDisplay) co
 int Timecode::getFrameCount(const QString duration) const
 {
     if (m_dropFrame) {
+
+        //CONVERT DROP FRAME TIMECODE TO A FRAME NUMBER
+        //Code by David Heidelberger, adapted from Andrew Duncan
+        //Given ints called hours, minutes, seconds, frames, and a double called framerate
+
         //Get Hours, Minutes, Seconds, Frames from timecode
         int hours, minutes, seconds, frames;
 
@@ -90,6 +96,11 @@ int Timecode::getFrameCount(const QString duration) const
             frames = duration.section(':', 3, 3).toInt();
         }
 
+        int totalMinutes = (60 * hours) + minutes; //Total number of minutes
+        int frameNumber = ((m_displayedFramesPerSecond * 60 * 60 * hours) + (m_displayedFramesPerSecond * 60 * minutes) + (m_displayedFramesPerSecond * seconds) + frames) - (m_dropFrames * (totalMinutes - floor(totalMinutes / 10)));
+        return frameNumber;
+
+
         //Calculate the frame count
         int dropRate = (int)((ceil(m_displayedFramesPerSecond) / 30) * 2);
         frames += ((hours * 60 + minutes) * 60 + seconds) * m_displayedFramesPerSecond;
@@ -279,63 +290,54 @@ QString Timecode::getTimecodeDropFrame(const GenTime & time) const
     return getTimecodeDropFrame((int)time.frames(m_realFps));
 }
 
-QString Timecode::getTimecodeDropFrame(int frames) const
+QString Timecode::getTimecodeDropFrame(int framenumber) const
 {
-    // Calculate the timecode using dropframes to remove the difference in fps. Note that this algorithm should work
-    // for NTSC times, but is untested for any others - it is in no way an "official" algorithm, unless it's by fluke.
-
-    // calculate how many frames need to be dropped every minute.
-    int dropRate = 0;
-    if (m_dropFrame) {
-        dropRate = (int)((ceil(m_displayedFramesPerSecond) / 30) * 2);
+    //CONVERT A FRAME NUMBER TO DROP FRAME TIMECODE
+    //Based on code by David Heidelberger, adapted from Andrew Duncan
+    //Given an int called framenumber and a double called framerate
+    //Framerate should be 29.97, 59.94, or 23.976, otherwise the calculations will be off.
+
+    int d;
+    int m;
+
+    //int framesPerHour = round(m_realFps * 60 * 60); //Number of frames in an hour
+    //int framesPer24Hours = framesPerHour * 24; //Number of frames in a day - timecode rolls over after 24 hours
+    int framesPer10Minutes = round(m_realFps * 60 * 10); //Number of frames per ten minutes
+    //int framesPerMinute = round(framerate)*60)-  dropFrames; //Number of frames per minute is the round of the framerate * 60 minus the number of dropped frames
+
+    /*
+     * The 2 check below should not be necessary in Kdenlive
+    if (framenumber<0) //Negative time. Add 24 hours.
+    {
+    framenumber=framesPer24Hours+framenumber;
     }
 
-    // calculate how many frames are in a normal minute, and how many are in a tenth minute.
-    int normalMinuteFrames = (m_displayedFramesPerSecond * 60) - dropRate;
-    int tenthMinuteFrames = (m_displayedFramesPerSecond * 60);
-
-    // Number of actual frames in a 10 minute interval :
-    int tenMinutes = (normalMinuteFrames * 9) + tenthMinuteFrames;
-
-    int tenMinuteIntervals = frames / tenMinutes;
-    frames = frames % tenMinutes;
-
-    int hours = tenMinuteIntervals / 6;
-    tenMinuteIntervals = tenMinuteIntervals % 6;
+    //If framenumber is greater than 24 hrs, next operation will rollover clock
+    framenumber = framenumber % framesPer24Hours; //% is the modulus operator, which returns a remainder. a % b = the remainder of a/b
+    */
 
-    // At the point, we have figured out HH:M?:??:??
+    d = floor(framenumber / framesPer10Minutes); // \ means integer division, which is a/b without a remainder. Some languages you could use floor(a/b)
+    m = framenumber % framesPer10Minutes;
 
-    int numMinutes;
-
-    if (frames < tenthMinuteFrames) {
-        // tenth minute logic applies.
-        numMinutes = 0;
+    if (m > 1) {
+        framenumber = framenumber + (m_dropFrames * 9 * d) + m_dropFrames * (floor((m - m_dropFrames) / (round(m_realFps * 60) - m_dropFrames)));
     } else {
-        // normal minute logic applies.
-        numMinutes = 1 + (frames - tenthMinuteFrames) / normalMinuteFrames;
-        frames = (frames - tenthMinuteFrames) % normalMinuteFrames;
-        frames +=  dropRate;
+        framenumber = framenumber + m_dropFrames * 9 * d;
     }
-    // We now have HH:MM:??:??
 
-    int seconds = frames / m_displayedFramesPerSecond;
-    frames = frames % m_displayedFramesPerSecond;
+    int frames = framenumber % m_displayedFramesPerSecond;
+    int seconds = (int) floor(framenumber / m_displayedFramesPerSecond) % 60;
+    int minutes = (int) floor(floor(framenumber / m_displayedFramesPerSecond) / 60) % 60;
+    int hours = floor(floor(floor(framenumber / m_displayedFramesPerSecond) / 60) / 60);
 
-    // We now have HH:MM:SS:FF
-
-    // THANK FUCK FOR THAT.
 
     QString text;
     text.append(QString::number(hours).rightJustified(2, '0', false));
     text.append(':');
-    text.append(QString::number(tenMinuteIntervals));
-    text.append(QString::number(numMinutes));
+    text.append(QString::number(minutes).rightJustified(2, '0', false));
     text.append(':');
     text.append(QString::number(seconds).rightJustified(2, '0', false));
-    if (m_dropFrame)
-        text.append(';');
-    else
-        text.append(':');
+    text.append(';');
     text.append(QString::number(frames).rightJustified(2, '0', false));
 
     return text;
index 8521aa822f28d29970b58ee163e6d3f54e51def6..f8efcd32a986a0237b5059daf1e68a82852872e7 100644 (file)
@@ -68,6 +68,7 @@ private:
     bool m_dropFrame;
     int m_displayedFramesPerSecond;
     double m_realFps;
+    double m_dropFrames;
     QRegExpValidator *m_validator;
 
     const QString getTimecodeHH_MM_SS_FF(const GenTime & time) const;
@@ -77,7 +78,7 @@ private:
     QString getTimecodeFrames(const GenTime & time) const;
     QString getTimecodeSeconds(const GenTime & time) const;
     QString getTimecodeDropFrame(const GenTime & time) const;
-    QString getTimecodeDropFrame(int frames) const;
+    QString getTimecodeDropFrame(int framenumber) const;
 };
 
 #endif
index 7c996ebfa057252ce0be817c452420af08c3f95e..8fce02eab3f83016a7c5adc64e960795c9c3e6e7 100644 (file)
@@ -40,8 +40,8 @@ TimecodeDisplay::TimecodeDisplay(Timecode t, QWidget *parent)
     QFontMetrics fm = lineedit->fontMetrics();
     lineedit->setMaximumWidth(fm.width("88:88:88:888"));
     setSizePolicy(QSizePolicy::Maximum, QSizePolicy::MinimumExpanding);
-
-    slotUpdateTimeCodeFormat();
+    
+    setTimeCodeFormat(KdenliveSettings::frametimecode(), true);
 
     connect(uparrow, SIGNAL(clicked()), this, SLOT(slotValueUp()));
     connect(downarrow, SIGNAL(clicked()), this, SLOT(slotValueDown()));
@@ -66,11 +66,11 @@ void TimecodeDisplay::slotValueDown()
     emit editingFinished();
 }
 
-void TimecodeDisplay::setTimeCodeFormat(bool frametimecode)
+void TimecodeDisplay::setTimeCodeFormat(bool frametimecode, bool init)
 {
+    if (!init && m_frametimecode == frametimecode) return;
     int val = value();
     m_frametimecode = frametimecode;
-    lineedit->setInputMask("");
     if (m_frametimecode) {
         QIntValidator *valid = new QIntValidator(lineedit);
         valid->setBottom(0);
index 4a751afb2bf3c04a33279b93ce4b6bb4b7fe27e3..4a4232ed7798d4180bd1616f88dfb4df30c6230f 100644 (file)
@@ -66,8 +66,9 @@ public:
     Timecode timecode() const;
 
     /** @brief Sets value's format to frames or HH:MM:SS:FF according to @param frametimecode.
-    * @param frametimecode true = frames, false = HH:MM:SS:FF */
-    void setTimeCodeFormat(bool frametimecode);
+    * @param frametimecode true = frames, false = HH:MM:SS:FF
+    * @param init true = force the change, false = update only if the frametimecode param changed */
+    void setTimeCodeFormat(bool frametimecode, bool init = false);
 
     /** @brief Sets timecode for current project.
      * @param t the new timecode */