You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
7.0 KiB

/*
* ratiocodes.c -- database for all ratio/codes (asr, sar, dar, frc...)
* used in transcode
* (C) 2005-2010 - Francesco Romani <fromani -at- gmail -dot- com>
*
* This file is part of transcode, a video stream processing tool.
*
* transcode is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* transcode is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libtc.h"
#include "ratiocodes.h"
#include <stdlib.h>
#include <math.h>
#define TABLE_LEN(tab) (sizeof((tab))/sizeof((tab)[0]))
/* WARNING: this table MUST BE in frc order */
static const double frc_table[16] = {
0,
(24000.0/1001.0),
24,
25,
(30000.0/1001.0),
30,
50,
(2*(30000.0/1001.0)),
60,
1,
5,
10,
12,
15,
0,
0
};
/* WARNING: this table MUST BE in asr order */
static const double asr_table[8] = {
0.0,
1.0,
(4.0/3.0),
(16.0/9.0),
(221.0/100.0),
0.0,
0.0,
0.0,
};
/* WARNING: this table MUST BE in frc order */
static const TCPair frc_ratios[16] = {
{ 0, 0 },
{ 24000, 1001 },
{ 24000, 1000 },
{ 25000, 1000 },
{ 30000, 1001 },
{ 30000, 1000 },
{ 50000, 1000 },
{ 60000, 1001 },
{ 60000, 1000 },
/* XXX */
{ 1000, 1000 },
{ 5000, 1000 },
{ 10000, 1000 },
{ 12000, 1000 },
{ 15000, 1000 },
/* XXX */
{ 0, 0 },
{ 0, 0 },
};
/* WARNING: this table MUST BE in asr order */
static const TCPair asr_ratios[8] = {
{ 0, 0 },
{ 1, 1 },
{ 4, 3 },
{ 16, 9 },
{ 221, 100 },
{ 0, 0 },
{ 0, 0 },
{ 0, 0 },
/*
* XXX: import/tcprobe.c also claims that
* asr == 8 and asr == 12 are 4:3.
* Need further investigation.
*/
};
static const TCPair par_ratios[8] = {
{ 1, 1 },
{ 1, 1 },
{ 1200, 1100 },
{ 1000, 1100 },
{ 1600, 1100 },
{ 4000, 3300 },
{ 1, 1 },
{ 1, 1 }
};
/*************************************************************************/
const char *tc_asr_code_describe(int asr_code)
{
switch (asr_code) {
case 1:
return "encoded @ 1:1";
case 2:
return "encoded @ 4:3";
case 3:
return "encoded @ 16:9";
case 4:
return "encoded @ 2.21:1";
case 8:
return "encoded @ 4:3";
case 12:
return "encoded @ 4:3";
}
return "encoded @ UNKNOWN";
}
#define DELTA 0.0005
static int tc_guess_code_from_value(const double *pairs, size_t len,
int *code, double val)
{
int idx = TC_NULL_MATCH, i = 0;
double mindiff = DELTA;
for (i = 0; i < len; i++) {
double diff = fabs(pairs[i] - val);
if (diff < mindiff) {
mindiff = diff;
idx = i;
}
}
if (code != NULL && idx != TC_NULL_MATCH) {
*code = idx;
}
return idx;
}
#undef DELTA
int tc_asr_code_from_value(int *asr_code, double ratio)
{
return tc_guess_code_from_value(asr_table, TABLE_LEN(frc_table),
asr_code, ratio);
}
int tc_frc_code_from_value(int *frc_code, double fps)
{
return tc_guess_code_from_value(frc_table, TABLE_LEN(frc_table),
frc_code, fps);
}
int tc_frc_code_to_value(int frc_code, double *fps)
{
if ((fps != NULL && frc_code >= 0)
&& frc_code <= TABLE_LEN(frc_table)) {
*fps = frc_table[frc_code];
return 0;
}
return TC_NULL_MATCH;
}
/*
* match_ratio:
* helper for various detection functions. Scans a ratio
* table (that MUST be in frc order) looking for corrispondences
* between a ratio and a ratio code.
*
* Parameters:
* pairs: pointer to an array of TCPair to scan
* len: number of pairs to consider
* n: numerator of ratio to look for. Use TC_NULL_MATCH
* if this function must look for a corrispondency of code
* and not for a corrispondency of ratio.
* d: denominator of ratio to look for. Use TC_NULL_MATCH
* if this function must look for a corrispondency of code
* and not for a corrispondency of ratio.
* code: code of ratio to look for. Use TC_NULL_MATCH if this function
* must look for a corrispondency of ratio.
* Return Value:
* TC_NULL_MATCH if input parameter(s) isn't known.
* >= 0 index in table of given corrispondency.
* Precondintions:
* given pairs table MUST BE in code (frc, asr) order.
* pairs != NULL.
*/
static int match_ratio(const TCPair *pairs, size_t len,
int n, int d, int code)
{
int i = 0, r = TC_NULL_MATCH;
for (i = 0; i < len; i++) {
if (i == code) {
r = i;
break;
}
if (n == pairs[i].a && d == pairs[i].b) {
r = i;
break;
}
}
return r;
}
static int select_table(TCRatioCode rc, const TCPair **table, size_t *len)
{
int ret = 0;
switch (rc) {
case TC_FRC_CODE:
*table = frc_ratios;
*len = TABLE_LEN(frc_ratios);
break;
case TC_ASR_CODE:
*table = asr_ratios;
*len = TABLE_LEN(asr_ratios);
break;
case TC_PAR_CODE:
*table = par_ratios;
*len = TABLE_LEN(par_ratios);
break;
default:
*table = NULL;
*len = 0;
ret = TC_NULL_MATCH;
}
return ret;
}
int tc_code_from_ratio(TCRatioCode rc, int *out_code, int in_n, int in_d)
{
int code = TC_NULL_MATCH;
const TCPair *table = NULL;
size_t len = 0;
select_table(rc, &table, &len);
if (table != NULL) {
code = match_ratio(table, len, in_n, in_d, TC_NULL_MATCH);
if (out_code != NULL && code != TC_NULL_MATCH) {
*out_code = code;
}
}
return code;
}
int tc_code_to_ratio(TCRatioCode rc, int in_code, int *out_n, int *out_d)
{
int code = TC_NULL_MATCH;
const TCPair *table = NULL;
size_t len = 0;
select_table(rc, &table, &len);
if (table != NULL) {
code = match_ratio(table, len,
TC_NULL_MATCH, TC_NULL_MATCH, in_code);
if ((out_n != NULL && out_d != NULL) && code != TC_NULL_MATCH) {
*out_n = table[code].a;
*out_d = table[code].b;
}
}
return code;
}
/*************************************************************************/
/*
* Local variables:
* c-file-style: "stroustrup"
* c-file-offsets: ((case-label . *) (statement-case-intro . *))
* indent-tabs-mode: nil
* End:
*
* vim: expandtab shiftwidth=4:
*/