@@ -13,75 +13,68 @@ namespace opentime { namespace OPENTIME_VERSION {
1313
1414RationalTime RationalTime::_invalid_time{ 0 , RationalTime::_invalid_rate };
1515
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{ {
2217 30000.0 / 1001.0 ,
23- 59.94 ,
2418 60000.0 / 1001.0 ,
2519} };
2620
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+ //
2725static constexpr std::array<double , 11 > smpte_timecode_rates{
28- { 1.0 ,
29- 12.0 ,
30- 24000.0 / 1001.0 ,
26+ { 24000.0 / 1001.0 ,
3127 24.0 ,
3228 25.0 ,
3329 30000.0 / 1001.0 ,
3430 30.0 ,
31+ 48000.0 / 1001.0 ,
3532 48.0 ,
3633 50.0 ,
3734 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+ }
5837};
5938
39+ // deprecated in favor of `is_smpte_timecode_rate`
6040bool
6141RationalTime::is_valid_timecode_rate (double fps)
6242{
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 ();
6450 return std::find (b, e, fps) != e;
6551}
6652
53+ // deprecated in favor of `is_smpte_timecode_rate`
6754double
6855RationalTime::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)
6962{
7063 double nearest_rate = 0 ;
7164 double min_diff = std::numeric_limits<double >::max ();
72- for (auto valid_rate : smpte_timecode_rates)
65+ for (auto smpte_rate : smpte_timecode_rates)
7366 {
74- if (valid_rate == rate)
67+ if (smpte_rate == rate)
7568 {
7669 return rate;
7770 }
78- auto diff = std::abs (rate - valid_rate );
71+ auto diff = std::abs (rate - smpte_rate );
7972 if (diff >= min_diff)
8073 {
8174 continue ;
8275 }
8376 min_diff = diff;
84- nearest_rate = valid_rate ;
77+ nearest_rate = smpte_rate ;
8578 }
8679 return nearest_rate;
8780}
@@ -200,7 +193,7 @@ RationalTime::from_timecode(
200193 double rate,
201194 ErrorStatus* error_status)
202195{
203- if (!RationalTime::is_valid_timecode_rate (rate))
196+ if (!RationalTime::is_smpte_timecode_rate (rate))
204197 {
205198 if (error_status)
206199 {
@@ -331,7 +324,7 @@ RationalTime::from_time_string(
331324 double rate,
332325 ErrorStatus* error_status)
333326{
334- if (!RationalTime::is_valid_timecode_rate (rate))
327+ if (!RationalTime::is_smpte_timecode_rate (rate))
335328 {
336329 set_error (
337330 time_string,
@@ -460,7 +453,12 @@ RationalTime::to_timecode(
460453 return std::string ();
461454 }
462455
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 )
464462 {
465463 if (error_status)
466464 {
@@ -469,6 +467,9 @@ RationalTime::to_timecode(
469467 return std::string ();
470468 }
471469
470+ // Let's assume this is the rate instead of the given rate.
471+ rate = nearest_smpte_rate;
472+
472473 bool rate_is_dropframe = is_dropframe_rate (rate);
473474 if (drop_frame == IsDropFrameRate::ForceYes and not rate_is_dropframe)
474475 {
@@ -504,11 +505,11 @@ RationalTime::to_timecode(
504505 }
505506 else
506507 {
507- if (( rate == 29.97 ) or (rate == 30000 / 1001.0 ) )
508+ if (rate == 30000 / 1001.0 )
508509 {
509510 dropframes = 2 ;
510511 }
511- else if (rate == 59.94 )
512+ else if (rate == 60000 / 1001.0 )
512513 {
513514 dropframes = 4 ;
514515 }
@@ -582,7 +583,7 @@ RationalTime::to_nearest_timecode(
582583 {
583584 *error_status = ErrorStatus ();
584585
585- double nearest_rate = nearest_valid_timecode_rate (rate);
586+ double nearest_rate = nearest_smpte_timecode_rate (rate);
586587
587588 return to_timecode (nearest_rate, drop_frame, error_status);
588589 }
0 commit comments