[x264-devel] [PATCH] encoder/set: add timecode to pic_timing SEI
joshdk at ob-encoder.com
joshdk at ob-encoder.com
Tue Oct 2 17:48:27 CEST 2018
From: Josh de Kock <joshdk at obe.tv>
---
Comments welcome, and appreciated.
common/frame.c | 3 +++
common/frame.h | 3 ++-
encoder/set.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++--
x264.h | 27 +++++++++++++++++++-
4 files changed, 98 insertions(+), 4 deletions(-)
diff --git a/common/frame.c b/common/frame.c
index a74a7858..86f937fc 100644
--- a/common/frame.c
+++ b/common/frame.c
@@ -396,6 +396,9 @@ int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
dst->i_qpplus1 = src->i_qpplus1;
dst->i_pts = dst->i_reordered_pts = src->i_pts;
dst->param = src->param;
+ if( src->i_timecode )
+ memcpy( dst->timecode, src->timecode, sizeof(dst->timecode[0]) * src->i_timecode );
+ dst->i_timecode = src->i_timecode;
dst->i_pic_struct = src->i_pic_struct;
dst->extra_sei = src->extra_sei;
dst->opaque = src->opaque;
diff --git a/common/frame.h b/common/frame.h
index 8370d581..ea11b1da 100644
--- a/common/frame.h
+++ b/common/frame.h
@@ -50,7 +50,8 @@ typedef struct x264_frame
int64_t i_cpb_delay; /* in SPS time_scale units (i.e 2 * timebase units) */
int64_t i_dpb_output_delay;
x264_param_t *param;
-
+ x264_timecode_t timecode[3];
+ int i_timecode;
int i_frame; /* Presentation frame number */
int i_coded; /* Coded frame number */
int64_t i_field_cnt; /* Presentation field count */
diff --git a/encoder/set.c b/encoder/set.c
index 07a1261e..677c76c6 100644
--- a/encoder/set.c
+++ b/encoder/set.c
@@ -228,6 +228,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
sps->vui.b_vcl_hrd_parameters_present = 0; // we don't support VCL HRD
sps->vui.b_nal_hrd_parameters_present = !!param->i_nal_hrd;
sps->vui.b_pic_struct_present = param->b_pic_struct;
+ sps->vui.hrd.i_time_offset_length = 24;
// NOTE: HRD related parts of the SPS are initialised in x264_ratecontrol_init_reconfigurable
@@ -652,8 +653,72 @@ void x264_sei_pic_timing_write( x264_t *h, bs_t *s )
// These clock timestamps are not standardised so we don't set them
// They could be time of origin, capture or alternative ideal display
- for( int i = 0; i < num_clock_ts[h->fenc->i_pic_struct]; i++ )
- bs_write1( &q, 0 ); // clock_timestamp_flag
+ for( int i = 0; i < num_clock_ts[h->fenc->i_pic_struct]; i++ ) {
+ if ( !h->fenc->i_timecode )
+ {
+ bs_write1( &q, 0 ); // clock_timestamp_flag
+ }
+ else
+ {
+ // D.2.2
+ int ct_type; // Table D-2
+ switch ( h->fenc->i_pic_struct )
+ {
+ case PIC_STRUCT_PROGRESSIVE:
+ case PIC_STRUCT_DOUBLE:
+ case PIC_STRUCT_TRIPLE:
+ ct_type = 0; // progressive
+ break;
+ case PIC_STRUCT_TOP_BOTTOM:
+ case PIC_STRUCT_BOTTOM_TOP:
+ case PIC_STRUCT_TOP_BOTTOM_TOP:
+ case PIC_STRUCT_BOTTOM_TOP_BOTTOM:
+ ct_type = 1; // interlaced
+ break;
+ default:
+ ct_type = 2; // unknown
+ }
+ x264_timecode_t *tc = &h->fenc->timecode[X264_MIN(i, h->fenc->i_timecode - 1)];
+ bs_write1( &q, 1 ); // have timecode
+
+ bs_write( &q, 2, ct_type ); // ct_type
+ bs_write1( &q, 1 ); // nuit_field_based_flag
+ bs_write( &q, 5, tc->i_counting_type ); // counting_type (Table D-3)
+ bs_write1( &q, tc->i_type == TIMECODE_FULL); // full_timestamp_flag
+
+ bs_write1( &q, tc->b_discontinuity ); // discontinuity_flag
+ bs_write1( &q, tc->b_drop ); // cnt_dropped_flag
+
+ bs_write( &q, 8, tc->i_frame ); // n_frames
+ if ( tc->i_type == TIMECODE_FULL )
+ {
+ bs_write( &q, 6, tc->i_seconds ); // seconds 0..59
+ bs_write( &q, 6, tc->i_minutes ); // minutes 0..59
+ bs_write( &q, 5, tc->i_hours ); // hours 0..23
+ }
+ else
+ {
+ bs_write1( &q, !!(tc->i_type & TIMECODE_SECONDS) ); // seconds_flag
+ if ( tc->i_type & TIMECODE_SECONDS )
+ {
+ bs_write( &q, 6, tc->i_seconds ); // seconds 0..59
+ bs_write1( &q, !!(tc->i_type & TIMECODE_MINUTES) ); // minutes_flag
+ if ( tc->i_type & TIMECODE_MINUTES )
+ {
+ bs_write( &q, 6, tc->i_minutes ); // minutes 0..59
+ bs_write1( &q, !!(tc->i_type & TIMECODE_HOURS) ); // hours_flag
+ if ( tc->i_type & TIMECODE_HOURS )
+ {
+ bs_write( &q, 5, tc->i_hours ); // hours 0..23
+ }
+ }
+ }
+ }
+
+ // length is initialised to 24, it is user's fault if it's invalid here
+ bs_write( &q, sps->vui.hrd.i_time_offset_length, 0 );
+ }
+ }
}
bs_align_10( &q );
diff --git a/x264.h b/x264.h
index 5f7294e3..ae9a7e5e 100644
--- a/x264.h
+++ b/x264.h
@@ -45,7 +45,7 @@ extern "C" {
#include "x264_config.h"
-#define X264_BUILD 157
+#define X264_BUILD 158
/* Application developers planning to link against a shared library version of
* libx264 from a Microsoft Visual Studio or similar development environment
@@ -720,6 +720,27 @@ typedef struct x264_hrd_t
* Payloads are written first in order of input, apart from in the case when HRD
* is enabled where payloads are written after the Buffering Period SEI. */
+enum x264_timecode_type_e
+{
+ TIMECODE_SECONDS = 1,
+ TIMECODE_MINUTES = 1 << 1,
+ TIMECODE_HOURS = 1 << 2,
+ TIMECODE_FULL = TIMECODE_SECONDS | TIMECODE_MINUTES | TIMECODE_HOURS,
+};
+
+typedef struct x264_timecode_t
+{
+ uint8_t i_hours;
+ uint8_t i_minutes;
+ uint8_t i_seconds;
+ uint8_t i_frame;
+ int b_drop;
+ int b_sync;
+ int b_discontinuity;
+ int i_counting_type;
+ int i_type;
+} x264_timecode_t;
+
typedef struct x264_sei_payload_t
{
int payload_size;
@@ -838,6 +859,10 @@ typedef struct x264_picture_t
/* Out: HRD timing information. Output only when i_nal_hrd is set. */
x264_hrd_t hrd_timing;
/* In: arbitrary user SEI (e.g subtitles, AFDs) */
+ x264_timecode_t timecode[3];
+ /* In: arbitary user timecode */
+ int i_timecode;
+ /* Number of timecode in use for this frame */
x264_sei_t extra_sei;
/* private user data. copied from input to output frames. */
void *opaque;
--
2.17.1
More information about the x264-devel
mailing list