1 
2 /*
3  *  mpegconsts.c:  Video format constants for MPEG and utilities for display
4  *                 and conversion to format used for yuv4mpeg
5  *
6  *  Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com>
7  *  Copyright (C) 2001 Matthew Marjanovic <maddog@mir.com>
8  *
9  *
10  *  This program is free software; you can redistribute it and/or
11  *  modify it under the terms of version 2 of the GNU General Public License
12  *  as published by the Free Software Foundation.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  */
23 
24 #include <config.h>
25 #include "mpegconsts.h"
26 #include "yuv4mpeg.h"
27 #include "yuv4mpeg_intern.h"
28 #include "format_codes.h"
29 
30 static y4m_ratio_t
31 mpeg_framerates[] = {
32   Y4M_FPS_UNKNOWN,
33   Y4M_FPS_NTSC_FILM,
34   Y4M_FPS_FILM,
35   Y4M_FPS_PAL,
36   Y4M_FPS_NTSC,
37   Y4M_FPS_30,
38   Y4M_FPS_PAL_FIELD,
39   Y4M_FPS_NTSC_FIELD,
40   Y4M_FPS_60
41 };
42 
43 
44 #define MPEG_NUM_RATES (sizeof(mpeg_framerates)/sizeof(mpeg_framerates[0]))
45 static const mpeg_framerate_code_t mpeg_num_framerates = MPEG_NUM_RATES;
46 
47 static const char *
48 framerate_definitions[MPEG_NUM_RATES] =
49 {
50    "illegal",
51   "24000.0/1001.0 (NTSC 3:2 pulldown converted FILM)",
52   "24.0 (NATIVE FILM)",
53   "25.0 (PAL/SECAM VIDEO / converted FILM)",
54   "30000.0/1001.0 (NTSC VIDEO)",
55   "30.0",
56   "50.0 (PAL FIELD RATE)",
57   "60000.0/1001.0 (NTSC FIELD RATE)",
58   "60.0"
59 };
60 
61 
62 static const char *mpeg1_aspect_ratio_definitions[] =
63 {
64     "illegal",
65 	"1:1 (square pixels)",
66 	"1:0.6735",
67 	"1:0.7031 (16:9 Anamorphic PAL/SECAM for 720x578/352x288 images)",
68 	"1:0.7615",
69 	"1:0.8055",
70 	"1:0.8437 (16:9 Anamorphic NTSC for 720x480/352x240 images)",
71 	"1:0.8935",
72 	"1:0.9375 (4:3 PAL/SECAM for 720x578/352x288 images)",
73 	"1:0.9815",
74 	"1:1.0255",
75 	"1:1:0695",
76 	"1:1.1250 (4:3 NTSC for 720x480/352x240 images)",
77 	"1:1.1575",
78 	"1:1.2015"
79 };
80 
81 static const y4m_ratio_t mpeg1_aspect_ratios[] =
82 {
83     Y4M_SAR_UNKNOWN,
84 	Y4M_SAR_MPEG1_1,
85 	Y4M_SAR_MPEG1_2,
86 	Y4M_SAR_MPEG1_3, /* Anamorphic 16:9 PAL */
87 	Y4M_SAR_MPEG1_4,
88 	Y4M_SAR_MPEG1_5,
89 	Y4M_SAR_MPEG1_6, /* Anamorphic 16:9 NTSC */
90 	Y4M_SAR_MPEG1_7,
91 	Y4M_SAR_MPEG1_8, /* PAL/SECAM 4:3 */
92 	Y4M_SAR_MPEG1_9,
93 	Y4M_SAR_MPEG1_10,
94 	Y4M_SAR_MPEG1_11,
95 	Y4M_SAR_MPEG1_12, /* NTSC 4:3 */
96 	Y4M_SAR_MPEG1_13,
97 	Y4M_SAR_MPEG1_14,
98 };
99 
100 static const char *mpeg2_aspect_ratio_definitions[] =
101 {
102     "illegal",
103 	"1:1 pixels",
104 	"4:3 display",
105 	"16:9 display",
106 	"2.21:1 display"
107 };
108 
109 
110 static const y4m_ratio_t mpeg2_aspect_ratios[] =
111 {
112     Y4M_DAR_UNKNOWN,
113 	Y4M_DAR_MPEG2_1,
114 	Y4M_DAR_MPEG2_2,
115  	Y4M_DAR_MPEG2_3,
116 	Y4M_DAR_MPEG2_4
117 };
118 
119 static const char **aspect_ratio_definitions[2] =
120 {
121 	mpeg1_aspect_ratio_definitions,
122 	mpeg2_aspect_ratio_definitions
123 };
124 
125 static const y4m_ratio_t *mpeg_aspect_ratios[2] =
126 {
127 	mpeg1_aspect_ratios,
128 	mpeg2_aspect_ratios
129 };
130 
131 static const mpeg_aspect_code_t mpeg_num_aspect_ratios[2] =
132 {
133   sizeof(mpeg1_aspect_ratios)/sizeof(mpeg1_aspect_ratios[0]),
134   sizeof(mpeg2_aspect_ratios)/sizeof(mpeg2_aspect_ratios[0])
135 };
136 
137 static const char *mjpegtools_format_code_definitions[MPEG_FORMAT_LAST+1] =
138 {
139     "Generic MPEG1",
140     "Standard VCD",
141     "Stretched VCD",
142     "Generic MPEG2",
143     "Standard SVCD",
144     "Stretched SVCD",
145     "VCD Still",
146     "SVCD Still",
147     "DVD with dummy navigation packets",
148     "Standard DVD",
149     "ATSC 480i",
150     "ATSC 480p",
151     "ATSC 720p",
152     "ATSC 1080i"
153 };
154 
155 /*
156  * Is code a valid MPEG framerate code?
157  */
158 
159 int
mpeg_valid_framerate_code(mpeg_framerate_code_t code)160 mpeg_valid_framerate_code( mpeg_framerate_code_t code )
161 {
162     return ((code > 0) && (code < mpeg_num_framerates)) ? 1 : 0;
163 }
164 
165 
166 /*
167  * Convert MPEG frame-rate code to corresponding frame-rate
168  */
169 
170 y4m_ratio_t
mpeg_framerate(mpeg_framerate_code_t code)171 mpeg_framerate( mpeg_framerate_code_t code )
172 {
173     if ((code > 0) && (code < mpeg_num_framerates))
174 		return mpeg_framerates[code];
175     else
176 		return y4m_fps_UNKNOWN;
177 }
178 
179 /*
180  * Look-up MPEG frame rate code for a (exact) frame rate.
181  */
182 
183 
184 mpeg_framerate_code_t
mpeg_framerate_code(y4m_ratio_t framerate)185 mpeg_framerate_code( y4m_ratio_t framerate )
186 {
187 	mpeg_framerate_code_t i;
188 
189 	y4m_ratio_reduce(&framerate);
190     /* start at '1', because 0 is unknown/illegal */
191 	for (i = 1; i < mpeg_num_framerates; ++i) {
192 		if (Y4M_RATIO_EQL(framerate, mpeg_framerates[i]))
193 			return i;
194 	}
195 	return 0;
196 }
197 
198 
199 /* small enough to distinguish 1/1000 from 1/1001 */
200 #define MPEG_FPS_TOLERANCE 0.0001
201 
202 
203 y4m_ratio_t
mpeg_conform_framerate(double fps)204 mpeg_conform_framerate( double fps )
205 {
206 	mpeg_framerate_code_t i;
207 	y4m_ratio_t result;
208 
209 	/* try to match it to a standard frame rate */
210     /* (start at '1', because 0 is unknown/illegal) */
211 	for (i = 1; i < mpeg_num_framerates; i++)
212 	{
213 		double deviation = 1.0 - (Y4M_RATIO_DBL(mpeg_framerates[i]) / fps);
214 		if ( (deviation > -MPEG_FPS_TOLERANCE) &&
215 			 (deviation < +MPEG_FPS_TOLERANCE) )
216 			return mpeg_framerates[i];
217 	}
218 	/* no luck?  just turn it into a ratio (6 decimal place accuracy) */
219 	result.n = (int)((fps * 1000000.0) + 0.5);
220 	result.d = 1000000;
221 	y4m_ratio_reduce(&result);
222 	return result;
223 }
224 
225 
226 
227 /*
228  * Is code a valid MPEG aspect-ratio code?
229  */
230 
231 int
mpeg_valid_aspect_code(int version,mpeg_framerate_code_t c)232 mpeg_valid_aspect_code( int version, mpeg_framerate_code_t c )
233 {
234 	if ((version == 1) || (version == 2))
235         return ((c > 0) && (c < mpeg_num_aspect_ratios[version-1])) ? 1 : 0;
236     else
237         return 0;
238 }
239 
240 
241 /*
242  * Convert MPEG aspect-ratio code to corresponding aspect-ratio
243  */
244 
245 y4m_ratio_t
mpeg_aspect_ratio(int mpeg_version,mpeg_aspect_code_t code)246 mpeg_aspect_ratio( int mpeg_version,  mpeg_aspect_code_t code )
247 {
248 	y4m_ratio_t ratio;
249     if ((mpeg_version >= 1) && (mpeg_version <= 2) &&
250         (code > 0) && (code < mpeg_num_aspect_ratios[mpeg_version-1]))
251 	{
252 		ratio = mpeg_aspect_ratios[mpeg_version-1][code];
253 		y4m_ratio_reduce(&ratio);
254 		return ratio;
255 	}
256     else
257 		return y4m_sar_UNKNOWN;
258 }
259 
260 
261 
262 /*
263  * Look-up corresponding MPEG aspect ratio code given an exact aspect ratio.
264  *
265  * WARNING: The semantics of aspect ratio coding *changed* between
266  * MPEG1 and MPEG2.  In MPEG1 it is the *pixel* aspect ratio. In
267  * MPEG2 it is the (far more sensible) aspect ratio of the eventual
268  * display.
269  *
270  */
271 
272 mpeg_aspect_code_t
mpeg_frame_aspect_code(int mpeg_version,y4m_ratio_t aspect_ratio)273 mpeg_frame_aspect_code( int mpeg_version, y4m_ratio_t aspect_ratio )
274 {
275 	mpeg_aspect_code_t i;
276 	y4m_ratio_t red_ratio = aspect_ratio;
277 	y4m_ratio_reduce( &red_ratio );
278 	if( mpeg_version < 1 || mpeg_version > 2 )
279 		return 0;
280     /* (start at '1', because 0 is unknown/illegal) */
281 	for( i = 1; i < mpeg_num_aspect_ratios[mpeg_version-1]; ++i )
282 	{
283 		y4m_ratio_t red_entry =  mpeg_aspect_ratios[mpeg_version-1][i];
284 		y4m_ratio_reduce( &red_entry );
285 		if(  Y4M_RATIO_EQL( red_entry, red_ratio) )
286 			return i;
287 	}
288 
289 	return 0;
290 
291 }
292 
293 
294 
295 /*
296  * Guess the correct MPEG aspect ratio code,
297  *  given the true sample aspect ratio and frame size of a video stream
298  *  (and the MPEG version, 1 or 2).
299  *
300  * Returns 0 if it has no good guess.
301  *
302  */
303 
304 
305 /* this is big enough to accommodate the difference between 720 and 704 */
306 #define GUESS_ASPECT_TOLERANCE 0.03
307 
308 mpeg_aspect_code_t
mpeg_guess_mpeg_aspect_code(int mpeg_version,y4m_ratio_t sampleaspect,int frame_width,int frame_height)309 mpeg_guess_mpeg_aspect_code(int mpeg_version, y4m_ratio_t sampleaspect,
310 							int frame_width, int frame_height)
311 {
312 	if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_UNKNOWN))
313     {
314 		return 0;
315     }
316 	switch (mpeg_version) {
317 	case 1:
318 		if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE))
319 		{
320 			return 1;
321 		}
322 		else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_CCIR601))
323 		{
324 			return 12;
325 		}
326 		else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_NTSC_16_9))
327 		{
328 			return 6;
329 		}
330 		else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_CCIR601))
331 		{
332 			return 8;
333 		}
334 		else if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_PAL_16_9))
335 		{
336 			return 3;
337 		}
338 		return 0;
339 		break;
340 	case 2:
341 		if (Y4M_RATIO_EQL(sampleaspect, y4m_sar_SQUARE))
342 		{
343 			return 1;  /* '1' means square *pixels* in MPEG-2; go figure. */
344 		}
345 		else
346 		{
347 			int i;
348 			double true_far;  /* true frame aspect ratio */
349 			true_far =
350 				(double)(sampleaspect.n * frame_width) /
351 				(double)(sampleaspect.d * frame_height);
352 			/* start at '2'... */
353 			for (i = 2; i < (int)(mpeg_num_aspect_ratios[mpeg_version-1]); i++)
354 			{
355 				double ratio =
356 					true_far / Y4M_RATIO_DBL(mpeg_aspect_ratios[mpeg_version-1][i]);
357 				if ( (ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) &&
358 					 (ratio < (1.0 + GUESS_ASPECT_TOLERANCE)) )
359 					return i;
360 			}
361 			return 0;
362 		}
363 		break;
364 	default:
365 		return 0;
366 		break;
367 	}
368 }
369 
370 
371 
372 
373 /*
374  * Guess the true sample aspect ratio of a video stream,
375  *  given the MPEG aspect ratio code and the actual frame size
376  *  (and the MPEG version, 1 or 2).
377  *
378  * Returns y4m_sar_UNKNOWN if it has no good guess.
379  *
380  */
381 y4m_ratio_t
mpeg_guess_sample_aspect_ratio(int mpeg_version,mpeg_aspect_code_t code,int frame_width,int frame_height)382 mpeg_guess_sample_aspect_ratio(int mpeg_version,
383 							   mpeg_aspect_code_t code,
384 							   int frame_width, int frame_height)
385 {
386 	switch (mpeg_version)
387 	{
388 	case 1:
389 		/* MPEG-1 codes turn into SAR's, just not quite the right ones.
390 		   For the common/known values, we provide the ratio used in practice,
391 		   otherwise say we don't know.*/
392 		switch (code)
393 		{
394 		case 1:  return y4m_sar_SQUARE;        break;
395 		case 3:  return y4m_sar_PAL_16_9;      break;
396 		case 6:  return y4m_sar_NTSC_16_9;     break;
397 		case 8:  return y4m_sar_PAL_CCIR601;   break;
398 		case 12: return y4m_sar_NTSC_CCIR601;  break;
399 		default:
400 			return y4m_sar_UNKNOWN;       break;
401 		}
402 		break;
403 	case 2:
404 		/* MPEG-2 codes turn into Display Aspect Ratios, though not exactly the
405 		   DAR's used in practice.  For common/standard frame sizes, we provide
406 		   the original SAR; otherwise, we say we don't know. */
407 		if (code == 1)
408 		{
409 			return y4m_sar_SQUARE; /* '1' means square *pixels* in MPEG-2 */
410 		}
411 		else if ((code >= 2) && (code <= 4))
412 		{
413             return y4m_guess_sar(frame_width, frame_height,
414                                  mpeg2_aspect_ratios[code]);
415 		}
416 		else
417 		{
418 			return y4m_sar_UNKNOWN;
419 		}
420 		break;
421 	default:
422 		return y4m_sar_UNKNOWN;
423 		break;
424 	}
425 }
426 
427 
428 
429 
430 
431 /*
432  * Look-up MPEG explanatory definition string for frame rate code
433  *
434  */
435 
436 
437 const char *
mpeg_framerate_code_definition(mpeg_framerate_code_t code)438 mpeg_framerate_code_definition(   mpeg_framerate_code_t code  )
439 {
440 	if( code == 0 || code >=  mpeg_num_framerates )
441 		return "UNDEFINED: illegal/reserved frame-rate ratio code";
442 
443 	return framerate_definitions[code];
444 }
445 
446 /*
447  * Look-up MPEG explanatory definition string aspect ratio code for an
448  * aspect ratio code
449  *
450  */
451 
452 const char *
mpeg_aspect_code_definition(int mpeg_version,mpeg_aspect_code_t code)453 mpeg_aspect_code_definition( int mpeg_version,  mpeg_aspect_code_t code  )
454 {
455 	if( mpeg_version < 1 || mpeg_version > 2 )
456 		return "UNDEFINED: illegal MPEG version";
457 
458 	if( code < 1 || code >=  mpeg_num_aspect_ratios[mpeg_version-1] )
459 		return "UNDEFINED: illegal aspect ratio code";
460 
461 	return aspect_ratio_definitions[mpeg_version-1][code];
462 }
463 
464 
465 /*
466  * Look-up explanatory definition of interlace field order code
467  *
468  */
469 
470 const char *
mpeg_interlace_code_definition(int yuv4m_interlace_code)471 mpeg_interlace_code_definition( int yuv4m_interlace_code )
472 {
473 	const char *def;
474 	switch( yuv4m_interlace_code )
475 	{
476 	case Y4M_UNKNOWN :
477 		def = "unknown";
478 		break;
479 	case Y4M_ILACE_NONE :
480 		def = "none/progressive";
481 		break;
482 	case Y4M_ILACE_TOP_FIRST :
483 		def = "top-field-first";
484 		break;
485 	case Y4M_ILACE_BOTTOM_FIRST :
486 		def = "bottom-field-first";
487 		break;
488 	default :
489 		def = "UNDEFINED: illegal video interlacing type-code!";
490 		break;
491 	}
492 	return def;
493 }
494 
495 /*
496  * Look-up explanatory definition of mjepgtools preset format code
497  *
498  */
mpeg_format_code_defintion(int format_code)499 const char *mpeg_format_code_defintion( int format_code )
500 {
501     if(format_code >= MPEG_FORMAT_FIRST && format_code <= MPEG_FORMAT_LAST )
502         return mjpegtools_format_code_definitions[format_code];
503     else
504         return "UNDEFINED: illegal format code!";
505 };
506 
507 /*
508  * Local variables:
509  *  c-file-style: "stroustrup"
510  *  tab-width: 4
511  *  indent-tabs-mode: nil
512  * End:
513  */
514