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