Commit 1d18f0e0 authored by Kieran Kunhya's avatar Kieran Kunhya Committed by Henrik Gramner

Add Sony XAVC, a flavour of AVC-Intra

parent bc136ec6
......@@ -429,6 +429,8 @@ static void param_default( x264_param_t *param )
param->i_opencl_device = 0;
param->opencl_device_id = NULL;
param->psz_clbin_file = NULL;
param->i_avcintra_class = 0;
param->i_avcintra_flavor = X264_AVCINTRA_FLAVOR_PANASONIC;
}
void x264_param_default( x264_param_t *param )
......@@ -955,6 +957,8 @@ static int param_parse( x264_param_t *p, const char *name, const char *value )
p->b_bluray_compat = atobool(value);
OPT("avcintra-class")
p->i_avcintra_class = atoi(value);
OPT("avcintra-flavor")
b_error |= parse_enum( value, x264_avcintra_flavor_names, &p->i_avcintra_flavor );
OPT("sar")
{
b_error = ( 2 != sscanf( value, "%d:%d", &p->vui.i_sar_width, &p->vui.i_sar_height ) &&
......
......@@ -94,7 +94,7 @@ int x264_cqm_init( x264_t *h )
int start = w == 8 ? 4 : 0;\
int j;\
for( j = 0; j < i; j++ )\
if( !memcmp( h->pps->scaling_list[i+start], h->pps->scaling_list[j+start], size*sizeof(uint8_t) ) )\
if( !memcmp( h->sps->scaling_list[i+start], h->sps->scaling_list[j+start], size*sizeof(uint8_t) ) )\
break;\
if( j < i )\
{\
......@@ -110,7 +110,7 @@ int x264_cqm_init( x264_t *h )
}\
for( j = 0; j < i; j++ )\
if( deadzone[j] == deadzone[i] &&\
!memcmp( h->pps->scaling_list[i+start], h->pps->scaling_list[j+start], size*sizeof(uint8_t) ) )\
!memcmp( h->sps->scaling_list[i+start], h->sps->scaling_list[j+start], size*sizeof(uint8_t) ) )\
break;\
if( j < i )\
{\
......@@ -148,14 +148,14 @@ int x264_cqm_init( x264_t *h )
for( int i_list = 0; i_list < 4; i_list++ )
for( int i = 0; i < 16; i++ )
{
h->dequant4_mf[i_list][q][i] = def_dequant4[q][i] * h->pps->scaling_list[i_list][i];
quant4_mf[i_list][q][i] = DIV(def_quant4[q][i] * 16, h->pps->scaling_list[i_list][i]);
h->dequant4_mf[i_list][q][i] = def_dequant4[q][i] * h->sps->scaling_list[i_list][i];
quant4_mf[i_list][q][i] = DIV(def_quant4[q][i] * 16, h->sps->scaling_list[i_list][i]);
}
for( int i_list = 0; i_list < num_8x8_lists; i_list++ )
for( int i = 0; i < 64; i++ )
{
h->dequant8_mf[i_list][q][i] = def_dequant8[q][i] * h->pps->scaling_list[4+i_list][i];
quant8_mf[i_list][q][i] = DIV(def_quant8[q][i] * 16, h->pps->scaling_list[4+i_list][i]);
h->dequant8_mf[i_list][q][i] = def_dequant8[q][i] * h->sps->scaling_list[4+i_list][i];
quant8_mf[i_list][q][i] = DIV(def_quant8[q][i] * 16, h->sps->scaling_list[4+i_list][i]);
}
}
for( int q = 0; q <= QP_MAX_SPEC; q++ )
......
......@@ -140,6 +140,10 @@ typedef struct
int b_qpprime_y_zero_transform_bypass;
int i_chroma_format_idc;
int b_avcintra;
int i_cqm_preset;
const uint8_t *scaling_list[8]; /* could be 12, but we don't allow separate Cb/Cr lists */
} x264_sps_t;
typedef struct
......@@ -169,9 +173,6 @@ typedef struct
int b_transform_8x8_mode;
int i_cqm_preset;
const uint8_t *scaling_list[8]; /* could be 12, but we don't allow separate Cb/Cr lists */
} x264_pps_t;
#define x264_cqm_init x264_template(cqm_init)
......
......@@ -817,21 +817,34 @@ static int validate_parameters( x264_t *h, int b_open )
memcpy( h->param.cqm_4ic, avcintra_lut[type][res][i].cqm_4ic, sizeof(h->param.cqm_4ic) );
memcpy( h->param.cqm_8iy, avcintra_lut[type][res][i].cqm_8iy, sizeof(h->param.cqm_8iy) );
/* Need exactly 10 slices of equal MB count... why? $deity knows... */
h->param.i_slice_max_mbs = ((h->param.i_width + 15) / 16) * ((h->param.i_height + 15) / 16) / 10;
h->param.i_slice_max_size = 0;
/* The slice structure only allows a maximum of 2 threads for 1080i/p
* and 1 or 5 threads for 720p */
if( h->param.b_sliced_threads )
/* Sony XAVC flavor much more simple */
if( h->param.i_avcintra_flavor == X264_AVCINTRA_FLAVOR_SONY )
{
if( res )
h->param.i_threads = X264_MIN( 2, h->param.i_threads );
else
h->param.i_slice_count = 8;
/* Sony XAVC unlike AVC-Intra doesn't seem to have a QP floor */
}
else
{
/* Need exactly 10 slices of equal MB count... why? $deity knows... */
h->param.i_slice_max_mbs = ((h->param.i_width + 15) / 16) * ((h->param.i_height + 15) / 16) / 10;
h->param.i_slice_max_size = 0;
/* The slice structure only allows a maximum of 2 threads for 1080i/p
* and 1 or 5 threads for 720p */
if( h->param.b_sliced_threads )
{
h->param.i_threads = X264_MIN( 5, h->param.i_threads );
if( h->param.i_threads < 5 )
h->param.i_threads = 1;
if( res )
h->param.i_threads = X264_MIN( 2, h->param.i_threads );
else
{
h->param.i_threads = X264_MIN( 5, h->param.i_threads );
if( h->param.i_threads < 5 )
h->param.i_threads = 1;
}
}
/* Official encoder doesn't appear to go under 13
* and Avid cannot handle negative QPs */
h->param.rc.i_qp_min = X264_MAX( h->param.rc.i_qp_min, QP_BD_OFFSET + 1 );
}
if( type )
......@@ -841,10 +854,6 @@ static int validate_parameters( x264_t *h, int b_open )
h->param.vui.i_sar_width = 4;
h->param.vui.i_sar_height = 3;
}
/* Official encoder doesn't appear to go under 13
* and Avid cannot handle negative QPs */
h->param.rc.i_qp_min = X264_MAX( h->param.rc.i_qp_min, QP_BD_OFFSET + 1 );
}
h->param.rc.f_rf_constant = x264_clip3f( h->param.rc.f_rf_constant, -QP_BD_OFFSET, 51 );
......@@ -3582,7 +3591,13 @@ int x264_encoder_encode( x264_t *h,
if( nal_end( h ) )
return -1;
if( h->param.i_avcintra_class )
h->out.nal[h->out.i_nal-1].i_padding = 256 - h->out.nal[h->out.i_nal-1].i_payload - NALU_OVERHEAD;
{
int total_len = 256;
/* Sony XAVC uses an oversized PPS instead of SEI padding */
if( h->param.i_avcintra_flavor == X264_AVCINTRA_FLAVOR_SONY )
total_len += h->param.i_height == 1080 ? 18*512 : 10*512;
h->out.nal[h->out.i_nal-1].i_padding = total_len - h->out.nal[h->out.i_nal-1].i_payload - NALU_OVERHEAD;
}
overhead += h->out.nal[h->out.i_nal-1].i_payload + h->out.nal[h->out.i_nal-1].i_padding + NALU_OVERHEAD;
}
......@@ -3689,7 +3704,7 @@ int x264_encoder_encode( x264_t *h,
h->i_cpb_delay_pir_offset_next = h->fenc->i_cpb_delay;
/* Filler space: 10 or 18 SEIs' worth of space, depending on resolution */
if( h->param.i_avcintra_class )
if( h->param.i_avcintra_class && h->param.i_avcintra_flavor != X264_AVCINTRA_FLAVOR_SONY )
{
/* Write an empty filler NAL to mimic the AUD in the P2 format*/
nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE );
......
......@@ -40,15 +40,15 @@ static void transpose( uint8_t *buf, int w )
XCHG( uint8_t, buf[w*i+j], buf[w*j+i] );
}
static void scaling_list_write( bs_t *s, x264_pps_t *pps, int idx )
static void scaling_list_write( bs_t *s, x264_sps_t *sps, int idx )
{
const int len = idx<4 ? 16 : 64;
const uint8_t *zigzag = idx<4 ? x264_zigzag_scan4[0] : x264_zigzag_scan8[0];
const uint8_t *list = pps->scaling_list[idx];
const uint8_t *def_list = (idx==CQM_4IC) ? pps->scaling_list[CQM_4IY]
: (idx==CQM_4PC) ? pps->scaling_list[CQM_4PY]
: (idx==CQM_8IC+4) ? pps->scaling_list[CQM_8IY+4]
: (idx==CQM_8PC+4) ? pps->scaling_list[CQM_8PY+4]
const uint8_t *list = sps->scaling_list[idx];
const uint8_t *def_list = (idx==CQM_4IC) ? sps->scaling_list[CQM_4IY]
: (idx==CQM_4PC) ? sps->scaling_list[CQM_4PY]
: (idx==CQM_8IC+4) ? sps->scaling_list[CQM_8IY+4]
: (idx==CQM_8PC+4) ? sps->scaling_list[CQM_8PY+4]
: x264_cqm_jvt[idx];
if( !memcmp( list, def_list, len ) )
bs_write1( s, 0 ); // scaling_list_present_flag
......@@ -240,6 +240,44 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
sps->vui.i_log2_max_mv_length_horizontal =
sps->vui.i_log2_max_mv_length_vertical = (int)log2f( X264_MAX( 1, param->analyse.i_mv_range*4-1 ) ) + 1;
}
sps->b_avcintra = !!param->i_avcintra_class;
sps->i_cqm_preset = param->i_cqm_preset;
switch( sps->i_cqm_preset )
{
case X264_CQM_FLAT:
for( int i = 0; i < 8; i++ )
sps->scaling_list[i] = x264_cqm_flat16;
break;
case X264_CQM_JVT:
for( int i = 0; i < 8; i++ )
sps->scaling_list[i] = x264_cqm_jvt[i];
break;
case X264_CQM_CUSTOM:
/* match the transposed DCT & zigzag */
transpose( param->cqm_4iy, 4 );
transpose( param->cqm_4py, 4 );
transpose( param->cqm_4ic, 4 );
transpose( param->cqm_4pc, 4 );
transpose( param->cqm_8iy, 8 );
transpose( param->cqm_8py, 8 );
transpose( param->cqm_8ic, 8 );
transpose( param->cqm_8pc, 8 );
sps->scaling_list[CQM_4IY] = param->cqm_4iy;
sps->scaling_list[CQM_4PY] = param->cqm_4py;
sps->scaling_list[CQM_4IC] = param->cqm_4ic;
sps->scaling_list[CQM_4PC] = param->cqm_4pc;
sps->scaling_list[CQM_8IY+4] = param->cqm_8iy;
sps->scaling_list[CQM_8PY+4] = param->cqm_8py;
sps->scaling_list[CQM_8IC+4] = param->cqm_8ic;
sps->scaling_list[CQM_8PC+4] = param->cqm_8pc;
for( int i = 0; i < 8; i++ )
for( int j = 0; j < (i < 4 ? 16 : 64); j++ )
if( sps->scaling_list[i][j] == 0 )
sps->scaling_list[i] = x264_cqm_jvt[i];
break;
}
}
void x264_sps_init_reconfigurable( x264_sps_t *sps, x264_param_t *param )
......@@ -283,7 +321,26 @@ void x264_sps_write( bs_t *s, x264_sps_t *sps )
bs_write_ue( s, BIT_DEPTH-8 ); // bit_depth_luma_minus8
bs_write_ue( s, BIT_DEPTH-8 ); // bit_depth_chroma_minus8
bs_write1( s, sps->b_qpprime_y_zero_transform_bypass );
bs_write1( s, 0 ); // seq_scaling_matrix_present_flag
/* Exactly match the AVC-Intra bitstream */
bs_write1( s, sps->b_avcintra ); // seq_scaling_matrix_present_flag
if( sps->b_avcintra )
{
scaling_list_write( s, sps, CQM_4IY );
scaling_list_write( s, sps, CQM_4IC );
scaling_list_write( s, sps, CQM_4IC );
bs_write1( s, 0 ); // no inter
bs_write1( s, 0 ); // no inter
bs_write1( s, 0 ); // no inter
scaling_list_write( s, sps, CQM_8IY+4 );
bs_write1( s, 0 ); // no inter
if( sps->i_chroma_format_idc == CHROMA_444 )
{
scaling_list_write( s, sps, CQM_8IC+4 );
bs_write1( s, 0 ); // no inter
scaling_list_write( s, sps, CQM_8IC+4 );
bs_write1( s, 0 ); // no inter
}
}
}
bs_write_ue( s, sps->i_log2_max_frame_num - 4 );
......@@ -439,43 +496,6 @@ void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *
pps->b_redundant_pic_cnt = 0;
pps->b_transform_8x8_mode = param->analyse.b_transform_8x8 ? 1 : 0;
pps->i_cqm_preset = param->i_cqm_preset;
switch( pps->i_cqm_preset )
{
case X264_CQM_FLAT:
for( int i = 0; i < 8; i++ )
pps->scaling_list[i] = x264_cqm_flat16;
break;
case X264_CQM_JVT:
for( int i = 0; i < 8; i++ )
pps->scaling_list[i] = x264_cqm_jvt[i];
break;
case X264_CQM_CUSTOM:
/* match the transposed DCT & zigzag */
transpose( param->cqm_4iy, 4 );
transpose( param->cqm_4py, 4 );
transpose( param->cqm_4ic, 4 );
transpose( param->cqm_4pc, 4 );
transpose( param->cqm_8iy, 8 );
transpose( param->cqm_8py, 8 );
transpose( param->cqm_8ic, 8 );
transpose( param->cqm_8pc, 8 );
pps->scaling_list[CQM_4IY] = param->cqm_4iy;
pps->scaling_list[CQM_4PY] = param->cqm_4py;
pps->scaling_list[CQM_4IC] = param->cqm_4ic;
pps->scaling_list[CQM_4PC] = param->cqm_4pc;
pps->scaling_list[CQM_8IY+4] = param->cqm_8iy;
pps->scaling_list[CQM_8PY+4] = param->cqm_8py;
pps->scaling_list[CQM_8IC+4] = param->cqm_8ic;
pps->scaling_list[CQM_8PC+4] = param->cqm_8pc;
for( int i = 0; i < 8; i++ )
for( int j = 0; j < (i < 4 ? 16 : 64); j++ )
if( pps->scaling_list[i][j] == 0 )
pps->scaling_list[i] = x264_cqm_jvt[i];
break;
}
}
void x264_pps_write( bs_t *s, x264_sps_t *sps, x264_pps_t *pps )
......@@ -501,26 +521,27 @@ void x264_pps_write( bs_t *s, x264_sps_t *sps, x264_pps_t *pps )
bs_write1( s, pps->b_constrained_intra_pred );
bs_write1( s, pps->b_redundant_pic_cnt );
if( pps->b_transform_8x8_mode || pps->i_cqm_preset != X264_CQM_FLAT )
int b_scaling_list = !sps->b_avcintra && sps->i_cqm_preset != X264_CQM_FLAT;
if( pps->b_transform_8x8_mode || b_scaling_list )
{
bs_write1( s, pps->b_transform_8x8_mode );
bs_write1( s, (pps->i_cqm_preset != X264_CQM_FLAT) );
if( pps->i_cqm_preset != X264_CQM_FLAT )
bs_write1( s, b_scaling_list );
if( b_scaling_list )
{
scaling_list_write( s, pps, CQM_4IY );
scaling_list_write( s, pps, CQM_4IC );
scaling_list_write( s, sps, CQM_4IY );
scaling_list_write( s, sps, CQM_4IC );
bs_write1( s, 0 ); // Cr = Cb
scaling_list_write( s, pps, CQM_4PY );
scaling_list_write( s, pps, CQM_4PC );
scaling_list_write( s, sps, CQM_4PY );
scaling_list_write( s, sps, CQM_4PC );
bs_write1( s, 0 ); // Cr = Cb
if( pps->b_transform_8x8_mode )
{
scaling_list_write( s, pps, CQM_8IY+4 );
scaling_list_write( s, pps, CQM_8PY+4 );
scaling_list_write( s, sps, CQM_8IY+4 );
scaling_list_write( s, sps, CQM_8PY+4 );
if( sps->i_chroma_format_idc == CHROMA_444 )
{
scaling_list_write( s, pps, CQM_8IC+4 );
scaling_list_write( s, pps, CQM_8PC+4 );
scaling_list_write( s, sps, CQM_8IC+4 );
scaling_list_write( s, sps, CQM_8PC+4 );
bs_write1( s, 0 ); // Cr = Cb
bs_write1( s, 0 ); // Cr = Cb
}
......
......@@ -861,7 +861,7 @@ static int check_dct( int cpu_ref, int cpu_new )
h->param.analyse.i_luma_deadzone[1] = 0;
h->param.analyse.b_transform_8x8 = 1;
for( int i = 0; i < 6; i++ )
h->pps->scaling_list[i] = x264_cqm_flat16;
h->sps->scaling_list[i] = x264_cqm_flat16;
x264_cqm_init( h );
x264_quant_init( h, 0, &qf );
......@@ -2037,14 +2037,14 @@ static int check_quant( int cpu_ref, int cpu_new )
if( i_cqm == 0 )
{
for( int i = 0; i < 6; i++ )
h->pps->scaling_list[i] = x264_cqm_flat16;
h->param.i_cqm_preset = h->pps->i_cqm_preset = X264_CQM_FLAT;
h->sps->scaling_list[i] = x264_cqm_flat16;
h->param.i_cqm_preset = h->sps->i_cqm_preset = X264_CQM_FLAT;
}
else if( i_cqm == 1 )
{
for( int i = 0; i < 6; i++ )
h->pps->scaling_list[i] = x264_cqm_jvt[i];
h->param.i_cqm_preset = h->pps->i_cqm_preset = X264_CQM_JVT;
h->sps->scaling_list[i] = x264_cqm_jvt[i];
h->param.i_cqm_preset = h->sps->i_cqm_preset = X264_CQM_JVT;
}
else
{
......@@ -2056,8 +2056,8 @@ static int check_quant( int cpu_ref, int cpu_new )
for( int i = 0; i < 64; i++ )
cqm_buf[i] = 1;
for( int i = 0; i < 6; i++ )
h->pps->scaling_list[i] = cqm_buf;
h->param.i_cqm_preset = h->pps->i_cqm_preset = X264_CQM_CUSTOM;
h->sps->scaling_list[i] = cqm_buf;
h->param.i_cqm_preset = h->sps->i_cqm_preset = X264_CQM_CUSTOM;
}
h->param.rc.i_qp_min = 0;
......
......@@ -935,6 +935,8 @@ static void help( x264_param_t *defaults, int longhelp )
H1( " --bluray-compat Enable compatibility hacks for Blu-ray support\n" );
H1( " --avcintra-class <integer> Use compatibility hacks for AVC-Intra class\n"
" - 50, 100, 200\n" );
H1( " --avcintra-flavor <string> AVC-Intra flavor [\"%s\"]\n"
" - %s\n", x264_avcintra_flavor_names[0], stringify_names( buf, x264_avcintra_flavor_names ) );
H1( " --stitchable Don't optimize headers based on video content\n"
" Ensures ability to recombine a segmented encode\n" );
H1( "\n" );
......@@ -1038,6 +1040,7 @@ static struct option long_options[] =
{ "open-gop", no_argument, NULL, 0 },
{ "bluray-compat", no_argument, NULL, 0 },
{ "avcintra-class", required_argument, NULL, 0 },
{ "avcintra-flavor", required_argument, NULL, 0 },
{ "min-keyint", required_argument, NULL, 'i' },
{ "keyint", required_argument, NULL, 'I' },
{ "intra-refresh", no_argument, NULL, 0 },
......
......@@ -45,7 +45,7 @@ extern "C" {
#include "x264_config.h"
#define X264_BUILD 156
#define X264_BUILD 157
/* Application developers planning to link against a shared library version of
* libx264 from a Microsoft Visual Studio or similar development environment
......@@ -170,6 +170,7 @@ typedef struct x264_nal_t
#define X264_ANALYSE_PSUB16x16 0x0010 /* Analyse p16x8, p8x16 and p8x8 */
#define X264_ANALYSE_PSUB8x8 0x0020 /* Analyse p8x4, p4x8, p4x4 */
#define X264_ANALYSE_BSUB16x16 0x0100 /* Analyse b16x8, b8x16 and b8x8 */
#define X264_DIRECT_PRED_NONE 0
#define X264_DIRECT_PRED_SPATIAL 1
#define X264_DIRECT_PRED_TEMPORAL 2
......@@ -202,6 +203,10 @@ typedef struct x264_nal_t
#define X264_KEYINT_MIN_AUTO 0
#define X264_KEYINT_MAX_INFINITE (1<<30)
/* AVC-Intra flavors */
#define X264_AVCINTRA_FLAVOR_PANASONIC 0
#define X264_AVCINTRA_FLAVOR_SONY 1
static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 };
static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 };
static const char * const x264_b_pyramid_names[] = { "none", "strict", "normal", 0 };
......@@ -215,6 +220,7 @@ static const char * const x264_transfer_names[] = { "", "bt709", "undef", "", "b
static const char * const x264_colmatrix_names[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", "bt2020nc", "bt2020c",
"smpte2085", "chroma-derived-nc", "chroma-derived-c", "ICtCp", 0 };
static const char * const x264_nal_hrd_names[] = { "none", "vbr", "cbr", 0 };
static const char * const x264_avcintra_flavor_names[] = { "panasonic", "sony", 0 };
/* Colorspace type */
#define X264_CSP_MASK 0x00ff /* */
......@@ -338,6 +344,7 @@ typedef struct x264_param_t
int b_open_gop;
int b_bluray_compat;
int i_avcintra_class;
int i_avcintra_flavor;
int b_deblocking_filter;
int i_deblocking_filter_alphac0; /* [-6, 6] -6 light filter, 6 strong */
......
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