Commit 898579cc authored by Vittorio Giovara's avatar Vittorio Giovara Committed by Fiona Glaser

Add frame-packing SEI support for signalling 3D video

parent dde9e9bc
......@@ -165,6 +165,7 @@ void x264_param_default( x264_param_t *param )
param->b_tff = 1;
param->b_pic_struct = 0;
param->b_fake_interlaced = 0;
param->i_frame_packing = -1;
}
static int x264_param_apply_preset( x264_param_t *param, const char *preset )
......@@ -978,6 +979,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
p->b_pic_struct = atobool(value);
OPT("fake-interlaced")
p->b_fake_interlaced = atobool(value);
OPT("frame-packing")
p->i_frame_packing = atoi(value);
else
return X264_PARAM_BAD_NAME;
#undef OPT
......
......@@ -309,6 +309,7 @@ enum sei_payload_type_e
SEI_USER_DATA_REGISTERED = 4,
SEI_USER_DATA_UNREGISTERED = 5,
SEI_RECOVERY_POINT = 6,
SEI_FRAME_PACKING = 45,
};
typedef struct
......
......@@ -469,6 +469,8 @@ static int x264_validate_parameters( x264_t *h )
}
}
h->param.i_frame_packing = x264_clip3( h->param.i_frame_packing, -1, 5 );
/* Detect default ffmpeg settings and terminate with an error. */
{
int score = 0;
......@@ -1199,6 +1201,7 @@ int x264_encoder_reconfig( x264_t *h, x264_param_t *param )
COPY( b_deblocking_filter );
COPY( i_deblocking_filter_alphac0 );
COPY( i_deblocking_filter_beta );
COPY( i_frame_packing );
COPY( analyse.inter );
COPY( analyse.intra );
COPY( analyse.i_direct_mv_pred );
......@@ -2674,7 +2677,17 @@ int x264_encoder_encode( x264_t *h,
int time_to_recovery = h->param.i_open_gop ? 0 : X264_MIN( h->mb.i_mb_width - 1, h->param.i_keyint_max ) + h->param.i_bframe - 1;
x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
x264_sei_recovery_point_write( h, &h->out.bs, time_to_recovery );
x264_nal_end( h );
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);
}
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);
}
}
......
......@@ -638,6 +638,47 @@ void x264_sei_pic_timing_write( x264_t *h, bs_t *s )
x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_PIC_TIMING );
}
void x264_sei_frame_packing_write( x264_t *h, bs_t *s )
{
bs_t q;
uint8_t tmp_buf[100];
bs_init( &q, tmp_buf, 100 );
bs_realign( &q );
bs_write_ue( &q, 0 ); // frame_packing_arrangement_id
bs_write1( &q, 0 ); // frame_packing_arrangement_cancel_flag
bs_write ( &q, 7, h->param.i_frame_packing ); // frame_packing_arrangement_type
bs_write1( &q, 0 ); // quincunx_sampling_flag
// 0: views are unrelated, 1: left view is on the left, 2: left view is on the right
bs_write ( &q, 6, 1 ); // content_interpretation_type
/* The following flags shall be set to 0 and ignored by the decoder
* (Why, then, do they even exist? Who knows.) */
bs_write1( &q, 0 ); // spatial_flipping_flag
bs_write1( &q, 0 ); // frame0_flipped_flag
bs_write1( &q, 0 ); // field_views_flag
bs_write1( &q, 0 ); // current_frame_is_frame0_flag
bs_write1( &q, 0 ); // frame0_self_contained_flag
bs_write1( &q, 0 ); // frame1_self_contained_flag
if ( /* quincunx_sampling_flag == 0 && */ h->param.i_frame_packing != 5 )
{
bs_write( &q, 4, 0 ); // frame0_grid_position_x
bs_write( &q, 4, 0 ); // frame0_grid_position_y
bs_write( &q, 4, 0 ); // frame1_grid_position_x
bs_write( &q, 4, 0 ); // frame1_grid_position_y
}
bs_write( &q, 8, 0 ); // frame_packing_arrangement_reserved_byte
bs_write_ue( &q, 0 ); // frame_packing_arrangement_repetition_period
bs_write1( &q, 0 ); // frame_packing_arrangement_extension_flag
bs_align_10( &q );
bs_flush( &q );
x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_FRAME_PACKING );
}
void x264_filler_write( x264_t *h, bs_t *s, int filler )
{
bs_realign( s );
......
......@@ -36,6 +36,7 @@ int x264_sei_version_write( x264_t *h, bs_t *s );
int x264_validate_levels( x264_t *h, int verbose );
void x264_sei_buffering_period_write( x264_t *h, bs_t *s );
void x264_sei_pic_timing_write( x264_t *h, bs_t *s );
void x264_sei_frame_packing_write( x264_t *h, bs_t *s );
void x264_sei_write( bs_t *s, uint8_t *payload, int payload_size, int payload_type );
void x264_filler_write( x264_t *h, bs_t *s, int filler );
......
......@@ -551,6 +551,13 @@ static void help( x264_param_t *defaults, int longhelp )
H2( " --fake-interlaced Flag stream as interlaced but encode progressive.\n"
" Makes it possible to encode 25p and 30p Blu-Ray\n"
" streams. Ignored in interlaced mode.\n" );
H2( " --frame-packing <integer> For stereoscopic videos define frame arrangement\n"
" - 0: checkerboard - pixels are alternatively from L and R\n"
" - 1: column alternation - L and R are interlaced by column\n"
" - 2: row alternation - L and R are interlaced by row\n"
" - 3: side by side - L is on the left, R on the right\n"
" - 4: top bottom - L is on top, R on bottom\n"
" - 5: frame alternation - one view per frame\n" );
H0( "\n" );
H0( "Ratecontrol:\n" );
H0( "\n" );
......@@ -937,6 +944,7 @@ static struct option long_options[] =
{ "nal-hrd", required_argument, NULL, 0 },
{ "pulldown", required_argument, NULL, OPT_PULLDOWN },
{ "fake-interlaced", no_argument, NULL, 0 },
{ "frame-packing", required_argument, NULL, 0 },
{ "vf", required_argument, NULL, OPT_VIDEO_FILTER },
{ "video-filter", required_argument, NULL, OPT_VIDEO_FILTER },
{ "input-res", required_argument, NULL, OPT_INPUT_RES },
......
......@@ -41,7 +41,7 @@
#include "x264_config.h"
#define X264_BUILD 110
#define X264_BUILD 111
/* x264_t:
* opaque handler for encoder */
......@@ -390,6 +390,9 @@ typedef struct x264_param_t
unsigned int i_bottom;
} crop_rect;
/* frame packing arrangement flag */
int i_frame_packing;
/* Muxing parameters */
int b_aud; /* generate access unit delimiters */
int b_repeat_headers; /* put SPS/PPS before each keyframe */
......
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