place timecode conversion functions into a Timecode class rather than an olive namespace

Code cleanup and improvement.
This commit is contained in:
itsmattkc
2019-12-26 17:20:58 +11:00
parent 3b2fcf4aae
commit 520b8b46fa
19 changed files with 110 additions and 92 deletions
+2 -2
View File
@@ -225,7 +225,7 @@ FramePtr FFmpegDecoder::RetrieveVideo(const rational &timecode)
frame_container->set_width(frame->width);
frame_container->set_height(frame->height);
frame_container->set_format(static_cast<olive::PixelFormat>(output_fmt_));
frame_container->set_timestamp(olive::timestamp_to_time(target_ts, avstream_->time_base));
frame_container->set_timestamp(Timecode::timestamp_to_time(target_ts, avstream_->time_base));
frame_container->allocate();
// Convert pixel format/linesize if necessary
@@ -326,7 +326,7 @@ int64_t FFmpegDecoder::GetTimestampFromTime(const rational &time)
}
// Convert timecode to AVStream timebase
int64_t target_ts = olive::time_to_timestamp(time, avstream_->time_base);
int64_t target_ts = Timecode::time_to_timestamp(time, avstream_->time_base);
// Find closest actual timebase in the file
target_ts = GetClosestTimestampInIndex(target_ts);
+17 -12
View File
@@ -28,10 +28,10 @@ QString padded(int64_t arg, int padding) {
return QStringLiteral("%1").arg(arg, padding, 10, QChar('0'));
}
QString olive::timestamp_to_timecode(const int64_t &timestamp,
const rational& timebase,
const TimecodeDisplay& display,
bool show_plus_if_positive)
QString Timecode::timestamp_to_timecode(const int64_t &timestamp,
const rational& timebase,
const Display& display,
bool show_plus_if_positive)
{
if (timebase.isNull()) {
return QString();
@@ -75,7 +75,7 @@ QString olive::timestamp_to_timecode(const int64_t &timestamp,
int64_t frames, secs, mins, hours;
int64_t f = qAbs(timestamp);
if (display == kTimecodeDropFrame && timebase.numerator() == 1001) {
if (display == kTimecodeDropFrame && TimebaseIsDropFrame(timebase)) {
frame_token = ";";
/**
@@ -129,7 +129,7 @@ QString olive::timestamp_to_timecode(const int64_t &timestamp,
return QString();
}
int64_t olive::timecode_to_timestamp(const QString &timecode, const rational &timebase, const olive::TimecodeDisplay &display, bool* ok)
int64_t Timecode::timecode_to_timestamp(const QString &timecode, const rational &timebase, const Display &display, bool* ok)
{
double timebase_dbl = timebase.toDouble();
@@ -182,7 +182,7 @@ int64_t olive::timecode_to_timestamp(const QString &timecode, const rational &ti
int64_t sec_count = (hours*3600 + mins*60 + secs);
int64_t timestamp = sec_count*rounded_frame_rate + frames;
if (display == kTimecodeDropFrame && timebase.numerator() == 1001) {
if (display == kTimecodeDropFrame && TimebaseIsDropFrame(timebase)) {
// Number of frames to drop on the minute marks is the nearest integer to 6% of the framerate
int64_t dropFrames = qRound64(frame_rate * (2.0/30.0));
@@ -231,22 +231,27 @@ err_fatal:
return 0;
}
rational olive::timestamp_to_time(const int64_t &timestamp, const rational &timebase)
rational Timecode::timestamp_to_time(const int64_t &timestamp, const rational &timebase)
{
return rational(timestamp) * timebase;
}
int64_t olive::time_to_timestamp(const rational &time, const rational &timebase)
bool Timecode::TimebaseIsDropFrame(const rational &timebase)
{
return (timebase.numerator() == 1001);
}
int64_t Timecode::time_to_timestamp(const rational &time, const rational &timebase)
{
return time_to_timestamp(time.toDouble(), timebase);
}
int64_t olive::time_to_timestamp(const double &time, const rational &timebase)
int64_t Timecode::time_to_timestamp(const double &time, const rational &timebase)
{
return qRound64(time * timebase.flipped().toDouble());
}
olive::TimecodeDisplay olive::CurrentTimecodeDisplay()
Timecode::Display Timecode::CurrentDisplay()
{
return static_cast<olive::TimecodeDisplay>(Config::Current()["TimecodeDisplay"].toInt());
return static_cast<Timecode::Display>(Config::Current()["TimecodeDisplay"].toInt());
}
+35 -23
View File
@@ -25,30 +25,42 @@
#include "common/rational.h"
namespace olive {
/**
* @brief Functions for converting times/timecodes/timestamps
*
* Olive uses the following terminology through its code:
*
* `time` - time in seconds presented in a rational form
* `timebase` - the base time unit of an audio/video stream in seconds
* `timestamp` - an integer representation of a time in timebase units (in many cases is used like a frame number)
* `timecode` a user-friendly string representation of a time according to Timecode::Display
*/
class Timecode {
public:
enum Display {
kTimecodeDropFrame,
kTimecodeNonDropFrame,
kTimecodeSeconds,
kFrames,
kMilliseconds
};
static Display CurrentDisplay();
/**
* @brief Convert a timestamp (according to a rational timebase) to a user-friendly string representation
*/
static QString timestamp_to_timecode(const int64_t &timestamp, const rational& timebase, const Display &display, bool show_plus_if_positive = false);
static int64_t timecode_to_timestamp(const QString& timecode, const rational& timebase, const Display& display, bool *ok = nullptr);
static int64_t time_to_timestamp(const rational& time, const rational& timebase);
static int64_t time_to_timestamp(const double& time, const rational& timebase);
static rational timestamp_to_time(const int64_t& timestamp, const rational& timebase);
static bool TimebaseIsDropFrame(const rational& timebase);
enum TimecodeDisplay {
kTimecodeDropFrame,
kTimecodeNonDropFrame,
kTimecodeSeconds,
kFrames,
kMilliseconds
};
TimecodeDisplay CurrentTimecodeDisplay();
/**
* @brief Convert a timestamp (according to a rational timebase) to a user-friendly string representation
*/
QString timestamp_to_timecode(const int64_t &timestamp, const rational& timebase, const TimecodeDisplay& display, bool show_plus_if_positive = false);
int64_t timecode_to_timestamp(const QString& timecode, const rational& timebase, const TimecodeDisplay& display, bool *ok = nullptr);
int64_t time_to_timestamp(const rational& time, const rational& timebase);
int64_t time_to_timestamp(const double& time, const rational& timebase);
rational timestamp_to_time(const int64_t& timestamp, const rational& timebase);
}
#endif // TIMECODEFUNCTIONS_H
+1 -1
View File
@@ -49,7 +49,7 @@ Config &Config::Current()
void Config::SetDefaults()
{
config_map_.clear();
config_map_["TimecodeDisplay"] = olive::kTimecodeDropFrame;
config_map_["TimecodeDisplay"] = Timecode::kTimecodeDropFrame;
config_map_["DefaultStillLength"] = QVariant::fromValue(rational(2));
config_map_["HoverFocus"] = false;
config_map_["AudioScrubbing"] = true;
+6 -6
View File
@@ -92,7 +92,7 @@ SpeedDurationDialog::SpeedDurationDialog(const rational& timebase, const QList<C
speed_layout->addWidget(duration_slider_, row, 1);
if (same_duration) {
duration_slider_->SetValue(olive::time_to_timestamp(clips_.first()->length(), timebase_));
duration_slider_->SetValue(Timecode::time_to_timestamp(clips_.first()->length(), timebase_));
} else {
duration_slider_->SetTristate();
}
@@ -149,7 +149,7 @@ void SpeedDurationDialog::accept()
if (change_duration) {
// Change the duration
int64_t current_duration = olive::time_to_timestamp(clip->length(), timebase_);
int64_t current_duration = Timecode::time_to_timestamp(clip->length(), timebase_);
int64_t new_duration = current_duration;
// Check if we're getting the duration value directly from the slider or calculating it from the speed
@@ -168,7 +168,7 @@ void SpeedDurationDialog::accept()
}
if (new_duration != current_duration) {
new_clip_length = olive::timestamp_to_time(new_duration, timebase_);
new_clip_length = Timecode::timestamp_to_time(new_duration, timebase_);
Block* next_block = clip->next();
// If "ripple clips" isn't checked, we need to calculate around the timeline as-is
@@ -222,9 +222,9 @@ void SpeedDurationDialog::accept()
}
if (change_speed) {
int64_t new_clip_duration = olive::time_to_timestamp(new_clip_length, timebase_);
int64_t new_clip_duration = Timecode::time_to_timestamp(new_clip_length, timebase_);
int64_t new_media_duration = qRound(static_cast<double>(new_clip_duration) * new_speed);
rational new_media_length = olive::timestamp_to_time(new_media_duration, timebase_);
rational new_media_length = Timecode::timestamp_to_time(new_media_duration, timebase_);
if (clip->is_reversed()) {
new_media_length = -new_media_length;
@@ -248,7 +248,7 @@ void SpeedDurationDialog::accept()
double SpeedDurationDialog::GetUnadjustedLengthTimestamp(ClipBlock *clip) const
{
double duration = static_cast<double>(olive::time_to_timestamp(clip->length(), timebase_));
double duration = static_cast<double>(Timecode::time_to_timestamp(clip->length(), timebase_));
// Convert duration to non-speed adjusted duration
duration *= clip->speed();
+8 -8
View File
@@ -162,19 +162,19 @@ QString Footage::duration()
if (video_stream->timebase() != frame_rate_timebase) {
// Convert from timebase to frame rate
rational duration_time = olive::timestamp_to_time(duration, video_stream->timebase());
duration = olive::time_to_timestamp(duration_time, frame_rate_timebase);
rational duration_time = Timecode::timestamp_to_time(duration, video_stream->timebase());
duration = Timecode::time_to_timestamp(duration_time, frame_rate_timebase);
}
return olive::timestamp_to_timecode(duration,
frame_rate_timebase,
olive::CurrentTimecodeDisplay());
return Timecode::timestamp_to_timecode(duration,
frame_rate_timebase,
Timecode::CurrentDisplay());
} else if (streams_.first()->type() == Stream::kAudio) {
AudioStreamPtr audio_stream = std::static_pointer_cast<AudioStream>(streams_.first());
return olive::timestamp_to_timecode(streams_.first()->duration(),
streams_.first()->timebase(),
olive::CurrentTimecodeDisplay());
return Timecode::timestamp_to_timecode(streams_.first()->duration(),
streams_.first()->timebase(),
Timecode::CurrentDisplay());
}
return QString();
+2 -2
View File
@@ -95,9 +95,9 @@ QString Sequence::duration()
rational timeline_length = timeline_output_->length();
int64_t timestamp = olive::time_to_timestamp(timeline_length, video_params_.time_base());
int64_t timestamp = Timecode::time_to_timestamp(timeline_length, video_params_.time_base());
return olive::timestamp_to_timecode(timestamp, video_params_.time_base(), olive::CurrentTimecodeDisplay());
return Timecode::timestamp_to_timecode(timestamp, video_params_.time_base(), Timecode::CurrentDisplay());
}
QString Sequence::rate()
+2 -2
View File
@@ -56,8 +56,8 @@ void VideoRenderBackend::InvalidateCache(const rational &start_range, const rati
<< end_range_adj.toDouble();
// Snap start_range to timebase
int64_t timestamp = olive::time_to_timestamp(start_range_adj, params_.time_base());
rational true_start = olive::timestamp_to_time(timestamp, params_.time_base());
int64_t timestamp = Timecode::time_to_timestamp(start_range_adj, params_.time_base());
rational true_start = Timecode::timestamp_to_time(timestamp, params_.time_base());
for (rational r=true_start;r<end_range_adj;r+=params_.time_base()) {
// Try to order the queue from closest to the playhead to furthest
+2 -2
View File
@@ -137,7 +137,7 @@ void NodeParamView::SetScale(const double& scale)
void NodeParamView::SetTime(const rational &time)
{
int64_t timestamp = olive::time_to_timestamp(time, keyframe_view_->timebase());
int64_t timestamp = Timecode::time_to_timestamp(time, keyframe_view_->timebase());
ruler_->SetTime(timestamp);
keyframe_view_->SetTime(timestamp);
@@ -160,7 +160,7 @@ void NodeParamView::UpdateItemTime(const rational &time)
void NodeParamView::RulerTimeChanged(const int64_t &timestamp)
{
rational time = olive::timestamp_to_time(timestamp, keyframe_view_->timebase());
rational time = Timecode::timestamp_to_time(timestamp, keyframe_view_->timebase());
UpdateItemTime(time);
}
@@ -18,7 +18,7 @@ public:
private:
void CreateWidgets();
void SetInputValue(NodeInput* input, const QVariant& value);
void SetInputValue(const QVariant& value);
NodeInput* input_;
@@ -176,7 +176,7 @@ void PlaybackControls::SetTimeLabelInternal(QLabel* label, const int64_t& time)
return;
}
label->setText(olive::timestamp_to_timecode(time,
time_base_,
olive::CurrentTimecodeDisplay()));
label->setText(Timecode::timestamp_to_timecode(time,
time_base_,
Timecode::CurrentDisplay()));
}
+4 -4
View File
@@ -23,12 +23,12 @@ QString TimeSlider::ValueToString(const QVariant &v)
return IntegerSlider::ValueToString(v);
}
return olive::timestamp_to_timecode(v.toLongLong(),
timebase_,
olive::CurrentTimecodeDisplay());
return Timecode::timestamp_to_timecode(v.toLongLong(),
timebase_,
Timecode::CurrentDisplay());
}
QVariant TimeSlider::StringToValue(const QString &s, bool *ok)
{
return olive::timecode_to_timestamp(s, timebase_, olive::CurrentTimecodeDisplay(), ok);
return Timecode::timecode_to_timestamp(s, timebase_, Timecode::CurrentDisplay(), ok);
}
+6 -6
View File
@@ -290,7 +290,7 @@ void TimelineWidget::GoToPrevCut()
int64_t this_track_closest_cut = 0;
foreach (Block* block, track->Blocks()) {
int64_t block_out_ts = olive::time_to_timestamp(block->out(), timebase());
int64_t block_out_ts = Timecode::time_to_timestamp(block->out(), timebase());
if (block_out_ts < playhead_) {
this_track_closest_cut = block_out_ts;
@@ -314,14 +314,14 @@ void TimelineWidget::GoToNextCut()
int64_t closest_cut = INT64_MAX;
foreach (TrackOutput* track, timeline_node_->Tracks()) {
int64_t this_track_closest_cut = olive::time_to_timestamp(track->track_length(), timebase());
int64_t this_track_closest_cut = Timecode::time_to_timestamp(track->track_length(), timebase());
if (this_track_closest_cut <= playhead_) {
this_track_closest_cut = INT64_MAX;
}
foreach (Block* block, track->Blocks()) {
int64_t block_in_ts = olive::time_to_timestamp(block->in(), timebase());
int64_t block_in_ts = Timecode::time_to_timestamp(block->in(), timebase());
if (block_in_ts > playhead_) {
this_track_closest_cut = block_in_ts;
@@ -339,7 +339,7 @@ void TimelineWidget::GoToNextCut()
void TimelineWidget::SplitAtPlayhead()
{
rational playhead_time = olive::timestamp_to_time(playhead_, timebase());
rational playhead_time = Timecode::timestamp_to_time(playhead_, timebase());
QList<TimelineViewBlockItem *> selected_blocks = GetSelectedBlocks();
@@ -494,7 +494,7 @@ QList<TimelineViewBlockItem *> TimelineWidget::GetSelectedBlocks()
void TimelineWidget::RippleEditTo(olive::timeline::MovementMode mode, bool insert_gaps)
{
rational playhead_time = olive::timestamp_to_time(playhead_, timebase());
rational playhead_time = Timecode::timestamp_to_time(playhead_, timebase());
rational closest_point_to_playhead;
if (mode == olive::timeline::kTrimIn) {
@@ -551,7 +551,7 @@ void TimelineWidget::RippleEditTo(olive::timeline::MovementMode mode, bool inser
olive::undo_stack.pushIfHasChildren(command);
if (mode == olive::timeline::kTrimIn && !insert_gaps) {
int64_t new_time = olive::time_to_timestamp(closest_point_to_playhead, timebase());
int64_t new_time = Timecode::time_to_timestamp(closest_point_to_playhead, timebase());
SetTimeAndSignal(new_time);
}
+4 -4
View File
@@ -185,10 +185,10 @@ void TimelineWidget::ImportTool::DragMove(TimelineViewMouseEvent *event)
}
// Generate tooltip (showing earliest in point of imported clip)
int64_t earliest_timestamp = olive::time_to_timestamp(earliest_ghost, parent()->timebase());
QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp,
parent()->timebase(),
olive::CurrentTimecodeDisplay());
int64_t earliest_timestamp = Timecode::time_to_timestamp(earliest_ghost, parent()->timebase());
QString tooltip_text = Timecode::timestamp_to_timecode(earliest_timestamp,
parent()->timebase(),
Timecode::CurrentDisplay());
// Force tooltip to update (otherwise the tooltip won't move as written in the documentation, and could get in the way
// of the cursor)
+5 -5
View File
@@ -326,11 +326,11 @@ void TimelineWidget::PointerTool::ProcessDrag(const TimelineCoordinate &mouse_po
// Show tooltip
// Generate tooltip (showing earliest in point of imported clip)
int64_t earliest_timestamp = olive::time_to_timestamp(time_movement, parent()->timebase());
QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp,
parent()->timebase(),
olive::CurrentTimecodeDisplay(),
true);
int64_t earliest_timestamp = Timecode::time_to_timestamp(time_movement, parent()->timebase());
QString tooltip_text = Timecode::timestamp_to_timecode(earliest_timestamp,
parent()->timebase(),
Timecode::CurrentDisplay(),
true);
// Force tooltip to update (otherwise the tooltip won't move as written in the documentation, and could get in the way
// of the cursor)
+5 -5
View File
@@ -51,11 +51,11 @@ void TimelineWidget::SlipTool::ProcessDrag(const TimelineCoordinate &mouse_pos)
// Show tooltip
// Generate tooltip (showing earliest in point of imported clip)
int64_t earliest_timestamp = olive::time_to_timestamp(time_movement, parent()->timebase());
QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp,
parent()->timebase(),
olive::CurrentTimecodeDisplay(),
true);
int64_t earliest_timestamp = Timecode::time_to_timestamp(time_movement, parent()->timebase());
QString tooltip_text = Timecode::timestamp_to_timecode(earliest_timestamp,
parent()->timebase(),
Timecode::CurrentDisplay(),
true);
// Force tooltip to update (otherwise the tooltip won't move as written in the documentation, and could get in the way
// of the cursor)
QToolTip::hideText();
@@ -89,7 +89,7 @@ bool TimelineViewBase::PlayheadMove(QMouseEvent *event)
QPointF scene_pos = mapToScene(event->pos());
rational mouse_time = SceneToTime(scene_pos.x());
int64_t target_ts = olive::time_to_timestamp(mouse_time, timebase());
int64_t target_ts = Timecode::time_to_timestamp(mouse_time, timebase());
SetTime(target_ts);
emit TimeChanged(target_ts);
+3 -2
View File
@@ -156,7 +156,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
if (text_visible_) {
QFontMetrics fm = p.fontMetrics();
double width_of_second = scale_;
int average_text_width = QFontMetricsWidth(fm, olive::timestamp_to_timecode(0, timebase_, olive::CurrentTimecodeDisplay()));
int average_text_width = QFontMetricsWidth(fm, Timecode::timestamp_to_timecode(0, timebase_, Timecode::CurrentDisplay()));
half_average_text_width = average_text_width/2;
while (width_of_second * text_skip < average_text_width) {
text_skip++;
@@ -202,7 +202,8 @@ void TimeRuler::paintEvent(QPaintEvent *)
// Try to draw text here
if (text_visible_ && sec%text_skip == 0) {
QString timecode_string = olive::timestamp_to_timecode(sec, timebase_, olive::CurrentTimecodeDisplay());
int64_t timestamp_here = Timecode::time_to_timestamp(rational(sec), timebase_);
QString timecode_string = Timecode::timestamp_to_timecode(timestamp_here, timebase_, Timecode::CurrentDisplay());
int text_x = i;
+3 -3
View File
@@ -105,7 +105,7 @@ const double &ViewerWidget::scale() const
rational ViewerWidget::GetTime() const
{
return olive::timestamp_to_time(ruler_->GetTime(), time_base_);
return Timecode::timestamp_to_time(ruler_->GetTime(), time_base_);
}
void ViewerWidget::SetScale(const double &scale_)
@@ -330,7 +330,7 @@ void ViewerWidget::GoToEnd()
if (viewer_node_ != nullptr) {
Pause();
SetTime(olive::time_to_timestamp(viewer_node_->Length(), time_base_));
SetTime(Timecode::time_to_timestamp(viewer_node_->Length(), time_base_));
}
}
@@ -426,7 +426,7 @@ void ViewerWidget::SizeChangedSlot(int width, int height)
void ViewerWidget::LengthChangedSlot(const rational &length)
{
controls_->SetEndTime(olive::time_to_timestamp(length, time_base_));
controls_->SetEndTime(Timecode::time_to_timestamp(length, time_base_));
}
void ViewerWidget::resizeEvent(QResizeEvent *event)