videotimecode: Add missing 119.88fps support to some functions

And while at it generalize the drop frame handling to all integer multiples
of 30000/1001 fps.

Also adjust tests accordingly and add some other missing test.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8649>
This commit is contained in:
Sebastian Dröge 2025-03-15 12:07:22 +02:00
parent 18798440e3
commit c2be97d591
2 changed files with 19 additions and 32 deletions

View File

@ -98,16 +98,15 @@ gst_video_time_code_is_valid (const GstVideoTimeCode * tc)
/* We need either a specific X/1001 framerate, or less than 1 FPS,
* otherwise an integer framerate. */
if (tc->config.fps_d == 1001) {
if (tc->config.fps_n != 30000 && tc->config.fps_n != 60000 &&
tc->config.fps_n != 24000 && tc->config.fps_n != 120000)
if (tc->config.fps_n % 30000 != 0 && tc->config.fps_n != 24000)
return FALSE;
} else if (tc->config.fps_n >= tc->config.fps_d
&& tc->config.fps_n % tc->config.fps_d != 0) {
return FALSE;
}
/* We support only 30000/1001, 60000/1001, and 120000/1001 (see above) as
* drop-frame framerates. 24000/1001 is *not* a drop-frame framerate! */
/* We support only multiples of 30000/1001 (see above) as drop-frame
* framerates. 24000/1001 is *not* a drop-frame framerate! */
if (tc->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) {
if (tc->config.fps_d != 1001 || tc->config.fps_n == 24000)
return FALSE;
@ -116,7 +115,7 @@ gst_video_time_code_is_valid (const GstVideoTimeCode * tc)
/* Drop-frame framerates require skipping over the first two
* timecodes every minute except for every tenth minute in case
* of 30000/1001, the first four timecodes for 60000/1001,
* and the first eight timecodes for 120000/1001. */
* and the first eight timecodes for 120000/1001, etc. */
if ((tc->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) &&
tc->minutes % 10 && tc->seconds == 0 && tc->frames < fr / 15) {
return FALSE;
@ -385,22 +384,16 @@ gst_video_time_code_frames_since_daily_jam (const GstVideoTimeCode * tc)
ff_nom = ff;
}
if (tc->config.flags & GST_VIDEO_TIME_CODE_FLAGS_DROP_FRAME) {
/* these need to be truncated to integer: side effect, code looks cleaner
* */
/* these need to be truncated to integer: side effect, code looks cleaner */
guint ff_minutes = 60 * ff;
guint ff_hours = 3600 * ff;
/* for 30000/1001 we drop the first 2 frames per minute, for 60000/1001 we
* drop the first 4 : so we use this number */
/* for 30000/1001 we drop the first 2 timecodes per minute, for 60000/1001
* the first 4, etc. except for every 10th minute */
guint dropframe_multiplier;
if (tc->config.fps_n == 30000) {
dropframe_multiplier = 2;
} else if (tc->config.fps_n == 60000) {
dropframe_multiplier = 4;
} else {
/* already checked by gst_video_time_code_is_valid() */
g_assert_not_reached ();
}
/* already checked by gst_video_time_code_is_valid() */
g_assert (tc->config.fps_n % 30000 == 0);
dropframe_multiplier = 2 * (tc->config.fps_n / 30000);
return tc->frames + (ff_nom * tc->seconds) +
(ff_minutes * tc->minutes) +
@ -471,18 +464,13 @@ gst_video_time_code_add_frames (GstVideoTimeCode * tc, gint64 frames)
/* a bunch of intermediate variables, to avoid monster code with possible
* integer overflows */
guint64 min_new_tmp1, min_new_tmp2, min_new_tmp3, min_new_denom;
/* for 30000/1001 we drop the first 2 frames per minute, for 60000/1001 we
* drop the first 4 : so we use this number */
/* for 30000/1001 we drop the first 2 timecodes per minute, for 60000/1001
* the first 4, etc. except for every 10th minute */
guint dropframe_multiplier;
if (tc->config.fps_n == 30000) {
dropframe_multiplier = 2;
} else if (tc->config.fps_n == 60000) {
dropframe_multiplier = 4;
} else {
/* already checked by gst_video_time_code_is_valid() */
g_assert_not_reached ();
}
/* already checked by gst_video_time_code_is_valid() */
g_assert (tc->config.fps_n % 30000 == 0);
dropframe_multiplier = 2 * (tc->config.fps_n / 30000);
framecount =
frames + tc->frames + (ff_nom * tc->seconds) +

View File

@ -664,16 +664,16 @@ GST_START_TEST (videotimecode_validation)
/* disallowed unknown frame rate */
CHECK_TC (0, 1, FALSE, 0, 0, 0, 0, FALSE);
/* disallowed fractional frame rate */
CHECK_TC (90000, 1001, FALSE, 0, 0, 0, 0, FALSE);
CHECK_TC (50000, 1001, FALSE, 0, 0, 0, 0, FALSE);
/* allowed fractional frame rate */
CHECK_TC (24000, 1001, FALSE, 0, 0, 0, 0, TRUE);
/* allowed frame rate less than 1 FPS */
CHECK_TC (900, 1000, FALSE, 0, 0, 0, 0, TRUE);
CHECK_TC (1, 4, FALSE, 0, 0, 0, 0, TRUE);
CHECK_TC (1, 4, FALSE, 0, 0, 2, 0, FALSE);
CHECK_TC (1, 4, FALSE, 0, 0, 4, 0, TRUE);
/* allowed integer frame rate */
CHECK_TC (9000, 100, FALSE, 0, 0, 0, 0, TRUE);
/* TODO: CHECK_TC (60060, 1001, FALSE, 0, 0, 0, 0, TRUE);
* https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2823
*/
/* 'hours' >= 24 */
CHECK_TC (60, 1, FALSE, 28, 1, 2, 3, FALSE);
@ -683,7 +683,6 @@ GST_START_TEST (videotimecode_validation)
CHECK_TC (25, 1, FALSE, 0, 1, 234, 5, FALSE);
/* 'frames' >= FPS */
CHECK_TC (24, 1, FALSE, 0, 1, 2, 34, FALSE);
/* TODO Add tests for dis-/allowed 'seconds' when FPS<1.0 */
/* 23.976 is not a drop-frame frame rate */
CHECK_TC (24000, 1001, TRUE, 0, 0, 0, 11, FALSE);