1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "libavutil/rational.h"
20 
21 #include "mpeg12.h"
22 #include "mpeg12data.h"
23 
24 const AVRational ff_mpeg12_frame_rate_tab[16] = {
25     {    0,    0},
26     {24000, 1001},
27     {   24,    1},
28     {   25,    1},
29     {30000, 1001},
30     {   30,    1},
31     {   50,    1},
32     {60000, 1001},
33     {   60,    1},
34   // Xing's 15fps: (9)
35     {   15,    1},
36   // libmpeg3's "Unofficial economy rates": (10-13)
37     {    5,    1},
38     {   10,    1},
39     {   12,    1},
40     {   15,    1},
41     {    0,    0},
42 };
43 
ff_mpeg12_find_best_frame_rate(AVRational frame_rate,int * code,int * ext_n,int * ext_d,int nonstandard)44 void ff_mpeg12_find_best_frame_rate(AVRational frame_rate,
45                                     int *code, int *ext_n, int *ext_d,
46                                     int nonstandard)
47 {
48     int mpeg2 = ext_n && ext_d;
49     int max_code = nonstandard ? 12 : 8;
50     int c, n, d, best_c, best_n, best_d;
51     AVRational best_error = { INT_MAX, 1 };
52 
53     // Default to NTSC if the inputs make no sense.
54     best_c = 4;
55     best_n = best_d = 1;
56 
57     for (c = 1; c <= max_code; c++) {
58         if (av_cmp_q(frame_rate, ff_mpeg12_frame_rate_tab[c]) == 0) {
59             best_c = c;
60             goto found;
61         }
62     }
63 
64     for (c = 1; c <= max_code; c++) {
65         for (n = 1; n <= (mpeg2 ? 4 : 1); n++) {
66             for (d = 1; d <= (mpeg2 ? 32 : 1); d++) {
67                 AVRational test, error;
68                 int cmp;
69 
70                 test = av_mul_q(ff_mpeg12_frame_rate_tab[c],
71                                 (AVRational) { n, d });
72 
73                 cmp = av_cmp_q(test, frame_rate);
74                 if (cmp == 0) {
75                     best_c = c;
76                     best_n = n;
77                     best_d = d;
78                     goto found;
79                 }
80 
81                 if (cmp < 0)
82                     error = av_div_q(frame_rate, test);
83                 else
84                     error = av_div_q(test, frame_rate);
85 
86                 cmp = av_cmp_q(error, best_error);
87                 if (cmp < 0 || (cmp == 0 && n == 1 && d == 1)) {
88                     best_c = c;
89                     best_n = n;
90                     best_d = d;
91                     best_error = error;
92                 }
93             }
94         }
95     }
96 
97 found:
98     *code = best_c;
99     if (mpeg2) {
100         *ext_n = best_n - 1;
101         *ext_d = best_d - 1;
102     }
103 }
104