Commit 4b925a1c authored by Loren Merritt's avatar Loren Merritt

expose the rest of the VUI flags.

patch by Christian Heine.



git-svn-id: svn://svn.videolan.org/x264/trunk@316 df754926-b1dd-0310-bc7b-ec298dee348c
parent aebad793
......@@ -53,6 +53,13 @@ void x264_param_default( x264_param_t *param )
param->i_height = 0;
param->vui.i_sar_width = 0;
param->vui.i_sar_height= 0;
param->vui.i_overscan = 0; /* undef */
param->vui.i_vidformat = 5; /* undef */
param->vui.b_fullrange = 0; /* off */
param->vui.i_colorprim = 2; /* undef */
param->vui.i_transfer = 2; /* undef */
param->vui.i_colmatrix = 2; /* undef */
param->vui.i_chroma_loc= 0; /* left center */
param->i_fps_num = 25;
param->i_fps_den = 1;
param->i_level_idc = 40; /* level 4.0 is sufficient for 720x576 with
......
......@@ -94,6 +94,21 @@ typedef struct
int b_aspect_ratio_info_present;
int i_sar_width;
int i_sar_height;
int b_overscan_info_present;
int b_overscan_info;
int b_signal_type_present;
int i_vidformat;
int b_fullrange;
int b_color_description_present;
int i_colorprim;
int i_transfer;
int i_colmatrix;
int b_chroma_loc_info_present;
int i_chroma_loc_top;
int i_chroma_loc_bottom;
int b_timing_info_present;
int i_num_units_in_tick;
......
Video Usability Information (VUI) Guide
by Christian Heine ( sennindemokrit at gmx dot net )
1. Sample Aspect Ratio
-----------------------
* What is it?
The Sample Aspect Ratio (SAR) (sometimes called Pixel Aspect Ratio or just
Pel Aspect Ratio) is defined as the ratio of the width of the sample to the
height of the sample. While pixels on a computer monitor generally are
"square" meaning that their SAR is 1:1, digitized video usually has rather
odd SARs. Playback of material with a particular SAR on a system with
a different SAR will result in a stretched/squashed image. A correction is
necessary that relies on the knowledge of both SARs.
* How do I use it?
You can derive the SAR of an image from the width, height and the
display aspect ratio (DAR) of the image as follows:
SAR_x DAR_x * height
----- = --------------
SAR_y DAR_y * width
for example:
width x height = 704x576, DAR = 4:3 ==> SAR = 2304:2112 or 12:11
Please note that if your material is a digitized analog signal, you should
not use this equation to calculate the SAR. Refer to the manual of your
digitizing equipment or this link instead.
A Quick Guide to Digital Video Resolution and Aspect Ratio Conversions
http://www.iki.fi/znark/video/conversion/
* Should I use this option?
In one word: yes. Most decoders/ media players nowadays support automatic
correction of aspect ratios, and there are just few exceptions. You should
even use it, if the SAR of your material is 1:1, as the default of x264 is
"SAR not defined".
2. Overscan
------------
* What is it?
The term overscan generally refers to all regions of an image that do
not contain information but are added to achieve a certain resolution or
aspect ratio. A "letterboxed" image therefore has overscan at the top and
the bottom. This is not the overscan this option refers to. Neither refers
it to the overscan that is added as part of the process of digitizing an
analog signal. Instead it refers to the "overscan" process on a display
that shows only a part of the image. What that part is depends on the
display.
* How do I use this option?
As I'm not sure about what part of the image is shown when the display uses
an overscan process, I can't provide you with rules or examples. The safe
assumption would be "overscan=show" as this always shows the whole image.
Use "overscan=crop" only if you are sure about the consequences. You may
also use the default value ("undefined").
* Should I use this option?
Only if you know exactly what you are doing. Don't use it on video streams
that have general overscan. Instead try to to crop the borders before
encoding and benefit from the higher bitrate/ image quality.
Furthermore the H264 specification says that the setting "overscan=show"
must be respected, but "overscan=crop" may be ignored. In fact most
playback equipment ignores this setting and shows the whole image.
3. Video Format
----------------
* What is it?
A purely informative setting, that explains what the type of your analog
video was, before you digitized it.
* How do I use this option?
Just set it to the desired value. ( e.g. NTSC, PAL )
If you transcode from MPEG2, you may find the value for this option in the
m2v bitstream. (see ITU-T Rec. H262 / ISO/IEC 13818-2 for details)
* Should I use this option?
That is entirely up to you. I have no idea how this information would ever
be relevant. I consider it to be informative only.
4. Full Range
--------------
* What is it?
Another relic from digitizing analog video. When digitizing analog video
the digital representation of the luma and chroma levels is limited to lie
within 16..235 and 16..240 respectively. Playback equipment usually assumes
all digitized samples to be within this range. However most DVDs use the
full range of 0..255 for luma and chroma samples, possibly resulting in an
oversaturation when played back on that equipment. To avoid this a range
correction is needed.
* How do I use this option?
If your source material is a digitized analog video/TV broadcast it is
quite possible that it is range limited. If you can make sure that it is
range limited you can safely set full range to off. If you are not sure
or want to make sure that your material is played back without
oversaturation, set if to on. Please note that the default for this option
in x264 is off, which is not a safe assumption.
* Should I use this option?
Yes, but there are few decoders/ media players that distinguish
between the two options.
5. Color Primaries, Transfer Characteristics, Matrix Coefficients
-------------------------------------------------------------------
* What is it?
A videophile setting. The average users won't ever need it.
Not all monitor models show all colors the same way. When comparing the
same image on two different monitor models you might find that one of them
"looks more blue", while the other "looks more green". Bottom line is, each
monitor model has a different color profile, which can be used to correct
colors in a way, that images look almost the same on all monitors. The same
goes for printers and film/ video digitizing equipment. If the color
profile of the digitizing equipment is known, it is possible to correct the
colors and gamma of the decoded h264 stream in a way that the video stream
looks the same, regardless of the digitizing equipment used.
* How do I use these options?
If you are able to find out which characteristics your digitizing equipment
uses, (see the equipment documentation or make reference measurements)
then find the most suitable characteristics in the list of available
characteristics (see H264 Annex E) and pass it to x264. Otherwise leave it
to the default (unspecified).
If you transcode from MPEG2, you may find the values for these options in
the m2v bitstream. (see ITU-T Rec. H262 / ISO/IEC 13818-2 for details)
* Should I use these options?
Only if you know exactly what you are doing. The default setting is better
than a wrong one. Use of this option is not a bad idea though.
Unfortunately I don't know any decoder/ media player that ever even
attempted color/gamma/color matrix correction.
6. Chroma Sample Location
--------------------------
* What is it?
A videophile setting. The average user won't ever notice a difference.
Due to a weakness of the eye, it is often economic to reduce the number of
chroma samples in a process called subsampling. In particular x264 uses
only one chroma sample of each chroma channel every block of 2x2 luma
samples. There are a number of possibilities on how this subsampling is
done, each resulting in another relative location of the chroma sample
towards the luma samples. The Chroma Sample Location matters when the
subsampling process is reversed, e.g. the number of chroma samples is
increased. This is most likely to happen at color space conversions. If it
is not done correctly the chroma values may appear shifted compared to the
luma samples by at most 1 pixel, or strangely blurred.
* How do I use this option?
Because x264 does no subsampling, since it only accepts already subsampled
input frames, you have to determine the method yourself.
If you transcode from MPEG1 with proper subsampled 4:2:0, and don't do any
color space conversion, you should set this option to 1.
If you transcode from MPEG2 with proper subsampled 4:2:0, and don't do any
color space conversion, you should set this option to 0.
If you transcode from MPEG4 with proper subsampled 4:2:0, and don't do any
color space conversion, you should set this option to 0.
If you do the color space conversion yourself this isn't that easy. If the
filter kernel of the subsampling is ( 0.5, 0.5 ) in one direction then the
chroma sample location in that direction is between the two luma samples.
If your filter kernel is ( 0.25, 0.5, 0.25 ) in one direction then the
chroma sample location in that direction is equal to one of the luma
samples. H264 Annex E contains images that tell you how to "transform" your
Chroma Sample Location into a value of 0 to 5 that you can pass to x264.
* Should I use this option?
Unless you are a perfectionist, don't bother. Media players ignore this
setting, and favor their own (fixed) assumed Chroma Sample Location.
......@@ -157,7 +157,45 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
sps->vui.i_sar_height= param->vui.i_sar_height;
}
sps->b_vui |= sps->vui.b_aspect_ratio_info_present;
sps->vui.b_overscan_info_present = ( param->vui.i_overscan ? 1 : 0 );
if( sps->vui.b_overscan_info_present )
sps->vui.b_overscan_info = ( param->vui.i_overscan == 2 ? 1 : 0 );
sps->b_vui |= sps->vui.b_overscan_info_present;
sps->vui.b_signal_type_present = 0;
sps->vui.i_vidformat = ( param->vui.i_vidformat <= 5 ? param->vui.i_vidformat : 5 );
sps->vui.b_fullrange = ( param->vui.b_fullrange ? 1 : 0 );
sps->vui.b_color_description_present = 0;
sps->vui.i_colorprim = ( param->vui.i_colorprim <= 9 ? param->vui.i_colorprim : 2 );
sps->vui.i_transfer = ( param->vui.i_transfer <= 11 ? param->vui.i_transfer : 2 );
sps->vui.i_colmatrix = ( param->vui.i_colmatrix <= 9 ? param->vui.i_colmatrix : 2 );
if( sps->vui.i_colorprim != 2 ||
sps->vui.i_transfer != 2 ||
sps->vui.i_colmatrix != 2 )
{
sps->vui.b_color_description_present = 1;
}
if( sps->vui.i_vidformat != 5 ||
sps->vui.b_fullrange ||
sps->vui.b_color_description_present )
{
sps->vui.b_signal_type_present = 1;
}
sps->b_vui |= sps->vui.b_signal_type_present;
/* FIXME: not sufficient for interlaced video */
sps->vui.b_chroma_loc_info_present = ( param->vui.i_chroma_loc ? 1 : 0 );
if( sps->vui.b_chroma_loc_info_present )
{
sps->vui.i_chroma_loc_top = param->vui.i_chroma_loc;
sps->vui.i_chroma_loc_bottom = param->vui.i_chroma_loc;
}
sps->b_vui |= sps->vui.b_chroma_loc_info_present;
sps->vui.b_timing_info_present = 0;
if( param->i_fps_num > 0 && param->i_fps_den > 0)
{
sps->vui.b_timing_info_present = 1;
......@@ -276,15 +314,30 @@ void x264_sps_write( bs_t *s, x264_sps_t *sps )
}
}
bs_write1( s, 0 ); /* overscan_info_present_flag */
bs_write1( s, sps->vui.b_overscan_info_present );
if( sps->vui.b_overscan_info_present )
bs_write1( s, sps->vui.b_overscan_info );
bs_write1( s, 0 ); /* video_signal_type_present_flag */
#if 0
bs_write( s, 3, 5 ); /* unspecified video format */
bs_write1( s, 1 ); /* video full range flag */
bs_write1( s, 0 ); /* colour description present flag */
#endif
bs_write1( s, 0 ); /* chroma_loc_info_present_flag */
bs_write1( s, sps->vui.b_signal_type_present );
if( sps->vui.b_signal_type_present )
{
bs_write( s, 3, sps->vui.i_vidformat );
bs_write1( s, sps->vui.b_fullrange );
bs_write1( s, sps->vui.b_color_description_present );
if( sps->vui.b_color_description_present )
{
bs_write( s, 8, sps->vui.i_colorprim );
bs_write( s, 8, sps->vui.i_transfer );
bs_write( s, 8, sps->vui.i_colmatrix );
}
}
bs_write1( s, sps->vui.b_chroma_loc_info_present );
if( sps->vui.b_chroma_loc_info_present )
{
bs_write_ue( s, sps->vui.i_chroma_loc_top );
bs_write_ue( s, sps->vui.i_chroma_loc_bottom );
}
bs_write1( s, sps->vui.b_timing_info_present );
if( sps->vui.b_timing_info_present )
......
......@@ -154,6 +154,19 @@ int main( int argc, char **argv )
return Encode( &param, &opt );
}
static char const *overscan_str[] = { "undef", "show", "crop", NULL };
static char const *vidformat_str[] = { "component", "pal", "ntsc", "secam", "mac", "undef", NULL };
static char const *fullrange_str[] = { "off", "on", NULL };
static char const *colorprim_str[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", NULL };
static char const *transfer_str[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "linear", "log100", "log316", NULL };
static char const *colmatrix_str[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", NULL };
static char const *strtable_lookup( char const * table[], int index )
{
int i = 0; while( table[i] ) i++;
return ( ( index >= 0 && index < i ) ? table[ index ] : "???" );
}
/*****************************************************************************
* Help:
*****************************************************************************/
......@@ -256,10 +269,31 @@ static void Help( x264_param_t *defaults )
" --cqm4iy, --cqm4ic, --cqm4py, --cqm4pc\n"
" Set individual quant matrices\n"
"\n"
"Video Usability Info (Annex E):\n"
"The VUI settings are not used by the encoder but are merely suggestions to\n"
"the playback equipment. See doc/vui.txt for details. Use at your own risk.\n"
"\n"
" --sar width:height Specify Sample Aspect Ratio\n"
" --overscan <string> Specify crop overscan setting [\"%s\"]\n"
" - undef, show, crop\n"
" --videoformat <string> Specify video format [\"%s\"]\n"
" - component, pal, ntsc, secam, mac, undef\n"
" --fullrange <string> Specify full range samples setting [\"%s\"]\n"
" - off, on\n"
" --colorprim <string> Specify color primaries [\"%s\"]\n"
" - undef, bt709, bt470m, bt470bg\n"
" smpte170m, smpte240m, film\n"
" --transfer <string> Specify transfer characteristics [\"%s\"]\n"
" - undef, bt709, bt470m, bt470bg, linear,\n"
" log100, log316, smpte170m, smpte240m\n"
" --colormatrix <string> Specify color matrix setting [\"%s\"]\n"
" - undef, bt709, fcc, bt470bg\n"
" smpte170m, smpte240m, GBR, YCgCo\n"
" --chromaloc <integer> Specify chroma sample location (0 to 5) [%d]\n"
"\n"
"Input/Output:\n"
"\n"
" --level <integer> Specify level (as defined by Annex A)\n"
" --sar width:height Specify Sample Aspect Ratio\n"
" --fps <float|rational> Specify framerate\n"
" --seek <integer> First frame to encode\n"
" --frames <integer> Maximum number of frames to encode\n"
......@@ -314,10 +348,29 @@ static void Help( x264_param_t *defaults )
: defaults->analyse.i_me_method==X264_ME_UMH ? "umh"
: defaults->analyse.i_me_method==X264_ME_ESA ? "esa" : NULL,
defaults->analyse.i_me_range,
defaults->analyse.i_subpel_refine
defaults->analyse.i_subpel_refine,
strtable_lookup( overscan_str, defaults->vui.i_overscan ),
strtable_lookup( vidformat_str, defaults->vui.i_vidformat ),
strtable_lookup( fullrange_str, defaults->vui.b_fullrange ),
strtable_lookup( colorprim_str, defaults->vui.i_colorprim ),
strtable_lookup( transfer_str, defaults->vui.i_transfer ),
strtable_lookup( colmatrix_str, defaults->vui.i_colmatrix ),
defaults->vui.i_chroma_loc
);
}
static int parse_enum( const char *arg, const char **names, int *dst )
{
int i;
for( i = 0; names[i]; i++ )
if( !strcmp( arg, names[i] ) )
{
*dst = i;
return 0;
}
return -1;
}
static int parse_cqm( const char *str, uint8_t *cqm, int length )
{
int i = 0;
......@@ -409,6 +462,14 @@ static int Parse( int argc, char **argv,
#define OPT_CQM8I 303
#define OPT_CQM8P 304
#define OPT_CQMFILE 305
#define OPT_SAR 306
#define OPT_OVERSCAN 307
#define OPT_VIDFORMAT 308
#define OPT_FULLRANGE 309
#define OPT_COLOURPRIM 310
#define OPT_TRANSFER 311
#define OPT_COLOURMATRIX 312
#define OPT_CHROMALOC 313
static struct option long_options[] =
{
......@@ -430,7 +491,7 @@ static int Parse( int argc, char **argv,
{ "qpstep", required_argument, NULL, OPT_QPSTEP },
{ "ref", required_argument, NULL, 'r' },
{ "no-asm", no_argument, NULL, 'C' },
{ "sar", required_argument, NULL, 's' },
{ "sar", required_argument, NULL, OPT_SAR },
{ "fps", required_argument, NULL, OPT_FPS },
{ "frames", required_argument, NULL, OPT_FRAMES },
{ "seek", required_argument, NULL, OPT_SEEK },
......@@ -477,6 +538,13 @@ static int Parse( int argc, char **argv,
{ "cqm8", required_argument, NULL, OPT_CQM8 },
{ "cqm8i", required_argument, NULL, OPT_CQM8I },
{ "cqm8p", required_argument, NULL, OPT_CQM8P },
{ "overscan", required_argument, NULL, OPT_OVERSCAN },
{ "videoformat", required_argument, NULL, OPT_VIDFORMAT },
{ "fullrange", required_argument, NULL, OPT_FULLRANGE },
{ "colorprim", required_argument, NULL, OPT_COLOURPRIM },
{ "transfer", required_argument, NULL, OPT_TRANSFER },
{ "colormatrix", required_argument, NULL, OPT_COLOURMATRIX },
{ "chromaloc", required_argument, NULL, OPT_CHROMALOC },
{0, 0, 0, 0}
};
......@@ -597,7 +665,7 @@ static int Parse( int argc, char **argv,
return -1;
}
break;
case 's':
case OPT_SAR:
{
char *p = strchr( optarg, ':' );
if( p )
......@@ -813,6 +881,28 @@ static int Parse( int argc, char **argv,
param->i_cqm_preset = X264_CQM_CUSTOM;
b_error |= parse_cqm( optarg, param->cqm_8py, 64 );
break;
case OPT_OVERSCAN:
b_error |= parse_enum( optarg, overscan_str, &param->vui.i_overscan );
break;
case OPT_VIDFORMAT:
b_error |= parse_enum( optarg, vidformat_str, &param->vui.i_vidformat );
break;
case OPT_FULLRANGE:
b_error |= parse_enum( optarg, fullrange_str, &param->vui.b_fullrange );
break;
case OPT_COLOURPRIM:
b_error |= parse_enum( optarg, colorprim_str, &param->vui.i_colorprim );
break;
case OPT_TRANSFER:
b_error |= parse_enum( optarg, transfer_str, &param->vui.i_transfer );
break;
case OPT_COLOURMATRIX:
b_error |= parse_enum( optarg, colmatrix_str, &param->vui.i_colmatrix );
break;
case OPT_CHROMALOC:
param->vui.i_chroma_loc = atoi( optarg );
b_error = ( param->vui.i_chroma_loc < 0 || param->vui.i_chroma_loc > 5 );
break;
default:
fprintf( stderr, "unknown option (%c)\n", optopt );
return -1;
......@@ -820,7 +910,7 @@ static int Parse( int argc, char **argv,
if( b_error )
{
fprintf( stderr, "bad argument (%s)\n", optarg );
fprintf( stderr, "bad argument: %s %s\n", argv[optind-2], optarg );
return -1;
}
}
......
......@@ -35,7 +35,7 @@
#include <stdarg.h>
#define X264_BUILD 34
#define X264_BUILD 35
/* x264_t:
* opaque handler for decoder and encoder */
......@@ -130,6 +130,16 @@ typedef struct
/* they will be reduced to be 0 < x <= 65535 and prime */
int i_sar_height;
int i_sar_width;
int i_overscan; /* 0=undef, 1=no overscan, 2=overscan */
/* see h264 annex E for the values of the following */
int i_vidformat;
int b_fullrange;
int i_colorprim;
int i_transfer;
int i_colmatrix;
int i_chroma_loc; /* both top & bottom */
} vui;
int i_fps_num;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment