[x264-devel] Improve Blu-ray compliance
Jason Garrett-Glaser
git at videolan.org
Wed Apr 13 04:04:30 CEST 2011
x264 | branch: master | Jason Garrett-Glaser <jason at x264.com> | Wed Apr 6 02:16:42 2011 -0700| [7a9e08d301212fc37516562269d5fbbc040cf84c] | committer: Jason Garrett-Glaser
Improve Blu-ray compliance
Use dec_ref_pic_marking SEIs to repeat B-ref referencing information.
Don't allow B-frames to reference frames outside their minigop.
> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=7a9e08d301212fc37516562269d5fbbc040cf84c
---
common/common.h | 5 +++++
encoder/encoder.c | 21 +++++++++++++++++++++
encoder/set.c | 33 ++++++++++++++++++++++++++++++++-
encoder/set.h | 1 +
4 files changed, 59 insertions(+), 1 deletions(-)
diff --git a/common/common.h b/common/common.h
index 496542e..a9be078 100644
--- a/common/common.h
+++ b/common/common.h
@@ -310,6 +310,7 @@ enum sei_payload_type_e
SEI_USER_DATA_REGISTERED = 4,
SEI_USER_DATA_UNREGISTERED = 5,
SEI_RECOVERY_POINT = 6,
+ SEI_DEC_REF_PIC_MARKING = 7,
SEI_FRAME_PACKING = 45,
};
@@ -473,6 +474,10 @@ struct x264_t
/* Slice header */
x264_slice_header_t sh;
+ /* Slice header backup, for SEI_DEC_REF_PIC_MARKING */
+ int b_sh_backup;
+ x264_slice_header_t sh_backup;
+
/* cabac context */
x264_cabac_t cabac;
diff --git a/encoder/encoder.c b/encoder/encoder.c
index b0fc7b9..56cbd27 100644
--- a/encoder/encoder.c
+++ b/encoder/encoder.c
@@ -1665,6 +1665,10 @@ static inline void x264_reference_build_list( x264_t *h, int i_poc )
h->i_ref[0] = X264_MIN( h->i_ref[0], h->frames.i_max_ref0 );
h->i_ref[0] = X264_MIN( h->i_ref[0], h->param.i_frame_reference ); // if reconfig() has lowered the limit
+ /* For Blu-ray compliance, don't reference frames outside of the minigop. */
+ if( IS_X264_TYPE_B( h->fenc->i_type ) && h->param.b_bluray_compat )
+ h->i_ref[0] = X264_MIN( h->i_ref[0], IS_X264_TYPE_B( h->fref[0][0]->i_type ) + 1 );
+
/* add duplicates */
if( h->fenc->i_type == X264_TYPE_P )
{
@@ -1879,6 +1883,12 @@ static inline void x264_slice_init( x264_t *h, int i_nal_type, int i_global_qp )
}
}
+ if( h->fenc->i_type == X264_TYPE_BREF && h->param.b_bluray_compat && h->sh.i_mmco_command_count )
+ {
+ h->b_sh_backup = 1;
+ h->sh_backup = h->sh;
+ }
+
h->fdec->i_frame_num = h->sh.i_frame_num;
if( h->sps->i_poc_type == 0 )
@@ -2775,6 +2785,17 @@ int x264_encoder_encode( x264_t *h,
overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
}
+ /* As required by Blu-ray. */
+ if( !IS_X264_TYPE_B( h->fenc->i_type ) && h->b_sh_backup )
+ {
+ h->b_sh_backup = 0;
+ x264_nal_start( h, NAL_SEI, NAL_PRIORITY_DISPOSABLE );
+ 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);
+ }
+
if( h->fenc->b_keyframe && h->param.b_intra_refresh )
h->i_cpb_delay_pir_offset = h->fenc->i_cpb_delay;
diff --git a/encoder/set.c b/encoder/set.c
index 78f1b56..e7cdf1c 100644
--- a/encoder/set.c
+++ b/encoder/set.c
@@ -551,7 +551,6 @@ void x264_sei_recovery_point_write( x264_t *h, bs_t *s, int recovery_frame_cnt )
bs_flush( &q );
x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_RECOVERY_POINT );
-
}
int x264_sei_version_write( x264_t *h, bs_t *s )
@@ -689,6 +688,38 @@ void x264_filler_write( x264_t *h, bs_t *s, int filler )
bs_flush( s );
}
+void x264_sei_dec_ref_pic_marking_write( x264_t *h, bs_t *s )
+{
+ x264_slice_header_t *sh = &h->sh_backup;
+ bs_t q;
+ uint8_t tmp_buf[100];
+ bs_init( &q, tmp_buf, 100 );
+
+ bs_realign( &q );
+
+ /* We currently only use this for repeating B-refs, as required by Blu-ray. */
+ bs_write1( &q, 0 ); //original_idr_flag
+ bs_write_ue( &q, sh->i_frame_num ); //original_frame_num
+ if( !h->sps->b_frame_mbs_only )
+ bs_write1( &q, 0 ); //original_field_pic_flag
+
+ bs_write1( &q, sh->i_mmco_command_count > 0 );
+ if( sh->i_mmco_command_count > 0 )
+ {
+ for( int i = 0; i < sh->i_mmco_command_count; i++ )
+ {
+ bs_write_ue( &q, 1 );
+ bs_write_ue( &q, sh->mmco[i].i_difference_of_pic_nums - 1 );
+ }
+ bs_write_ue( &q, 0 );
+ }
+
+ bs_align_10( &q );
+ bs_flush( &q );
+
+ x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_DEC_REF_PIC_MARKING );
+}
+
const x264_level_t x264_levels[] =
{
{ 10, 1485, 99, 152064, 64, 175, 64, 64, 0, 2, 0, 0, 1 },
diff --git a/encoder/set.h b/encoder/set.h
index 7fcca13..4f1eeab 100644
--- a/encoder/set.h
+++ b/encoder/set.h
@@ -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_dec_ref_pic_marking_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 );
More information about the x264-devel
mailing list