diff options
Diffstat (limited to 'gst-libs/ext/mplex/mpegconsts.cc')
-rw-r--r-- | gst-libs/ext/mplex/mpegconsts.cc | 427 |
1 files changed, 427 insertions, 0 deletions
diff --git a/gst-libs/ext/mplex/mpegconsts.cc b/gst-libs/ext/mplex/mpegconsts.cc new file mode 100644 index 00000000..2265da3a --- /dev/null +++ b/gst-libs/ext/mplex/mpegconsts.cc @@ -0,0 +1,427 @@ + +/* + * mpegconsts.c: Video format constants for MPEG and utilities for display + * and conversion to format used for yuv4mpeg + * + * Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com> + * Copyright (C) 2001 Matthew Marjanovic <maddog@mir.com> + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * 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 "mpegconsts.h" +#include "yuv4mpeg.h" +#include "yuv4mpeg_intern.h" + +static y4m_ratio_t mpeg_framerates[] = { + Y4M_FPS_UNKNOWN, + Y4M_FPS_NTSC_FILM, + Y4M_FPS_FILM, + Y4M_FPS_PAL, + Y4M_FPS_NTSC, + Y4M_FPS_30, + Y4M_FPS_PAL_FIELD, + Y4M_FPS_NTSC_FIELD, + Y4M_FPS_60 +}; + + +#define MPEG_NUM_RATES (sizeof(mpeg_framerates)/sizeof(mpeg_framerates[0])) +const mpeg_framerate_code_t mpeg_num_framerates = MPEG_NUM_RATES; + +static const char *framerate_definitions[MPEG_NUM_RATES] = { + "illegal", + "24000.0/1001.0 (NTSC 3:2 pulldown converted FILM)", + "24.0 (NATIVE FILM)", + "25.0 (PAL/SECAM VIDEO / converted FILM)", + "30000.0/1001.0 (NTSC VIDEO)", + "30.0", + "50.0 (PAL FIELD RATE)", + "60000.0/1001.0 (NTSC FIELD RATE)", + "60.0" +}; + + +static const char *mpeg1_aspect_ratio_definitions[] = { + "1:1 (square pixels)", + "1:0.6735", + "1:0.7031 (16:9 Anamorphic PAL/SECAM for 720x578/352x288 images)", + "1:0.7615", + "1:0.8055", + "1:0.8437 (16:9 Anamorphic NTSC for 720x480/352x240 images)", + "1:0.8935", + "1:0.9375 (4:3 PAL/SECAM for 720x578/352x288 images)", + "1:0.9815", + "1:1.0255", + "1:1:0695", + "1:1.1250 (4:3 NTSC for 720x480/352x240 images)", + "1:1.1575", + "1:1.2015" +}; + +static const y4m_ratio_t mpeg1_aspect_ratios[] = { + Y4M_SAR_MPEG1_1, + Y4M_SAR_MPEG1_2, + Y4M_SAR_MPEG1_3, /* Anamorphic 16:9 PAL */ + Y4M_SAR_MPEG1_4, + Y4M_SAR_MPEG1_5, + Y4M_SAR_MPEG1_6, /* Anamorphic 16:9 NTSC */ + Y4M_SAR_MPEG1_7, + Y4M_SAR_MPEG1_8, /* PAL/SECAM 4:3 */ + Y4M_SAR_MPEG1_9, + Y4M_SAR_MPEG1_10, + Y4M_SAR_MPEG1_11, + Y4M_SAR_MPEG1_12, /* NTSC 4:3 */ + Y4M_SAR_MPEG1_13, + Y4M_SAR_MPEG1_14, +}; + +static const char *mpeg2_aspect_ratio_definitions[] = { + "1:1 pixels", + "4:3 display", + "16:9 display", + "2.21:1 display" +}; + + +static const y4m_ratio_t mpeg2_aspect_ratios[] = { + Y4M_DAR_MPEG2_1, + Y4M_DAR_MPEG2_2, + Y4M_DAR_MPEG2_3, + Y4M_DAR_MPEG2_4 +}; + +static const char **aspect_ratio_definitions[2] = { + mpeg1_aspect_ratio_definitions, + mpeg2_aspect_ratio_definitions +}; + +static const y4m_ratio_t *mpeg_aspect_ratios[2] = { + mpeg1_aspect_ratios, + mpeg2_aspect_ratios +}; + +const mpeg_aspect_code_t mpeg_num_aspect_ratios[2] = { + sizeof (mpeg1_aspect_ratios) / sizeof (mpeg1_aspect_ratios[0]), + sizeof (mpeg2_aspect_ratios) / sizeof (mpeg2_aspect_ratios[0]) +}; + +/* + * Convert MPEG frame-rate code to corresponding frame-rate + */ + +y4m_ratio_t +mpeg_framerate (mpeg_framerate_code_t code) +{ + if (code == 0 || code > mpeg_num_framerates) + return y4m_fps_UNKNOWN; + else + return mpeg_framerates[code]; +} + +/* + * Look-up MPEG frame rate code for a (exact) frame rate. + */ + + +mpeg_framerate_code_t +mpeg_framerate_code (y4m_ratio_t framerate) +{ + mpeg_framerate_code_t i; + + y4m_ratio_reduce (&framerate); + for (i = 1; i < mpeg_num_framerates; ++i) { + if (Y4M_RATIO_EQL (framerate, mpeg_framerates[i])) + return i; + } + return 0; +} + + +/* small enough to distinguish 1/1000 from 1/1001 */ +#define MPEG_FPS_TOLERANCE 0.0001 + + +y4m_ratio_t +mpeg_conform_framerate (double fps) +{ + mpeg_framerate_code_t i; + y4m_ratio_t result; + + /* try to match it to a standard frame rate */ + for (i = 1; i < mpeg_num_framerates; i++) { + double deviation = 1.0 - (Y4M_RATIO_DBL (mpeg_framerates[i]) / fps); + + if ((deviation > -MPEG_FPS_TOLERANCE) && (deviation < +MPEG_FPS_TOLERANCE)) + return mpeg_framerates[i]; + } + /* no luck? just turn it into a ratio (6 decimal place accuracy) */ + result.n = (int) ((fps * 1000000.0) + 0.5); + result.d = 1000000; + y4m_ratio_reduce (&result); + return result; +} + + + +/* + * Convert MPEG aspect-ratio code to corresponding aspect-ratio + */ + +y4m_ratio_t +mpeg_aspect_ratio (int mpeg_version, mpeg_aspect_code_t code) +{ + y4m_ratio_t ratio; + + if (mpeg_version < 1 || mpeg_version > 2) + return y4m_sar_UNKNOWN; + if (code == 0 || code > mpeg_num_aspect_ratios[mpeg_version - 1]) + return y4m_sar_UNKNOWN; + else { + ratio = mpeg_aspect_ratios[mpeg_version - 1][code - 1]; + y4m_ratio_reduce (&ratio); + return ratio; + } +} + +/* + * Look-up corresponding MPEG aspect ratio code given an exact aspect ratio. + * + * WARNING: The semantics of aspect ratio coding *changed* between + * MPEG1 and MPEG2. In MPEG1 it is the *pixel* aspect ratio. In + * MPEG2 it is the (far more sensible) aspect ratio of the eventual + * display. + * + */ + +mpeg_aspect_code_t +mpeg_frame_aspect_code (int mpeg_version, y4m_ratio_t aspect_ratio) +{ + mpeg_aspect_code_t i; + y4m_ratio_t red_ratio = aspect_ratio; + + y4m_ratio_reduce (&red_ratio); + if (mpeg_version < 1 || mpeg_version > 2) + return 0; + for (i = 1; i < mpeg_num_aspect_ratios[mpeg_version - 1]; ++i) { + y4m_ratio_t red_entry = mpeg_aspect_ratios[mpeg_version - 1][i - 1]; + + y4m_ratio_reduce (&red_entry); + if (Y4M_RATIO_EQL (red_entry, red_ratio)) + return i; + } + + return 0; + +} + + + +/* + * Guess the correct MPEG aspect ratio code, + * given the true sample aspect ratio and frame size of a video stream + * (and the MPEG version, 1 or 2). + * + * Returns 0 if it has no good guess. + * + */ + + +/* this is big enough to accommodate the difference between 720 and 704 */ +#define GUESS_ASPECT_TOLERANCE 0.03 + +mpeg_aspect_code_t +mpeg_guess_mpeg_aspect_code (int mpeg_version, y4m_ratio_t sampleaspect, + int frame_width, int frame_height) +{ + if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_UNKNOWN)) { + return 0; + } + switch (mpeg_version) { + case 1: + if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_SQUARE)) { + return 1; + } else if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_NTSC_CCIR601)) { + return 12; + } else if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_NTSC_16_9)) { + return 6; + } else if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_PAL_CCIR601)) { + return 8; + } else if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_PAL_16_9)) { + return 3; + } + return 0; + break; + case 2: + if (Y4M_RATIO_EQL (sampleaspect, y4m_sar_SQUARE)) { + return 1; /* '1' means square *pixels* in MPEG-2; go figure. */ + } else { + unsigned int i; + double true_far; /* true frame aspect ratio */ + + true_far = + (double) (sampleaspect.n * frame_width) / (double) (sampleaspect.d * frame_height); + /* start at '2'... */ + for (i = 2; i < mpeg_num_aspect_ratios[mpeg_version - 1]; i++) { + double ratio = true_far / Y4M_RATIO_DBL (mpeg_aspect_ratios[mpeg_version - 1][i - 1]); + + if ((ratio > (1.0 - GUESS_ASPECT_TOLERANCE)) && (ratio < (1.0 + GUESS_ASPECT_TOLERANCE))) + return i; + } + return 0; + } + break; + default: + return 0; + break; + } +} + + + + +/* + * Guess the true sample aspect ratio of a video stream, + * given the MPEG aspect ratio code and the actual frame size + * (and the MPEG version, 1 or 2). + * + * Returns y4m_sar_UNKNOWN if it has no good guess. + * + */ +y4m_ratio_t +mpeg_guess_sample_aspect_ratio (int mpeg_version, + mpeg_aspect_code_t code, int frame_width, int frame_height) +{ + switch (mpeg_version) { + case 1: + /* MPEG-1 codes turn into SAR's, just not quite the right ones. + For the common/known values, we provide the ratio used in practice, + otherwise say we don't know. */ + switch (code) { + case 1: + return y4m_sar_SQUARE; + break; + case 3: + return y4m_sar_PAL_16_9; + break; + case 6: + return y4m_sar_NTSC_16_9; + break; + case 8: + return y4m_sar_PAL_CCIR601; + break; + case 12: + return y4m_sar_NTSC_CCIR601; + break; + default: + return y4m_sar_UNKNOWN; + break; + } + break; + case 2: + /* MPEG-2 codes turn into Frame Aspect Ratios, though not exactly the + FAR's used in practice. For common/standard frame sizes, we provide + the original SAR; otherwise, we say we don't know. */ + if (code == 1) { + return y4m_sar_SQUARE; /* '1' means square *pixels* in MPEG-2 */ + } else if ((code >= 2) && (code <= 4)) { + return y4m_guess_sar (frame_width, frame_height, mpeg2_aspect_ratios[code - 1]); + } else { + return y4m_sar_UNKNOWN; + } + break; + default: + return y4m_sar_UNKNOWN; + break; + } +} + + + + + +/* + * Look-up MPEG explanatory definition string for frame rate code + * + */ + + +const char * +mpeg_framerate_code_definition (mpeg_framerate_code_t code) +{ + if (code == 0 || code >= mpeg_num_framerates) + return "UNDEFINED: illegal/reserved frame-rate ratio code"; + + return framerate_definitions[code]; +} + +/* + * Look-up MPEG explanatory definition string aspect ratio code for an + * aspect ratio code + * + */ + +const char * +mpeg_aspect_code_definition (int mpeg_version, mpeg_aspect_code_t code) +{ + if (mpeg_version < 1 || mpeg_version > 2) + return "UNDEFINED: illegal MPEG version"; + + if (code < 1 || code > mpeg_num_aspect_ratios[mpeg_version - 1]) + return "UNDEFINED: illegal aspect ratio code"; + + return aspect_ratio_definitions[mpeg_version - 1][code - 1]; +} + + +/* + * Look-up explanatory definition of interlace field order code + * + */ + +const char * +mpeg_interlace_code_definition (int yuv4m_interlace_code) +{ + const char *def; + + switch (yuv4m_interlace_code) { + case Y4M_UNKNOWN: + def = "unknown"; + break; + case Y4M_ILACE_NONE: + def = "none/progressive"; + break; + case Y4M_ILACE_TOP_FIRST: + def = "top-field-first"; + break; + case Y4M_ILACE_BOTTOM_FIRST: + def = "bottom-field-first"; + break; + default: + def = "UNDEFINED: illegal video interlacing type-code!"; + break; + } + return def; +} + + +/* + * Local variables: + * c-file-style: "stroustrup" + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ |