1 /*
2 mkvmerge -- utility for splicing together matroska files
3 from component media subtypes
4
5 Distributed under the GPL v2
6 see the file COPYING for details
7 or visit https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
8
9 Written by Moritz Bunkus <moritz@bunkus.org>.
10 */
11
12 #include "common/common_pch.h"
13
14 #include "common/debugging.h"
15 #include "common/frame_timing.h"
16
17 namespace mtx::frame_timing {
18
19 std::vector<common_frame_rate_t> g_common_frame_rates{
20 { 1'000'000'000ll / 120, { 120, 1 } }, // 120 fps
21 { 1'000'000'000ll / 100, { 100, 1 } }, // 100 fps
22 { 1'000'000'000ll / 50, { 50, 1 } }, // 50 fps
23 { 1'000'000'000ll / 48, { 48, 1 } }, // 48 fps
24 { 1'000'000'000ll / 24, { 24, 1 } }, // 24 fps
25 { 1'000'000'000ll / 25, { 25, 1 } }, // 25 fps
26 { 1'000'000'000ll / 60, { 60, 1 } }, // 60 fps
27 { 1'000'000'000ll / 30, { 30, 1 } }, // 30 fps
28 { 1'000'000'000ll * 1'001 / 48'000, { 48'000, 1'001 } }, // 47.952 fps
29 { 1'000'000'000ll * 1'001 / 24'000, { 24'000, 1'001 } }, // 23.976 fps
30 { 1'000'000'000ll * 1'001 / 50'000, { 50'000, 1'001 } }, // 24.975 frames per second telecined PAL
31 { 1'000'000'000ll * 1'001 / 60'000, { 60'000, 1'001 } }, // 59.94 fps
32 { 1'000'000'000ll * 1'001 / 30'000, { 30'000, 1'001 } }, // 29.97 fps
33 };
34
35 mtx_mp_rational_t
determine_frame_rate(int64_t duration,int64_t max_difference)36 determine_frame_rate(int64_t duration,
37 int64_t max_difference) {
38 static debugging_option_c s_debug{"determine_frame_rate|fix_bitstream_timing_info"};
39
40 // search in the common FPS list
41 using common_frame_rate_diff_t = std::pair<int64_t, common_frame_rate_t>;
42 auto potentials = std::vector<common_frame_rate_diff_t>{};
43
44 for (auto const &common_frame_rate : g_common_frame_rates) {
45 auto difference = std::abs(duration - common_frame_rate.duration);
46 if (difference < max_difference)
47 potentials.emplace_back(difference, common_frame_rate);
48 }
49
50 if (potentials.empty()) {
51 mxdebug_if(s_debug, fmt::format("determine_frame_rate: duration {0} max_difference {1}: no match found\n", duration, max_difference));
52 return {};
53 }
54
55 std::sort(potentials.begin(), potentials.end(), [](auto const &a, auto const &b) {
56 return a.first < b.first;
57 });
58
59 mxdebug_if(s_debug,
60 fmt::format("determine_frame_rate: duration {0} max_difference {1}: {2} match(es) found returning {3} Δ {4}\n",
61 duration, max_difference, potentials.size(), potentials[0].second.frame_rate, potentials[0].first));
62
63 return potentials[0].second.frame_rate;
64 }
65
66 }
67