summaryrefslogtreecommitdiff
path: root/gst-libs/ext/mplex/yuv4mpeg_ratio.cc
blob: e02be6769bf103533493ae2836833ffcc3f2ed0a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
 *  yuv4mpeg_ratio.c:  Functions for dealing with y4m_ratio_t datatype.
 *
 *  Copyright (C) 2001 Matthew J. Marjanovic <maddog@mir.com>
 *
 *
 *  This program 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.
 *
 *  This program 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

#include <config.h>

#include <string.h>
#include "yuv4mpeg.h"
#include "yuv4mpeg_intern.h"


/* useful list of standard framerates */
const y4m_ratio_t y4m_fps_UNKNOWN = Y4M_FPS_UNKNOWN;
const y4m_ratio_t y4m_fps_NTSC_FILM = Y4M_FPS_NTSC_FILM;
const y4m_ratio_t y4m_fps_FILM = Y4M_FPS_FILM;
const y4m_ratio_t y4m_fps_PAL = Y4M_FPS_PAL;
const y4m_ratio_t y4m_fps_NTSC = Y4M_FPS_NTSC;
const y4m_ratio_t y4m_fps_30 = Y4M_FPS_30;
const y4m_ratio_t y4m_fps_PAL_FIELD = Y4M_FPS_PAL_FIELD;
const y4m_ratio_t y4m_fps_NTSC_FIELD = Y4M_FPS_NTSC_FIELD;
const y4m_ratio_t y4m_fps_60 = Y4M_FPS_60;

/* useful list of standard sample aspect ratios */
const y4m_ratio_t y4m_sar_UNKNOWN = Y4M_SAR_UNKNOWN;
const y4m_ratio_t y4m_sar_SQUARE = Y4M_SAR_SQUARE;
const y4m_ratio_t y4m_sar_SQR_ANA_16_9 = Y4M_SAR_SQR_ANA_16_9;
const y4m_ratio_t y4m_sar_NTSC_CCIR601 = Y4M_SAR_NTSC_CCIR601;
const y4m_ratio_t y4m_sar_NTSC_16_9 = Y4M_SAR_NTSC_16_9;
const y4m_ratio_t y4m_sar_NTSC_SVCD_4_3 = Y4M_SAR_NTSC_SVCD_4_3;
const y4m_ratio_t y4m_sar_NTSC_SVCD_16_9 = Y4M_SAR_NTSC_SVCD_16_9;
const y4m_ratio_t y4m_sar_PAL_CCIR601 = Y4M_SAR_PAL_CCIR601;
const y4m_ratio_t y4m_sar_PAL_16_9 = Y4M_SAR_PAL_16_9;
const y4m_ratio_t y4m_sar_PAL_SVCD_4_3 = Y4M_SAR_PAL_SVCD_4_3;
const y4m_ratio_t y4m_sar_PAL_SVCD_16_9 = Y4M_SAR_PAL_SVCD_16_9;

/* useful list of standard display aspect ratios */
const y4m_ratio_t y4m_dar_4_3 = Y4M_DAR_4_3;
const y4m_ratio_t y4m_dar_16_9 = Y4M_DAR_16_9;
const y4m_ratio_t y4m_dar_221_100 = Y4M_DAR_221_100;

/*
 *  Euler's algorithm for greatest common divisor
 */

static int
gcd (int a, int b)
{
  a = (a >= 0) ? a : -a;
  b = (b >= 0) ? b : -b;

  while (b > 0) {
    int x = b;

    b = a % b;
    a = x;
  }
  return a;
}


/*************************************************************************
 *
 * Remove common factors from a ratio
 *
 *************************************************************************/


void
y4m_ratio_reduce (y4m_ratio_t * r)
{
  int d;

  if ((r->n == 0) && (r->d == 0))
    return;			/* "unknown" */
  d = gcd (r->n, r->d);
  r->n /= d;
  r->d /= d;
}



/*************************************************************************
 *
 * Parse "nnn:ddd" into a ratio
 *
 * returns:         Y4M_OK  - success
 *           Y4M_ERR_RANGE  - range error 
 *
 *************************************************************************/

int
y4m_parse_ratio (y4m_ratio_t * r, const char *s)
{
  const char *t = strchr (s, ':');

  if (t == NULL)
    return Y4M_ERR_RANGE;
  r->n = atoi (s);
  r->d = atoi (t + 1);
  if (r->d < 0)
    return Y4M_ERR_RANGE;
  /* 0:0 == unknown, so that is ok, otherwise zero denominator is bad */
  if ((r->d == 0) && (r->n != 0))
    return Y4M_ERR_RANGE;
  y4m_ratio_reduce (r);
  return Y4M_OK;
}



/*************************************************************************
 *
 * Guess the true SAR (sample aspect ratio) from a list of commonly 
 * encountered values, given the "suggested" display aspect ratio, and
 * the true frame width and height.
 *
 * Returns y4m_sar_UNKNOWN if no match is found.
 *
 *************************************************************************/

/* this is big enough to accommodate the difference between 720 and 704 */
#define GUESS_ASPECT_TOLERANCE 0.03

y4m_ratio_t
y4m_guess_sar (int width, int height, y4m_ratio_t dar)
{
  int i;
  double implicit_sar = (double) (dar.n * height) / (double) (dar.d * width);
  y4m_ratio_t sarray[] = {
    y4m_sar_SQUARE,
    y4m_sar_NTSC_CCIR601,
    y4m_sar_NTSC_16_9,
    y4m_sar_NTSC_SVCD_4_3,
    y4m_sar_NTSC_SVCD_16_9,
    y4m_sar_PAL_CCIR601,
    y4m_sar_PAL_16_9,
    y4m_sar_PAL_SVCD_4_3,
    y4m_sar_PAL_SVCD_16_9,
    y4m_sar_UNKNOWN
  };

  for (i = 0; !(Y4M_RATIO_EQL (sarray[i], y4m_sar_UNKNOWN)); i++) {
    double ratio = implicit_sar / Y4M_RATIO_DBL (sarray[i]);

    if ((ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && (ratio < (1.0 + GUESS_ASPECT_TOLERANCE)))
      return sarray[i];
  }
  return y4m_sar_UNKNOWN;
}