X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Ftimecode.cpp;h=8e8465ff938e7e0ad99d6be2ca0f31708218a3e8;hb=f6afc93100a3d635181e017cd9f49844580fd0e7;hp=40e7b198d3fb2cd4f3ac8bdb165489cb4d45eff7;hpb=5ee798aed90c5a3a50024e6b5bd26753e03ec7cc;p=kdenlive diff --git a/src/timecode.cpp b/src/timecode.cpp index 40e7b198..8e8465ff 100644 --- a/src/timecode.cpp +++ b/src/timecode.cpp @@ -19,10 +19,11 @@ #include #include -Timecode::Timecode(Formats format, int framesPerSecond, bool dropFrame) : +Timecode::Timecode(Formats format, double framesPerSecond, bool dropFrame) : m_format(format), m_dropFrame(dropFrame), - m_displayedFramesPerSecond(framesPerSecond) + m_displayedFramesPerSecond(framesPerSecond + 0.5), + m_realFps(framesPerSecond) { } @@ -30,55 +31,80 @@ Timecode::~Timecode() { } -int Timecode::fps() +double Timecode::fps() const { - return m_displayedFramesPerSecond; + return m_realFps; //m_displayedFramesPerSecond; } +bool Timecode::df() const +{ + return m_dropFrame; +} + +QString Timecode::inputMask() const +{ + if (m_dropFrame) return "99:99.99:99"; + return "99:99:99:99"; +} + +QString Timecode::reformatSeparators(QString duration) const +{ + if (m_dropFrame) { + return duration.replace(5, 1, '.'); + } + return duration.replace(5, 1, ':'); +} -int Timecode::getFrameCount(const QString duration, double fps) const +int Timecode::getDisplayFrameCount(const QString duration, bool frameDisplay) const +{ + if (frameDisplay) return duration.toInt(); + return getFrameCount(duration); +} + +int Timecode::getFrameCount(const QString duration) const { if (m_dropFrame) { - // calculate how many frames need to be dropped every minute. - int frames; - int toDrop = (int) floor(600.0 * (m_displayedFramesPerSecond - fps) + 0.5); - - int perMinute = toDrop / 9; - int tenthMinute = toDrop % 9; - - // calculate how many frames are in a normal minute, and how many are in a tenth minute. - int normalMinuteFrames = (m_displayedFramesPerSecond * 60) - perMinute; - int tenthMinuteFrames = (m_displayedFramesPerSecond * 60) - tenthMinute;; - - // Number of actual frames in a 10 minute interval : - int tenMinutes = (normalMinuteFrames * 9) + tenthMinuteFrames; - frames = 6 * duration.section(':', 0, 0).toInt() * tenMinutes; - int minutes = duration.section(':', 1, 1).toInt(); - frames += ((int) minutes / 10) * tenMinutes; - int mins = minutes % 10; - if (mins > 0) { - frames += tenthMinuteFrames; - mins--; - if (mins > 0) frames += mins * normalMinuteFrames; + //Get Hours, Minutes, Seconds, Frames from timecode + int hours, minutes, seconds, frames; + + hours = duration.section(':', 0, 0).toInt(); + if (duration.contains('.')) { + minutes = duration.section('.', 0, 0).section(':', 1, 1).toInt(); + seconds = duration.section('.', 1, 1).section(':', 0, 0).toInt(); + frames = duration.section('.', 1, 1).section(':', 1, 1).toInt(); + } else { + //Handle Drop Frame timecode frame calculations, even if the timecode supplied uses incorrect "99:99:99:99" format instead of "99:99.99:99" + minutes = duration.section(':', 1, 1).toInt(); + seconds = duration.section(':', 2, 2).toInt(); + frames = duration.section(':', 3, 3).toInt(); } - if (minutes % 10 > 0) frames -= perMinute; - frames += duration.section(':', 2, 2).toInt() * m_displayedFramesPerSecond + duration.section(':', 3, 3).toInt(); + + //Calculate the frame count + int dropRate = (int)((ceil(m_displayedFramesPerSecond) / 30) * 2); + frames += ((hours * 60 + minutes) * 60 + seconds) * m_displayedFramesPerSecond; + frames -= dropRate * ((hours * 60 + minutes) - (floor((hours * 60 + minutes) / 10))); return frames; } - return (int)((duration.section(':', 0, 0).toInt()*3600.0 + duration.section(':', 1, 1).toInt()*60.0 + duration.section(':', 2, 2).toInt()) * fps + duration.section(':', 3, 3).toInt()); + return (int)((duration.section(':', 0, 0).toInt()*3600.0 + duration.section(':', 1, 1).toInt()*60.0 + duration.section(':', 2, 2).toInt()) * m_realFps + duration.section(':', 3, 3).toInt()); } -QString Timecode::getTimecode(const GenTime & time, double fps) const +QString Timecode::getDisplayTimecode(const GenTime & time, bool frameDisplay) const +{ + if (frameDisplay) return QString::number((int) time.frames(m_realFps)); + return getTimecode(time); +} + +QString Timecode::getTimecode(const GenTime & time) const { switch (m_format) { case HH_MM_SS_FF: - return getTimecodeHH_MM_SS_FF(time, fps); + return getTimecodeHH_MM_SS_FF(time); break; case HH_MM_SS_HH: return getTimecodeHH_MM_SS_HH(time); break; case Frames: - return getTimecodeFrames(time, fps); + return getTimecodeFrames(time); break; case Seconds: return getTimecodeSeconds(time); @@ -87,22 +113,48 @@ QString Timecode::getTimecode(const GenTime & time, double fps) const kWarning() << "Unknown timecode format specified, defaulting to HH_MM_SS_FF" << endl; - return getTimecodeHH_MM_SS_FF(time, fps); + return getTimecodeHH_MM_SS_FF(time); } } -QString Timecode::getTimecodeFromFrames(int frames) +const QString Timecode::getDisplayTimecodeFromFrames(int frames, bool frameDisplay) const +{ + if (frameDisplay) return QString::number(frames); + return getTimecodeHH_MM_SS_FF(frames); +} + +const QString Timecode::getTimecodeFromFrames(int frames) const { return getTimecodeHH_MM_SS_FF(frames); } + +//static +QString Timecode::getStringTimecode(int frames, const double &fps) +{ + // Returns the timecode in an hh:mm:ss format + int seconds = (int)(frames / fps); + int minutes = seconds / 60; + seconds = seconds % 60; + int hours = minutes / 60; + minutes = minutes % 60; + QString text; + text.append(QString::number(hours).rightJustified(2, '0', false)); + text.append(':'); + text.append(QString::number(minutes).rightJustified(2, '0', false)); + text.append(':'); + text.append(QString::number(seconds).rightJustified(2, '0', false)); + return text; +} + + //static QString Timecode::getEasyTimecode(const GenTime & time, const double &fps) { // Returns the timecode in an easily read display, like 3 min. 5 sec. - int frames = (int)time.frames(fps); - int seconds = frames / (int) floor(fps + 0.5); - frames = frames % ((int) fps); + int frames = (int) time.frames(fps); + int seconds = (int)(frames / fps); + frames = frames - ((int)(fps * seconds)); int minutes = seconds / 60; seconds = seconds % 60; @@ -142,16 +194,19 @@ QString Timecode::getEasyTimecode(const GenTime & time, const double &fps) } -QString Timecode::getTimecodeHH_MM_SS_FF(const GenTime & time, double fps) const +const QString Timecode::getTimecodeHH_MM_SS_FF(const GenTime & time) const { if (m_dropFrame) - return getTimecodeDropFrame(time, fps); + return getTimecodeDropFrame(time); - return getTimecodeHH_MM_SS_FF((int)time.frames(fps)); + return getTimecodeHH_MM_SS_FF((int) time.frames(m_realFps)); } -QString Timecode::getTimecodeHH_MM_SS_FF(int frames) const +const QString Timecode::getTimecodeHH_MM_SS_FF(int frames) const { + if (m_dropFrame) { + return getTimecodeDropFrame(frames); + } int seconds = frames / m_displayedFramesPerSecond; frames = frames % m_displayedFramesPerSecond; @@ -161,7 +216,6 @@ QString Timecode::getTimecodeHH_MM_SS_FF(int frames) const minutes = minutes % 60; QString text; - text.append(QString::number(hours).rightJustified(2, '0', false)); text.append(':'); text.append(QString::number(minutes).rightJustified(2, '0', false)); @@ -188,7 +242,11 @@ QString Timecode::getTimecodeHH_MM_SS_HH(const GenTime & time) const text.append(QString::number(hours).rightJustified(2, '0', false)); text.append(':'); text.append(QString::number(minutes).rightJustified(2, '0', false)); - text.append(':'); + if (m_dropFrame) { + text.append('.'); + } else { + text.append(':'); + } text.append(QString::number(seconds).rightJustified(2, '0', false)); text.append(':'); text.append(QString::number(hundredths).rightJustified(2, '0', false)); @@ -196,9 +254,9 @@ QString Timecode::getTimecodeHH_MM_SS_HH(const GenTime & time) const return text; } -QString Timecode::getTimecodeFrames(const GenTime & time, double fps) const +QString Timecode::getTimecodeFrames(const GenTime & time) const { - return QString::number(time.frames(fps)); + return QString::number(time.frames(m_realFps)); } QString Timecode::getTimecodeSeconds(const GenTime & time) const @@ -206,21 +264,25 @@ QString Timecode::getTimecodeSeconds(const GenTime & time) const return QString::number(time.seconds()); } -QString Timecode::getTimecodeDropFrame(const GenTime & time, double fps) const +QString Timecode::getTimecodeDropFrame(const GenTime & time) const +{ + return getTimecodeDropFrame((int)time.frames(m_realFps)); +} + +QString Timecode::getTimecodeDropFrame(int frames) 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. - int frames = (int)time.frames(fps); // calculate how many frames need to be dropped every minute. - int toDrop = (int) floor(600.0 * (m_displayedFramesPerSecond - fps) + 0.5); - - int perMinute = toDrop / 9; - int tenthMinute = toDrop % 9; + int dropRate = 0; + if (m_dropFrame) { + dropRate = (int)((ceil(m_displayedFramesPerSecond) / 30) * 2); + } // calculate how many frames are in a normal minute, and how many are in a tenth minute. - int normalMinuteFrames = (m_displayedFramesPerSecond * 60) - perMinute; - int tenthMinuteFrames = (m_displayedFramesPerSecond * 60) - tenthMinute;; + 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; @@ -242,7 +304,7 @@ QString Timecode::getTimecodeDropFrame(const GenTime & time, double fps) const // normal minute logic applies. numMinutes = 1 + (frames - tenthMinuteFrames) / normalMinuteFrames; frames = (frames - tenthMinuteFrames) % normalMinuteFrames; - frames += tenthMinute + perMinute; + frames += dropRate; } // We now have HH:MM:??:?? @@ -258,7 +320,11 @@ QString Timecode::getTimecodeDropFrame(const GenTime & time, double fps) const text.append(':'); text.append(QString::number(tenMinuteIntervals)); text.append(QString::number(numMinutes)); - text.append(':'); + if (m_dropFrame) { + text.append('.'); + } else { + text.append(':'); + } text.append(QString::number(seconds).rightJustified(2, '0', false)); text.append(':'); text.append(QString::number(frames).rightJustified(2, '0', false));