[x264-devel] [PATCH v2] encoder/set: add timecode to pic_timing SEI

joshdk at ob-encoder.com joshdk at ob-encoder.com
Thu Oct 18 17:41:02 CEST 2018


From: Josh de Kock <joshdk at obe.tv>

---
 common/frame.c |  1 +
 common/frame.h |  3 ++-
 encoder/set.c  | 69 ++++++++++++++++++++++++++++++++++++++++++++++++--
 x264.h         | 26 ++++++++++++++++++-
 4 files changed, 95 insertions(+), 4 deletions(-)

diff --git a/common/frame.c b/common/frame.c
index a74a7858..4c3a2ad0 100644
--- a/common/frame.c
+++ b/common/frame.c
@@ -396,6 +396,7 @@ 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;
+    memcpy( dst->timecode, src->timecode, sizeof(dst->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..3a0a4fa7 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->timecode[i].b_valid )
+            {
+                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[i];
+                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..429bd350 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,28 @@ 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
+{
+    int b_valid;
+    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 +860,8 @@ 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 */
     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