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 24const 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 44void 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 97found: 98 *code = best_c; 99 if (mpeg2) { 100 *ext_n = best_n - 1; 101 *ext_d = best_d - 1; 102 } 103} 104