diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-03-19 17:19:22 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2019-03-19 19:38:43 +0300 |
commit | 5b7b7101c81ca104111e0df76cccf5b1c88bd3f6 (patch) | |
tree | d26d5295a226e14c904e3bb904cb51a1292a3b3a /intern/cycles | |
parent | 01df4818a6e1d3b93517e48a617310481abd9339 (diff) |
Cycles: Implement function to format and parse human readable time
Gives value in seconds for a string which is encoded in format HH:MM:SS.hh.
Diffstat (limited to 'intern/cycles')
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 7 | ||||
-rw-r--r-- | intern/cycles/test/CMakeLists.txt | 5 | ||||
-rw-r--r-- | intern/cycles/test/util_time_test.cpp | 64 | ||||
-rw-r--r-- | intern/cycles/util/util_time.cpp | 88 | ||||
-rw-r--r-- | intern/cycles/util/util_time.h | 11 |
5 files changed, 153 insertions, 22 deletions
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 923fdf9be4b..87dc39ca676 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -960,7 +960,6 @@ void BlenderSession::update_status_progress() string scene = ""; float progress; double total_time, remaining_time = 0, render_time; - char time_str[128]; float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f; float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f; @@ -980,13 +979,11 @@ void BlenderSession::update_status_progress() scene += ", " + b_rview_name; } else { - BLI_timecode_string_from_time_simple(time_str, sizeof(time_str), total_time); - timestatus = "Time:" + string(time_str) + " | "; + timestatus = "Time:" + time_human_readable_from_seconds(total_time) + " | "; } if(remaining_time > 0) { - BLI_timecode_string_from_time_simple(time_str, sizeof(time_str), remaining_time); - timestatus += "Remaining:" + string(time_str) + " | "; + timestatus += "Remaining:" + time_human_readable_from_seconds(remaining_time) + " | "; } timestatus += string_printf("Mem:%.2fM, Peak:%.2fM", (double)mem_used, (double)mem_peak); diff --git a/intern/cycles/test/CMakeLists.txt b/intern/cycles/test/CMakeLists.txt index f22992ad79f..73fe590f8ae 100644 --- a/intern/cycles/test/CMakeLists.txt +++ b/intern/cycles/test/CMakeLists.txt @@ -101,5 +101,6 @@ set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PLATFORM_LIN CYCLES_TEST(render_graph_finalize "${ALL_CYCLES_LIBRARIES};bf_intern_numaapi") CYCLES_TEST(util_aligned_malloc "cycles_util") CYCLES_TEST(util_path "cycles_util;${BOOST_LIBRARIES};${OPENIMAGEIO_LIBRARIES}") -CYCLES_TEST(util_string "cycles_util;${BOOST_LIBRARIES}") -CYCLES_TEST(util_task "cycles_util;${BOOST_LIBRARIES};bf_intern_numaapi") +CYCLES_TEST(util_string "cycles_util;${BOOST_LIBRARIES};${OPENIMAGEIO_LIBRARIES}") +CYCLES_TEST(util_task "cycles_util;${BOOST_LIBRARIES};${OPENIMAGEIO_LIBRARIES};bf_intern_numaapi") +CYCLES_TEST(util_time "cycles_util;${BOOST_LIBRARIES};${OPENIMAGEIO_LIBRARIES}") diff --git a/intern/cycles/test/util_time_test.cpp b/intern/cycles/test/util_time_test.cpp new file mode 100644 index 00000000000..74f9f3b2134 --- /dev/null +++ b/intern/cycles/test/util_time_test.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 2011-2019 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testing/testing.h" + +#include "util/util_time.h" + +CCL_NAMESPACE_BEGIN + +TEST(time_human_readable_to_seconds, Empty) { + EXPECT_EQ(time_human_readable_to_seconds(""), 0.0); + EXPECT_EQ(time_human_readable_from_seconds(0.0), "00:00.00"); +} + +TEST(time_human_readable_to_seconds, Fraction) { + EXPECT_NEAR(time_human_readable_to_seconds(".1"), 0.1, 1e-8f); + EXPECT_NEAR(time_human_readable_to_seconds(".10"), 0.1, 1e-8f); + EXPECT_EQ(time_human_readable_from_seconds(0.1), "00:00.10"); +} + +TEST(time_human_readable_to_seconds, Seconds) { + EXPECT_NEAR(time_human_readable_to_seconds("2.1"), 2.1, 1e-8f); + EXPECT_NEAR(time_human_readable_to_seconds("02.10"), 2.1, 1e-8f); + EXPECT_EQ(time_human_readable_from_seconds(2.1), "00:02.10"); + + EXPECT_NEAR(time_human_readable_to_seconds("12.1"), 12.1, 1e-8f); + EXPECT_NEAR(time_human_readable_to_seconds("12.10"), 12.1, 1e-8f); + EXPECT_EQ(time_human_readable_from_seconds(12.1), "00:12.10"); +} + +TEST(time_human_readable_to_seconds, MinutesSeconds) { + EXPECT_NEAR(time_human_readable_to_seconds("3:2.1"), 182.1, 1e-8f); + EXPECT_NEAR(time_human_readable_to_seconds("03:02.10"), 182.1, 1e-8f); + EXPECT_EQ(time_human_readable_from_seconds(182.1), "03:02.10"); + + EXPECT_NEAR(time_human_readable_to_seconds("34:12.1"), 2052.1, 1e-8f); + EXPECT_NEAR(time_human_readable_to_seconds("34:12.10"), 2052.1, 1e-8f); + EXPECT_EQ(time_human_readable_from_seconds(2052.1), "34:12.10"); +} + +TEST(time_human_readable_to_seconds, HoursMinutesSeconds) { + EXPECT_NEAR(time_human_readable_to_seconds("4:3:2.1"), 14582.1, 1e-8f); + EXPECT_NEAR(time_human_readable_to_seconds("04:03:02.10"), 14582.1, 1e-8f); + EXPECT_EQ(time_human_readable_from_seconds(14582.1), "04:03:02.10"); + + EXPECT_NEAR(time_human_readable_to_seconds("56:34:12.1"), 203652.1, 1e-8f); + EXPECT_NEAR(time_human_readable_to_seconds("56:34:12.10"), 203652.1, 1e-8f); + EXPECT_EQ(time_human_readable_from_seconds(203652.1), "56:34:12.10"); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_time.cpp b/intern/cycles/util/util_time.cpp index bc6ac4e2099..9983fdd1df3 100644 --- a/intern/cycles/util/util_time.cpp +++ b/intern/cycles/util/util_time.cpp @@ -14,15 +14,22 @@ * limitations under the License. */ +#include "util/util_time.h" + #include <stdlib.h> -#include "util/util_time.h" -#include "util/util_windows.h" +#if !defined(_WIN32) +# include <sys/time.h> +# include <unistd.h> +#endif -#ifdef _WIN32 +#include "util/util_math.h" +#include "util/util_string.h" +#include "util/util_windows.h" CCL_NAMESPACE_BEGIN +#ifdef _WIN32 double time_dt() { __int64 frequency, counter; @@ -37,16 +44,7 @@ void time_sleep(double t) { Sleep((int)(t*1000)); } - -CCL_NAMESPACE_END - #else - -#include <sys/time.h> -#include <unistd.h> - -CCL_NAMESPACE_BEGIN - double time_dt() { struct timeval now; @@ -73,7 +71,69 @@ void time_sleep(double t) if(us > 0) usleep(us); } +#endif -CCL_NAMESPACE_END +/* Time in format "hours:minutes:seconds.hundreds" */ -#endif +string time_human_readable_from_seconds(const double seconds) +{ + const int h = (((int)seconds) / (60 * 60)); + const int m = (((int)seconds) / 60) % 60; + const int s = (((int)seconds) % 60); + const int r = (((int)(seconds * 100)) % 100); + + if(h > 0) { + return string_printf("%.2d:%.2d:%.2d.%.2d", h, m, s, r); + } + else { + return string_printf("%.2d:%.2d.%.2d", m, s, r); + } +} + +double time_human_readable_to_seconds(const string& time_string) +{ + /* Those are multiplies of a corresponding token surrounded by : in the + * time string, which denotes how to convert value to seconds. + * Effectively: seconds, minutes, hours, days in seconds. */ + const int multipliers[] = {1, 60, 60*60, 24*60*60}; + const int num_multiplies = sizeof(multipliers) / sizeof(*multipliers); + if(time_string.empty()) { + return 0.0; + } + double result = 0.0; + /* Split fractions of a second from the encoded time. */ + vector<string> fraction_tokens; + string_split(fraction_tokens, time_string, ".", false); + const int num_fraction_tokens = fraction_tokens.size(); + if(num_fraction_tokens == 0) { + /* Time string is malformed. */ + return 0.0; + } + else if(fraction_tokens.size() == 1) { + /* There is no fraction of a second specified, the rest of the code + * handles this normally. */ + } + else if(fraction_tokens.size() == 2) { + result = atof(fraction_tokens[1].c_str()); + result *= pow(0.1, fraction_tokens[1].length()); + } + else { + /* This is not a valid string, the result can not be reliable. */ + return 0.0; + } + /* Split hours, minutes and seconds. + * Hours part is optional. */ + vector<string> tokens; + string_split(tokens, fraction_tokens[0], ":", false); + const int num_tokens = tokens.size(); + if(num_tokens > num_multiplies) { + /* Can not reliably represent the value. */ + return 0.0; + } + for(int i = 0; i < num_tokens; ++i) { + result += atoi(tokens[num_tokens - i - 1].c_str()) * multipliers[i]; + } + return result; +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_time.h b/intern/cycles/util/util_time.h index 13281bf188b..ed4dd5154d7 100644 --- a/intern/cycles/util/util_time.h +++ b/intern/cycles/util/util_time.h @@ -17,16 +17,20 @@ #ifndef __UTIL_TIME_H__ #define __UTIL_TIME_H__ +#include "util/util_string.h" + CCL_NAMESPACE_BEGIN /* Give current time in seconds in double precision, with good accuracy. */ double time_dt(); -/* Sleep for the specified number of seconds */ +/* Sleep for the specified number of seconds. */ void time_sleep(double t); +/* Scoped timer. */ + class scoped_timer { public: explicit scoped_timer(double *value = NULL) : value_(value) @@ -56,6 +60,11 @@ protected: double time_start_; }; +/* Make human readable string from time, compatible with Blender metadata. */ + +string time_human_readable_from_seconds(const double seconds); +double time_human_readable_to_seconds(const string& str); + CCL_NAMESPACE_END #endif |