Blender V5.0
timecode.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <cstdio>
12
13#include "BLI_math_base.h"
14#include "BLI_string.h"
15
16#include "BLI_timecode.h" /* own include */
17
18#include "DNA_userdef_types.h" /* for eTimecodeStyles only */
19
20#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
21
23 const size_t maxncpy,
24 const int brevity_level,
25 const float time_seconds,
26 const double fps,
27 const short timecode_style)
28{
29 int hours = 0, minutes = 0, seconds = 0, frames = 0;
30 float time = time_seconds;
31 char neg[2] = {'\0'};
32 size_t rlen;
33
34 /* Get frames. */
35 if (time < 0) {
36 /* Correction for negative frames. */
37 neg[0] = '-';
38 time = -time;
39 }
40
41 if (time >= 3600.0f) {
42 /* hours */
43 /* XXX should we only display a single digit for hours since clips are
44 * VERY UNLIKELY to be more than 1-2 hours max? However, that would
45 * go against conventions...
46 */
47 hours = int(time) / 3600;
48 time = fmodf(time, 3600);
49 }
50
51 if (time >= 60.0f) {
52 /* minutes */
53 minutes = int(time) / 60;
54 time = fmodf(time, 60);
55 }
56
57 if (brevity_level <= 0) {
58 /* seconds + frames
59 * Frames are derived from 'fraction' of second. We need to perform some additional rounding
60 * to cope with 'half' frames, etc., which should be fine in most cases
61 */
62 seconds = int(time);
63 frames = round_fl_to_int(float((double(time) - double(seconds)) * fps));
64 }
65 else {
66 /* seconds (with pixel offset rounding) */
67 seconds = round_fl_to_int(time);
68 }
69
70 switch (timecode_style) {
72 /* - In general, minutes and seconds should be shown, as most clips will be
73 * within this length. Hours will only be included if relevant.
74 * - Only show frames when zoomed in enough for them to be relevant
75 * (using separator of '+' for frames).
76 * When showing frames, use slightly different display
77 * to avoid confusion with `mm:ss` format.
78 */
79 if (brevity_level <= 0) {
80 /* include "frames" in display */
81 if (hours) {
82 rlen = BLI_snprintf_rlen(
83 str, maxncpy, "%s%02d:%02d:%02d+%02d", neg, hours, minutes, seconds, frames);
84 }
85 else if (minutes) {
86 rlen = BLI_snprintf_rlen(
87 str, maxncpy, "%s%02d:%02d+%02d", neg, minutes, seconds, frames);
88 }
89 else {
90 rlen = BLI_snprintf_rlen(str, maxncpy, "%s00:%02d+%02d", neg, seconds, frames);
91 }
92 }
93 else {
94 /* don't include 'frames' in display */
95 if (hours) {
96 rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, hours, minutes, seconds);
97 }
98 else {
99 rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d", neg, minutes, seconds);
100 }
101 }
102 break;
103 }
105 /* reduced SMPTE format that always shows minutes, seconds, frames.
106 * Hours only shown as needed. */
107 if (hours) {
108 rlen = BLI_snprintf_rlen(
109 str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
110 }
111 else {
112 rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%02d:%02d", neg, minutes, seconds, frames);
113 }
114 break;
115 }
117 /* reduced SMPTE. Instead of frames, milliseconds are shown */
118
119 /* precision of decimal part */
120 const int ms_dp = (brevity_level <= 0) ? (1 - brevity_level) : 1;
121
122 /* to get 2 digit whole-number part for seconds display
123 * (i.e. 3 is for 2 digits + radix, on top of full length) */
124 const int s_pad = ms_dp + 3;
125
126 if (hours) {
127 rlen = BLI_snprintf_rlen(
128 str, maxncpy, "%s%02d:%02d:%0*.*f", neg, hours, minutes, s_pad, ms_dp, time);
129 }
130 else {
131 rlen = BLI_snprintf_rlen(str, maxncpy, "%s%02d:%0*.*f", neg, minutes, s_pad, ms_dp, time);
132 }
133 break;
134 }
136 /* SubRip, like SMPTE milliseconds but seconds and milliseconds
137 * are separated by a comma, not a dot... */
138
139 /* precision of decimal part */
140 const int ms_dp = (brevity_level <= 0) ? (1 - brevity_level) : 1;
141 const int ms = round_fl_to_int((time - float(seconds)) * 1000.0f);
142
143 rlen = BLI_snprintf_rlen(
144 str, maxncpy, "%s%02d:%02d:%02d,%0*d", neg, hours, minutes, seconds, ms_dp, ms);
145 break;
146 }
148 /* only show the original seconds display */
149 /* round to whole numbers if brevity_level is >= 1 (i.e. scale is coarse) */
150 if (brevity_level <= 0) {
151 rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - brevity_level, time_seconds);
152 }
153 else {
154 rlen = BLI_snprintf_rlen(str, maxncpy, "%d", round_fl_to_int(time_seconds));
155 }
156 break;
157 }
159 default: {
160 /* full SMPTE format */
161 rlen = BLI_snprintf_rlen(
162 str, maxncpy, "%s%02d:%02d:%02d:%02d", neg, hours, minutes, seconds, frames);
163 break;
164 }
165 }
166
167 return rlen;
168}
169
171 const size_t maxncpy,
172 const double time_seconds)
173{
174 size_t rlen;
175
176 /* format 00:00:00.00 (hr:min:sec) string has to be 12 long */
177 const int hr = int(time_seconds) / (60 * 60);
178 const int min = (int(time_seconds) / 60) % 60;
179 const int sec = int(time_seconds) % 60;
180 const int hun = int(fmod(time_seconds, 1.0) * 100);
181
182 if (hr) {
183 rlen = BLI_snprintf_rlen(str, maxncpy, "%.2d:%.2d:%.2d.%.2d", hr, min, sec, hun);
184 }
185 else {
186 rlen = BLI_snprintf_rlen(str, maxncpy, "%.2d:%.2d.%.2d", min, sec, hun);
187 }
188
189 return rlen;
190}
191
193 const size_t maxncpy,
194 const int brevity_level,
195 const float time_seconds)
196{
197 size_t rlen;
198
199 /* round to whole numbers if brevity_level is >= 1 (i.e. scale is coarse) */
200 if (brevity_level <= 0) {
201 rlen = BLI_snprintf_rlen(str, maxncpy, "%.*f", 1 - brevity_level, time_seconds);
202 }
203 else {
204 rlen = BLI_snprintf_rlen(str, maxncpy, "%d", round_fl_to_int(time_seconds));
205 }
206
207 return rlen;
208}
MINLINE int round_fl_to_int(float a)
size_t BLI_snprintf_rlen(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
@ USER_TIMECODE_SMPTE_FULL
@ USER_TIMECODE_SECONDS_ONLY
@ USER_TIMECODE_MINIMAL
@ USER_TIMECODE_SUBRIP
@ USER_TIMECODE_MILLISECONDS
@ USER_TIMECODE_SMPTE_MSF
#define fmodf(x, y)
#define str(s)
ccl_device_inline float2 fmod(const float2 a, const float b)
#define min(a, b)
Definition sort.cc:36
size_t BLI_timecode_string_from_time_simple(char *str, const size_t maxncpy, const double time_seconds)
Definition timecode.cc:170
size_t BLI_timecode_string_from_time_seconds(char *str, const size_t maxncpy, const int brevity_level, const float time_seconds)
Definition timecode.cc:192
size_t BLI_timecode_string_from_time(char *str, const size_t maxncpy, const int brevity_level, const float time_seconds, const double fps, const short timecode_style)
Definition timecode.cc:22