@@ -13,75 +13,68 @@ namespace opentime { namespace OPENTIME_VERSION {
13
13
14
14
RationalTime RationalTime::_invalid_time{ 0 , RationalTime::_invalid_rate };
15
15
16
- static constexpr std::array<double , 4 > dropframe_timecode_rates{ {
17
- // 23.976,
18
- // 23.98,
19
- // 23.97,
20
- // 24000.0/1001.0,
21
- 29.97 ,
16
+ static constexpr std::array<double , 2 > dropframe_timecode_rates{ {
22
17
30000.0 / 1001.0 ,
23
- 59.94 ,
24
18
60000.0 / 1001.0 ,
25
19
} };
26
20
21
+ // See the official source of these numbers here:
22
+ // ST 12-1:2014 - SMPTE Standard - Time and Control Code
23
+ // https://ieeexplore.ieee.org/document/7291029
24
+ //
27
25
static constexpr std::array<double , 11 > smpte_timecode_rates{
28
- { 1.0 ,
29
- 12.0 ,
30
- 24000.0 / 1001.0 ,
26
+ { 24000.0 / 1001.0 ,
31
27
24.0 ,
32
28
25.0 ,
33
29
30000.0 / 1001.0 ,
34
30
30.0 ,
31
+ 48000.0 / 1001.0 ,
35
32
48.0 ,
36
33
50.0 ,
37
34
60000.0 / 1001.0 ,
38
- 60.0 }
39
- };
40
-
41
- static constexpr std::array<double , 16 > valid_timecode_rates{
42
- { 1.0 ,
43
- 12.0 ,
44
- 23.97 ,
45
- 23.976 ,
46
- 23.98 ,
47
- 24000.0 / 1001.0 ,
48
- 24.0 ,
49
- 25.0 ,
50
- 29.97 ,
51
- 30000.0 / 1001.0 ,
52
- 30.0 ,
53
- 48.0 ,
54
- 50.0 ,
55
- 59.94 ,
56
- 60000.0 / 1001.0 ,
57
- 60.0 }
35
+ 60.0
36
+ }
58
37
};
59
38
39
+ // deprecated in favor of `is_smpte_timecode_rate`
60
40
bool
61
41
RationalTime::is_valid_timecode_rate (double fps)
62
42
{
63
- auto b = valid_timecode_rates.begin (), e = valid_timecode_rates.end ();
43
+ return is_smpte_timecode_rate (fps);
44
+ }
45
+
46
+ bool
47
+ RationalTime::is_smpte_timecode_rate (double fps)
48
+ {
49
+ auto b = smpte_timecode_rates.begin (), e = smpte_timecode_rates.end ();
64
50
return std::find (b, e, fps) != e;
65
51
}
66
52
53
+ // deprecated in favor of `is_smpte_timecode_rate`
67
54
double
68
55
RationalTime::nearest_valid_timecode_rate (double rate)
56
+ {
57
+ return nearest_smpte_timecode_rate (rate);
58
+ }
59
+
60
+ double
61
+ RationalTime::nearest_smpte_timecode_rate (double rate)
69
62
{
70
63
double nearest_rate = 0 ;
71
64
double min_diff = std::numeric_limits<double >::max ();
72
- for (auto valid_rate : smpte_timecode_rates)
65
+ for (auto smpte_rate : smpte_timecode_rates)
73
66
{
74
- if (valid_rate == rate)
67
+ if (smpte_rate == rate)
75
68
{
76
69
return rate;
77
70
}
78
- auto diff = std::abs (rate - valid_rate );
71
+ auto diff = std::abs (rate - smpte_rate );
79
72
if (diff >= min_diff)
80
73
{
81
74
continue ;
82
75
}
83
76
min_diff = diff;
84
- nearest_rate = valid_rate ;
77
+ nearest_rate = smpte_rate ;
85
78
}
86
79
return nearest_rate;
87
80
}
@@ -200,7 +193,7 @@ RationalTime::from_timecode(
200
193
double rate,
201
194
ErrorStatus* error_status)
202
195
{
203
- if (!RationalTime::is_valid_timecode_rate (rate))
196
+ if (!RationalTime::is_smpte_timecode_rate (rate))
204
197
{
205
198
if (error_status)
206
199
{
@@ -331,7 +324,7 @@ RationalTime::from_time_string(
331
324
double rate,
332
325
ErrorStatus* error_status)
333
326
{
334
- if (!RationalTime::is_valid_timecode_rate (rate))
327
+ if (!RationalTime::is_smpte_timecode_rate (rate))
335
328
{
336
329
set_error (
337
330
time_string,
@@ -460,7 +453,12 @@ RationalTime::to_timecode(
460
453
return std::string ();
461
454
}
462
455
463
- if (!is_valid_timecode_rate (rate))
456
+ // It is common practice to use truncated or rounded values
457
+ // like 29.97 instead of exact SMPTE rates like 30000/1001
458
+ // so as a convenience we will snap the rate to the nearest
459
+ // SMPTE rate if it is close enough.
460
+ double nearest_smpte_rate = nearest_smpte_timecode_rate (rate);
461
+ if (abs (nearest_smpte_rate - rate) > 0.1 )
464
462
{
465
463
if (error_status)
466
464
{
@@ -469,6 +467,9 @@ RationalTime::to_timecode(
469
467
return std::string ();
470
468
}
471
469
470
+ // Let's assume this is the rate instead of the given rate.
471
+ rate = nearest_smpte_rate;
472
+
472
473
bool rate_is_dropframe = is_dropframe_rate (rate);
473
474
if (drop_frame == IsDropFrameRate::ForceYes and not rate_is_dropframe)
474
475
{
@@ -504,11 +505,11 @@ RationalTime::to_timecode(
504
505
}
505
506
else
506
507
{
507
- if (( rate == 29.97 ) or (rate == 30000 / 1001.0 ) )
508
+ if (rate == 30000 / 1001.0 )
508
509
{
509
510
dropframes = 2 ;
510
511
}
511
- else if (rate == 59.94 )
512
+ else if (rate == 60000 / 1001.0 )
512
513
{
513
514
dropframes = 4 ;
514
515
}
@@ -582,7 +583,7 @@ RationalTime::to_nearest_timecode(
582
583
{
583
584
*error_status = ErrorStatus ();
584
585
585
- double nearest_rate = nearest_valid_timecode_rate (rate);
586
+ double nearest_rate = nearest_smpte_timecode_rate (rate);
586
587
587
588
return to_timecode (nearest_rate, drop_frame, error_status);
588
589
}
0 commit comments