Commit 9b94896b authored by Kieran Kunhya's avatar Kieran Kunhya Committed by Fiona Glaser

AVC-Intra support

This format has been reverse engineered and x264's output has almost exactly
the same bitstream as Panasonic cameras and encoders produce. It therefore does
not comply with SMPTE RP2027 since Panasonic themselves do not comply with
their own specification. It has been tested in Avid, Premiere, Edius and
Quantel.

Parts of this patch were written by Fiona Glaser and some reverse
engineering was done by Joseph Artsimovich.
parent fa1e2b74
......@@ -671,6 +671,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
}
OPT("bluray-compat")
p->b_bluray_compat = atobool(value);
OPT("avcintra-compat")
p->b_avcintra_compat = atobool(value);
OPT("sar")
{
b_error = ( 2 != sscanf( value, "%d:%d", &p->vui.i_sar_width, &p->vui.i_sar_height ) &&
......
......@@ -109,6 +109,7 @@ do {\
#define NALU_OVERHEAD 5 // startcode + NAL type costs 5 bytes per frame
#define FILLER_OVERHEAD (NALU_OVERHEAD+1)
#define SEI_OVERHEAD (NALU_OVERHEAD - (h->param.b_annexb && !h->param.b_avcintra_compat && (h->out.i_nal-1)))
/****************************************************************************
* Includes
......
......@@ -248,6 +248,98 @@ static const uint8_t * const x264_cqm_jvt[8] =
x264_cqm_jvt8i, x264_cqm_jvt8p
};
// 1080i25_avci50, 1080p25_avci50
static const uint8_t x264_cqm_avci50_4ic[16] =
{
16,22,28,40,
22,28,40,44,
28,40,44,48,
40,44,48,60
};
// 1080i25_avci50,
static const uint8_t x264_cqm_avci50_1080i_8iy[64] =
{
16,18,19,21,27,33,81,87,
18,19,21,24,30,33,81,87,
19,21,24,27,30,78,84,90,
21,24,27,30,33,78,84,90,
24,27,30,33,78,81,84,90,
24,27,30,33,78,81,84,93,
27,30,33,78,78,81,87,93,
30,33,33,78,81,84,87,96
};
// 1080p25_avci50, 720p25_avci50, 720p50_avci50
static const uint8_t x264_cqm_avci50_p_8iy[64] =
{
16,18,19,21,24,27,30,33,
18,19,21,24,27,30,33,78,
19,21,24,27,30,33,78,81,
21,24,27,30,33,78,81,84,
24,27,30,33,78,81,84,87,
27,30,33,78,81,84,87,90,
30,33,78,81,84,87,90,93,
33,78,81,84,87,90,93,96
};
// 1080i25_avci100, 1080p25_avci100
static const uint8_t x264_cqm_avci100_1080_4ic[16] =
{
16,20,26,32,
20,26,32,38,
26,32,38,44,
32,38,44,50
};
// 720p25_avci100, 720p50_avci100
static const uint8_t x264_cqm_avci100_720p_4ic[16] =
{
16,21,27,34,
21,27,34,41,
27,34,41,46,
34,41,46,54
};
// 1080i25_avci100,
static const uint8_t x264_cqm_avci100_1080i_8iy[64] =
{
16,19,20,23,24,26,32,42,
18,19,22,24,26,32,36,42,
18,20,23,24,26,32,36,63,
19,20,23,26,32,36,42,63,
20,22,24,26,32,36,59,63,
22,23,24,26,32,36,59,68,
22,23,24,26,32,42,59,68,
22,23,24,26,36,42,59,72
};
// 1080p25_avci100,
static const uint8_t x264_cqm_avci100_1080p_8iy[64] =
{
16,18,19,20,22,23,24,26,
18,19,20,22,23,24,26,32,
19,20,22,23,24,26,32,36,
20,22,23,24,26,32,36,42,
22,23,24,26,32,36,42,59,
23,24,26,32,36,42,59,63,
24,26,32,36,42,59,63,68,
26,32,36,42,59,63,68,72
};
// 720p25_avci100, 720p50_avci100
static const uint8_t x264_cqm_avci100_720p_8iy[64] =
{
16,18,19,21,22,24,26,32,
18,19,19,21,22,24,26,32,
19,19,21,22,22,24,26,32,
21,21,22,22,23,24,26,34,
22,22,22,23,24,25,26,34,
24,24,24,24,25,26,34,36,
26,26,26,26,26,34,36,38,
32,32,32,34,34,36,38,42
};
int x264_cqm_init( x264_t *h );
void x264_cqm_delete( x264_t *h );
int x264_cqm_parse_file( x264_t *h, const char *filename );
......
......@@ -436,7 +436,7 @@ static void x264_mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int qp )
/* non-RD PCM decision is inaccurate (as is psy-rd), so don't do it.
* PCM cost can overflow with high lambda2, so cap it at COST_MAX. */
uint64_t pcm_cost = ((uint64_t)X264_PCM_COST*a->i_lambda2 + 128) >> 8;
a->i_satd_pcm = !h->mb.i_psy_rd && a->i_mbrd && pcm_cost < COST_MAX ? pcm_cost : COST_MAX;
a->i_satd_pcm = !h->param.b_avcintra_compat && !h->mb.i_psy_rd && a->i_mbrd && pcm_cost < COST_MAX ? pcm_cost : COST_MAX;
a->b_fast_intra = 0;
a->b_avoid_topright = 0;
......@@ -811,58 +811,60 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
int lambda = a->i_lambda;
/*---------------- Try all mode and calculate their score ---------------*/
/* 16x16 prediction selection */
const int8_t *predict_mode = predict_16x16_mode_available( h->mb.i_neighbour_intra );
/* Not heavily tuned */
static const uint8_t i16x16_thresh_lut[11] = { 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 };
int i16x16_thresh = a->b_fast_intra ? (i16x16_thresh_lut[h->mb.i_subpel_refine]*i_satd_inter)>>1 : COST_MAX;
if( !h->mb.b_lossless && predict_mode[3] >= 0 )
/* Disabled i16x16 for AVC-Intra compat */
if( !h->param.b_avcintra_compat )
{
h->pixf.intra_mbcmp_x3_16x16( p_src, p_dst, a->i_satd_i16x16_dir );
a->i_satd_i16x16_dir[0] += lambda * bs_size_ue(0);
a->i_satd_i16x16_dir[1] += lambda * bs_size_ue(1);
a->i_satd_i16x16_dir[2] += lambda * bs_size_ue(2);
COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[0], a->i_predict16x16, 0 );
COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[1], a->i_predict16x16, 1 );
COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[2], a->i_predict16x16, 2 );
const int8_t *predict_mode = predict_16x16_mode_available( h->mb.i_neighbour_intra );
/* Plane is expensive, so don't check it unless one of the previous modes was useful. */
if( a->i_satd_i16x16 <= i16x16_thresh )
/* Not heavily tuned */
static const uint8_t i16x16_thresh_lut[11] = { 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 };
int i16x16_thresh = a->b_fast_intra ? (i16x16_thresh_lut[h->mb.i_subpel_refine]*i_satd_inter)>>1 : COST_MAX;
if( !h->mb.b_lossless && predict_mode[3] >= 0 )
{
h->predict_16x16[I_PRED_16x16_P]( p_dst );
a->i_satd_i16x16_dir[I_PRED_16x16_P] = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );
a->i_satd_i16x16_dir[I_PRED_16x16_P] += lambda * bs_size_ue(3);
COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[I_PRED_16x16_P], a->i_predict16x16, 3 );
h->pixf.intra_mbcmp_x3_16x16( p_src, p_dst, a->i_satd_i16x16_dir );
a->i_satd_i16x16_dir[0] += lambda * bs_size_ue(0);
a->i_satd_i16x16_dir[1] += lambda * bs_size_ue(1);
a->i_satd_i16x16_dir[2] += lambda * bs_size_ue(2);
COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[0], a->i_predict16x16, 0 );
COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[1], a->i_predict16x16, 1 );
COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[2], a->i_predict16x16, 2 );
/* Plane is expensive, so don't check it unless one of the previous modes was useful. */
if( a->i_satd_i16x16 <= i16x16_thresh )
{
h->predict_16x16[I_PRED_16x16_P]( p_dst );
a->i_satd_i16x16_dir[I_PRED_16x16_P] = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );
a->i_satd_i16x16_dir[I_PRED_16x16_P] += lambda * bs_size_ue(3);
COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[I_PRED_16x16_P], a->i_predict16x16, 3 );
}
}
}
else
{
for( ; *predict_mode >= 0; predict_mode++ )
else
{
int i_satd;
int i_mode = *predict_mode;
for( ; *predict_mode >= 0; predict_mode++ )
{
int i_satd;
int i_mode = *predict_mode;
if( h->mb.b_lossless )
x264_predict_lossless_16x16( h, 0, i_mode );
else
h->predict_16x16[i_mode]( p_dst );
if( h->mb.b_lossless )
x264_predict_lossless_16x16( h, 0, i_mode );
else
h->predict_16x16[i_mode]( p_dst );
i_satd = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE ) +
lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );
COPY2_IF_LT( a->i_satd_i16x16, i_satd, a->i_predict16x16, i_mode );
a->i_satd_i16x16_dir[i_mode] = i_satd;
i_satd = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE ) +
lambda * bs_size_ue( x264_mb_pred_mode16x16_fix[i_mode] );
COPY2_IF_LT( a->i_satd_i16x16, i_satd, a->i_predict16x16, i_mode );
a->i_satd_i16x16_dir[i_mode] = i_satd;
}
}
}
if( h->sh.i_type == SLICE_TYPE_B )
/* cavlc mb type prefix */
a->i_satd_i16x16 += lambda * i_mb_b_cost_table[I_16x16];
if( h->sh.i_type == SLICE_TYPE_B )
/* cavlc mb type prefix */
a->i_satd_i16x16 += lambda * i_mb_b_cost_table[I_16x16];
if( a->i_satd_i16x16 > i16x16_thresh )
return;
if( a->i_satd_i16x16 > i16x16_thresh )
return;
}
uint16_t *cost_i4x4_mode = (uint16_t*)ALIGN((intptr_t)x264_cost_i4x4_mode,64) + a->i_qp*32 + 8;
/* 8x8 prediction selection */
......@@ -888,7 +890,7 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
int i_best = COST_MAX;
int i_pred_mode = x264_mb_predict_intra4x4_mode( h, 4*idx );
predict_mode = predict_8x8_mode_available( a->b_avoid_topright, h->mb.i_neighbour8[idx], idx );
const int8_t *predict_mode = predict_8x8_mode_available( a->b_avoid_topright, h->mb.i_neighbour8[idx], idx );
h->predict_8x8_filter( p_dst_by, edge, h->mb.i_neighbour8[idx], ALL_NEIGHBORS );
if( h->pixf.intra_mbcmp_x9_8x8 && predict_mode[8] >= 0 )
......@@ -1003,7 +1005,7 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
int i_best = COST_MAX;
int i_pred_mode = x264_mb_predict_intra4x4_mode( h, idx );
predict_mode = predict_4x4_mode_available( a->b_avoid_topright, h->mb.i_neighbour4[idx], idx );
const int8_t *predict_mode = predict_4x4_mode_available( a->b_avoid_topright, h->mb.i_neighbour4[idx], idx );
if( (h->mb.i_neighbour4[idx] & (MB_TOPRIGHT|MB_TOP)) == MB_TOP )
/* emulate missing topright samples */
......
......@@ -568,6 +568,8 @@ static int x264_validate_parameters( x264_t *h, int b_open )
{
h->param.b_intra_refresh = 0;
h->param.analyse.i_weighted_pred = 0;
h->param.i_frame_reference = 1;
h->param.i_dpb_size = 1;
}
h->param.i_frame_packing = x264_clip3( h->param.i_frame_packing, -1, 5 );
......@@ -601,6 +603,165 @@ static int x264_validate_parameters( x264_t *h, int b_open )
x264_log( h, X264_LOG_ERROR, "no ratecontrol method specified\n" );
return -1;
}
if( PARAM_INTERLACED )
h->param.b_pic_struct = 1;
if( h->param.b_avcintra_compat )
{
if( BIT_DEPTH != 10 )
{
x264_log( h, X264_LOG_ERROR, "%2d-bit AVC-Intra is not widely compatible\n", BIT_DEPTH );
x264_log( h, X264_LOG_ERROR, "10-bit x264 is required to encode AVC-Intra\n" );
return -1;
}
/* [50/100][res][fps] */
static const struct
{
uint16_t fps_num;
uint16_t fps_den;
uint8_t interlaced;
uint16_t frame_size;
const uint8_t *cqm_4ic;
const uint8_t *cqm_8iy;
} avcintra_lut[2][2][5] =
{
{{{ 60000, 1001, 0, 912, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy },
{ 50, 1, 0, 1100, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy },
{ 30000, 1001, 0, 912, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy },
{ 25, 1, 0, 1100, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy },
{ 24000, 1001, 0, 912, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }},
{{ 30000, 1001, 1, 1820, x264_cqm_avci50_4ic, x264_cqm_avci50_1080i_8iy },
{ 25, 1, 1, 2196, x264_cqm_avci50_4ic, x264_cqm_avci50_1080i_8iy },
{ 30000, 1001, 0, 1820, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy },
{ 25, 1, 0, 2196, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy },
{ 24000, 1001, 0, 1820, x264_cqm_avci50_4ic, x264_cqm_avci50_p_8iy }}},
{{{ 60000, 1001, 0, 1848, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy },
{ 50, 1, 0, 2224, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy },
{ 30000, 1001, 0, 1848, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy },
{ 25, 1, 0, 2224, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy },
{ 24000, 1001, 0, 1848, x264_cqm_avci100_720p_4ic, x264_cqm_avci100_720p_8iy }},
{{ 30000, 1001, 1, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy },
{ 25, 1, 1, 4444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080i_8iy },
{ 30000, 1001, 0, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy },
{ 25, 1, 0, 4444, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy },
{ 24000, 1001, 0, 3692, x264_cqm_avci100_1080_4ic, x264_cqm_avci100_1080p_8iy }}}
};
int res = -1;
int type = i_csp == X264_CSP_I422;
if( type )
{
if( h->param.i_width == 1920 && h->param.i_height == 1080 ) res = 1;
else if( h->param.i_width == 1280 && h->param.i_height == 720 ) res = 0;
}
else if( i_csp == X264_CSP_I420 )
{
if( h->param.i_width == 1440 && h->param.i_height == 1080 ) res = 1;
else if( h->param.i_width == 960 && h->param.i_height == 720 ) res = 0;
}
else
{
x264_log( h, X264_LOG_ERROR, "Invalid colorspace for AVC-Intra\n" );
return -1;
}
if( res < 0 )
{
x264_log( h, X264_LOG_ERROR, "Resolution %dx%d invalid for AVC-Intra %s\n",
h->param.i_width, h->param.i_height, type ? "100" : "50" );
return -1;
}
if( h->param.nalu_process )
{
x264_log( h, X264_LOG_ERROR, "nalu_process is not supported in AVC-Intra mode\n" );
return -1;
}
if( !h->param.b_repeat_headers )
{
x264_log( h, X264_LOG_ERROR, "Separate headers not supported in AVC-Intra mode\n" );
return -1;
}
int i;
uint32_t fps_num = h->param.i_fps_num, fps_den = h->param.i_fps_den;
x264_reduce_fraction( &fps_num, &fps_den );
for( i = 0; i < 5; i++ )
{
if( avcintra_lut[type][res][i].fps_num == fps_num &&
avcintra_lut[type][res][i].fps_den == fps_den &&
avcintra_lut[type][res][i].interlaced == PARAM_INTERLACED )
{
break;
}
}
if( i == 5 )
{
x264_log( h, X264_LOG_ERROR, "FPS %d/%d%c not compatible with AVC-Intra\n",
h->param.i_fps_num, h->param.i_fps_den, PARAM_INTERLACED ? 'i' : 'p' );
return -1;
}
h->param.i_keyint_max = 1;
h->param.b_intra_refresh = 0;
h->param.analyse.i_weighted_pred = 0;
h->param.i_frame_reference = 1;
h->param.i_dpb_size = 1;
h->param.b_bluray_compat = 0;
h->param.b_vfr_input = 0;
h->param.b_aud = 1;
h->param.vui.i_chroma_loc = 0;
h->param.i_nal_hrd = X264_NAL_HRD_NONE;
h->param.b_deblocking_filter = 0;
h->param.b_stitchable = 1;
h->param.b_pic_struct = 0;
h->param.analyse.b_transform_8x8 = 1;
h->param.analyse.intra = X264_ANALYSE_I8x8;
h->param.analyse.i_chroma_qp_offset = res && type ? 3 : 4;
h->param.b_cabac = !type;
h->param.rc.i_vbv_buffer_size = avcintra_lut[type][res][i].frame_size;
h->param.rc.i_vbv_max_bitrate =
h->param.rc.i_bitrate = h->param.rc.i_vbv_buffer_size * fps_num / fps_den;
h->param.rc.i_rc_method = X264_RC_ABR;
h->param.rc.f_vbv_buffer_init = 1.0;
h->param.i_cqm_preset = X264_CQM_CUSTOM;
memcpy( h->param.cqm_4iy, x264_cqm_jvt4i, sizeof(h->param.cqm_4iy) );
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 )
{
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;
}
}
if( type )
h->param.vui.i_sar_width = h->param.vui.i_sar_height = 1;
else
{
h->param.vui.i_sar_width = 4;
h->param.vui.i_sar_height = 3;
}
/* Avid cannot handle negative QPs */
h->param.rc.i_qp_min = X264_MAX( h->param.rc.i_qp_min, QP_BD_OFFSET );
}
h->param.rc.f_rf_constant = x264_clip3f( h->param.rc.f_rf_constant, -QP_BD_OFFSET, 51 );
h->param.rc.f_rf_constant_max = x264_clip3f( h->param.rc.f_rf_constant_max, -QP_BD_OFFSET, 51 );
h->param.rc.i_qp_constant = x264_clip3( h->param.rc.i_qp_constant, 0, QP_MAX );
......@@ -902,10 +1063,10 @@ static int x264_validate_parameters( x264_t *h, int b_open )
h->param.analyse.i_chroma_qp_offset += 6;
/* Psy RDO increases overall quantizers to improve the quality of luma--this indirectly hurts chroma quality */
/* so we lower the chroma QP offset to compensate */
if( b_open && h->mb.i_psy_rd )
if( b_open && h->mb.i_psy_rd && !h->param.b_avcintra_compat )
h->param.analyse.i_chroma_qp_offset -= h->param.analyse.f_psy_rd < 0.25 ? 1 : 2;
/* Psy trellis has a similar effect. */
if( b_open && h->mb.i_psy_trellis )
if( b_open && h->mb.i_psy_trellis && !h->param.b_avcintra_compat )
h->param.analyse.i_chroma_qp_offset -= h->param.analyse.f_psy_trellis < 0.25 ? 1 : 2;
h->param.analyse.i_chroma_qp_offset = x264_clip3(h->param.analyse.i_chroma_qp_offset, -12, 12);
/* MB-tree requires AQ to be on, even if the strength is zero. */
......@@ -1026,9 +1187,6 @@ static int x264_validate_parameters( x264_t *h, int b_open )
h->param.i_sps_id &= 31;
if( PARAM_INTERLACED )
h->param.b_pic_struct = 1;
h->param.i_nal_hrd = x264_clip3( h->param.i_nal_hrd, X264_NAL_HRD_NONE, X264_NAL_HRD_CBR );
if( h->param.i_nal_hrd && !h->param.rc.i_vbv_buffer_size )
......@@ -1067,6 +1225,7 @@ static int x264_validate_parameters( x264_t *h, int b_open )
BOOLIFY( b_stitchable );
BOOLIFY( b_full_recon );
BOOLIFY( b_opencl );
BOOLIFY( b_avcintra_compat );
BOOLIFY( analyse.b_transform_8x8 );
BOOLIFY( analyse.b_weighted_bipred );
BOOLIFY( analyse.b_chroma_me );
......@@ -1615,6 +1774,7 @@ static void x264_nal_start( x264_t *h, int i_type, int i_ref_idc )
nal->i_payload= 0;
nal->p_payload= &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8];
nal->i_padding= 0;
}
/* if number of allocated nals is not enough, re-allocate a larger one. */
......@@ -1648,6 +1808,30 @@ static int x264_nal_end( x264_t *h )
return x264_nal_check_buffer( h );
}
static int x264_check_encapsulated_buffer( x264_t *h, x264_t *h0, int start,
int previous_nal_size, int necessary_size )
{
if( h0->nal_buffer_size < necessary_size )
{
necessary_size *= 2;
uint8_t *buf = x264_malloc( necessary_size );
if( !buf )
return -1;
if( previous_nal_size )
memcpy( buf, h0->nal_buffer, previous_nal_size );
intptr_t delta = buf - h0->nal_buffer;
for( int i = 0; i < start; i++ )
h->out.nal[i].p_payload += delta;
x264_free( h0->nal_buffer );
h0->nal_buffer = buf;
h0->nal_buffer_size = necessary_size;
}
return 0;
}
static int x264_encoder_encapsulate_nals( x264_t *h, int start )
{
x264_t *h0 = h->thread[0];
......@@ -1668,31 +1852,31 @@ static int x264_encoder_encapsulate_nals( x264_t *h, int start )
/* Worst-case NAL unit escaping: reallocate the buffer if it's too small. */
int necessary_size = previous_nal_size + nal_size * 3/2 + h->out.i_nal * 4 + 4 + 64;
if( h0->nal_buffer_size < necessary_size )
{
necessary_size *= 2;
uint8_t *buf = x264_malloc( necessary_size );
if( !buf )
return -1;
if( previous_nal_size )
memcpy( buf, h0->nal_buffer, previous_nal_size );
intptr_t delta = buf - h0->nal_buffer;
for( int i = 0; i < start; i++ )
h->out.nal[i].p_payload += delta;
x264_free( h0->nal_buffer );
h0->nal_buffer = buf;
h0->nal_buffer_size = necessary_size;
}
for( int i = start; i < h->out.i_nal; i++ )
necessary_size += h->out.nal[i].i_padding;
if( x264_check_encapsulated_buffer( h, h0, start, previous_nal_size, necessary_size ) )
return -1;
uint8_t *nal_buffer = h0->nal_buffer + previous_nal_size;
for( int i = start; i < h->out.i_nal; i++ )
{
h->out.nal[i].b_long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS;
int old_payload_len = h->out.nal[i].i_payload;
h->out.nal[i].b_long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS ||
h->param.b_avcintra_compat;
x264_nal_encode( h, nal_buffer, &h->out.nal[i] );
nal_buffer += h->out.nal[i].i_payload;
if( h->param.b_avcintra_compat )
{
h->out.nal[i].i_padding -= h->out.nal[i].i_payload - (old_payload_len + NALU_OVERHEAD);
if( h->out.nal[i].i_padding > 0 )
{
memset( nal_buffer, 0, h->out.nal[i].i_padding );
nal_buffer += h->out.nal[i].i_padding;
h->out.nal[i].i_payload += h->out.nal[i].i_padding;
}
h->out.nal[i].i_padding = X264_MAX( h->out.nal[i].i_padding, 0 );
}
}
x264_emms();
......@@ -3188,7 +3372,7 @@ int x264_encoder_encode( x264_t *h,
bs_rbsp_trailing( &h->out.bs );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
}
h->i_nal_type = i_nal_type;
......@@ -3240,14 +3424,19 @@ int x264_encoder_encode( x264_t *h,
x264_sps_write( &h->out.bs, h->sps );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
/* Pad AUD/SPS to 256 bytes like Panasonic */
if( h->param.b_avcintra_compat )
h->out.nal[h->out.i_nal-1].i_padding = 256 - bs_pos( &h->out.bs ) / 8 - 2*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;
/* generate picture parameters */
x264_nal_start( h, NAL_PPS, NAL_PRIORITY_HIGHEST );
x264_pps_write( &h->out.bs, h->sps, h->pps );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
if( h->param.b_avcintra_compat )
h->out.nal[h->out.i_nal-1].i_padding = 256 - 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;
}
/* when frame threading is used, buffering period sei is written in x264_encoder_frame_end */
......@@ -3258,7 +3447,7 @@ int x264_encoder_encode( x264_t *h,
x264_sei_buffering_period_write( h, &h->out.bs );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
}
}
......@@ -3270,7 +3459,7 @@ int x264_encoder_encode( x264_t *h,
h->fenc->extra_sei.payloads[i].payload_type );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
if( h->fenc->extra_sei.sei_free )
{
h->fenc->extra_sei.sei_free( h->fenc->extra_sei.payloads[i].payload );
......@@ -3287,7 +3476,8 @@ int x264_encoder_encode( x264_t *h,
if( h->fenc->b_keyframe )
{
if( h->param.b_repeat_headers && h->fenc->i_frame == 0 )
/* Avid's decoder strictly wants two SEIs for AVC-Intra so we can't insert the x264 SEI */
if( h->param.b_repeat_headers && h->fenc->i_frame == 0 && !h->param.b_avcintra_compat )
{
/* identify ourself */
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
......@@ -3295,7 +3485,7 @@ int x264_encoder_encode( x264_t *h,
return -1;
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
}
if( h->fenc->i_type != X264_TYPE_IDR )
......@@ -3305,16 +3495,16 @@ int x264_encoder_encode( x264_t *h,
x264_sei_recovery_point_write( h, &h->out.bs, time_to_recovery );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
}
if ( h->param.i_frame_packing >= 0 )
if( h->param.i_frame_packing >= 0 )
{
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
x264_sei_frame_packing_write( h, &h->out.bs );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
}
}
......@@ -3325,7 +3515,7 @@ int x264_encoder_encode( x264_t *h,
x264_sei_pic_timing_write( h, &h->out.bs );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
}
/* As required by Blu-ray. */
......@@ -3336,12 +3526,58 @@ int x264_encoder_encode( x264_t *h,
x264_sei_dec_ref_pic_marking_write( h, &h->out.bs );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
}
if( h->fenc->b_keyframe && h->param.b_intra_refresh )
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.b_avcintra_compat )
{
/* Write an empty filler NAL to mimic the AUD in the P2 format*/
if( h->param.b_avcintra_compat )
{
x264_nal_start( h, NAL_FILLER, NAL_PRIORITY_DISPOSABLE );
x264_filler_write( h, &h->out.bs, 0 );
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD;
}
/* All lengths are magic lengths that decoders expect to see */
/* "UMID" SEI */
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
if( x264_sei_avcintra_write( h, &h->out.bs, 497, "UMID" ) < 0 )
return -1;
if( x264_nal_end( h ) )
return -1;
overhead += h->out.nal[h->out.i_nal-1].i_payload + SEI_OVERHEAD;
int unpadded_len;
int total_len;
if( h->param.i_height == 1080 )
{
unpadded_len = 5780;
total_len = 17*512;
}
else
{
unpadded_len = 2900;
total_len = 9*512;
}
/* "VANC" SEI */
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
if( x264_sei_avcintra_write( h, &h->out.bs, unpadded_len, "VANC" ) < 0 )
return -1;
if( x264_nal_end( h ) )
return -1;
h->out.nal[h->out.i_nal-1].i_padding = total_len - h->out.nal[h->out.i_nal-1].i_payload - SEI_OVERHEAD;
overhead += h->out.nal[h->out.i_nal-1].i_payload + h->out.nal[h->out.i_nal-1].i_padding + SEI_OVERHEAD;
}
/* Init the rate control */