From 5ca52ea0260d26de8967216b3cc2cce5ed6c4901 Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Thu, 25 Jul 2024 17:50:26 +0200 Subject: [PATCH] h264parse, h265parse: Fix time code calculation We need to multiply for the nuit_field_based_flag before scaling, or we'll lose precision and end up only adding even timecodes. Part-of: --- .../gst/videoparsers/gsth264parse.c | 26 +++++------ .../gst/videoparsers/gsth265parse.c | 44 +++++++++++-------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/subprojects/gst-plugins-bad/gst/videoparsers/gsth264parse.c b/subprojects/gst-plugins-bad/gst/videoparsers/gsth264parse.c index d7fea7c026..56543d8acd 100644 --- a/subprojects/gst-plugins-bad/gst/videoparsers/gsth264parse.c +++ b/subprojects/gst-plugins-bad/gst/videoparsers/gsth264parse.c @@ -3388,8 +3388,7 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) GstH264ClockTimestamp *tim = &h264parse->pic_timing_sei.clock_timestamp[i]; gint field_count = -1; - guint64 n_frames_tmp; - guint n_frames = G_MAXUINT32; + guint64 n_frames = G_MAXUINT64; GstVideoTimeCodeFlags flags = 0; guint64 scale_n, scale_d; @@ -3467,19 +3466,17 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) scale_n = (guint64) h264parse->parsed_fps_n * vui->num_units_in_tick; scale_d = (guint64) h264parse->parsed_fps_d * vui->time_scale; - n_frames_tmp = gst_util_uint64_scale (tim->n_frames, scale_n, scale_d); - if (n_frames_tmp <= G_MAXUINT32) { - if (tim->nuit_field_based_flag) - n_frames_tmp *= 2; + if (tim->nuit_field_based_flag) + scale_n *= 2; - if (n_frames_tmp <= G_MAXUINT32) - n_frames = (guint) n_frames_tmp; - } + n_frames = gst_util_uint64_scale (tim->n_frames, scale_n, scale_d); - if (n_frames != G_MAXUINT32) { + if (n_frames <= G_MAXUINT32) { GST_LOG_OBJECT (h264parse, "Add time code meta %02u:%02u:%02u:%02u", - tim->hours_value, tim->minutes_value, tim->seconds_value, n_frames); + tim->hours_flag ? tim->hours_value : 0, + tim->minutes_flag ? tim->minutes_value : 0, + tim->seconds_flag ? tim->seconds_value : 0, (guint) n_frames); gst_buffer_add_video_time_code_meta_full (parse_buffer, h264parse->parsed_fps_n, @@ -3488,8 +3485,11 @@ gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) flags, tim->hours_flag ? tim->hours_value : 0, tim->minutes_flag ? tim->minutes_value : 0, - tim->seconds_flag ? tim->seconds_value : 0, n_frames, field_count); - } + tim->seconds_flag ? tim->seconds_value : 0, + (guint) n_frames, field_count); + } else + GST_WARNING_OBJECT (h264parse, + "Skipping time code meta, n_frames calculation failed"); } h264parse->num_clock_timestamp = 0; diff --git a/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c b/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c index 5994abafc5..491c1c8c24 100644 --- a/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c +++ b/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c @@ -3069,8 +3069,7 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) for (i = 0; i < h265parse->time_code.num_clock_ts; i++) { gint field_count = -1; - guint64 n_frames_tmp; - guint n_frames = G_MAXUINT32; + guint64 n_frames = G_MAXUINT64; GstVideoTimeCodeFlags flags = 0; guint64 scale_n, scale_d; @@ -3146,30 +3145,37 @@ gst_h265_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) scale_n = (guint64) h265parse->parsed_fps_n * vui->num_units_in_tick; scale_d = (guint64) h265parse->parsed_fps_d * vui->time_scale; - n_frames_tmp = - gst_util_uint64_scale_int (h265parse->time_code.n_frames[i], scale_n, - scale_d); - if (n_frames_tmp <= G_MAXUINT32) { - if (h265parse->time_code.units_field_based_flag[i]) - n_frames_tmp *= 2; + if (h265parse->time_code.units_field_based_flag[i]) + scale_n *= 2; - if (n_frames_tmp <= G_MAXUINT32) - n_frames = (guint) n_frames_tmp; - } + n_frames = gst_util_uint64_scale (h265parse->time_code.n_frames[i], + scale_n, scale_d); + + if (n_frames <= G_MAXUINT32) { + GST_LOG_OBJECT (h265parse, + "Add time code meta %02u:%02u:%02u:%02u", + h265parse->time_code.hours_flag[i] ? + h265parse->time_code.hours_value[i] : 0, + h265parse->time_code.minutes_flag[i] ? + h265parse->time_code.minutes_value[i] : 0, + h265parse->time_code.seconds_flag[i] ? + h265parse->time_code.seconds_value[i] : 0, (guint) n_frames); - if (n_frames != G_MAXUINT32) { gst_buffer_add_video_time_code_meta_full (parse_buffer, h265parse->parsed_fps_n, h265parse->parsed_fps_d, NULL, flags, - h265parse->time_code.hours_flag[i] ? h265parse->time_code. - hours_value[i] : 0, - h265parse->time_code.minutes_flag[i] ? h265parse->time_code. - minutes_value[i] : 0, - h265parse->time_code.seconds_flag[i] ? h265parse->time_code. - seconds_value[i] : 0, n_frames, field_count); - } + h265parse->time_code.hours_flag[i] ? + h265parse->time_code.hours_value[i] : 0, + h265parse->time_code.minutes_flag[i] ? + h265parse->time_code.minutes_value[i] : 0, + h265parse->time_code.seconds_flag[i] ? + h265parse->time_code.seconds_value[i] : 0, + (guint) n_frames, field_count); + } else + GST_WARNING_OBJECT (h265parse, + "Skipping time code meta, n_frames calculation failed"); } }