mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-29 23:32:33 +00:00
video: Add gst_video_guess_framerate() function
Takes a nominal frame duration and returns a standard FPS if it matches closely enough (< 0.1%), or else calculates a framerate that'll do.
This commit is contained in:
parent
2a37534129
commit
c98f051548
3 changed files with 93 additions and 0 deletions
|
@ -2202,6 +2202,7 @@ GstEncodingTargetClass
|
||||||
#video.h
|
#video.h
|
||||||
<SUBSECTION>
|
<SUBSECTION>
|
||||||
gst_video_calculate_display_ratio
|
gst_video_calculate_display_ratio
|
||||||
|
gst_video_guess_framerate
|
||||||
GstVideoConvertSampleCallback
|
GstVideoConvertSampleCallback
|
||||||
gst_video_convert_sample
|
gst_video_convert_sample
|
||||||
gst_video_convert_sample_async
|
gst_video_convert_sample_async
|
||||||
|
|
|
@ -98,6 +98,95 @@ error_overflow:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_video_guess_framerate:
|
||||||
|
* @duration: Nominal duration of one frame
|
||||||
|
* @dest_n: (out) (allow-none): Numerator of the calculated framerate
|
||||||
|
* @dest_d: (out) (allow-none): Denominator of the calculated framerate
|
||||||
|
*
|
||||||
|
* Given the nominal duration of one video frame,
|
||||||
|
* this function will check some standard framerates for
|
||||||
|
* a close match (within 0.1%) and return one if possible,
|
||||||
|
*
|
||||||
|
* It will calculate an arbitrary framerate if no close
|
||||||
|
* match was found, and return %FALSE.
|
||||||
|
*
|
||||||
|
* It returns %FALSE if a duration of 0 is passed.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if a close "standard" framerate was
|
||||||
|
* recognised, and %FALSE otherwise.
|
||||||
|
*
|
||||||
|
* Since: 1.6
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_video_guess_framerate (GstClockTime duration, gint * dest_n, gint * dest_d)
|
||||||
|
{
|
||||||
|
const int common_den[] = { 1, 2, 3, 4, 1001 };
|
||||||
|
int best_n, best_d, gcd;
|
||||||
|
guint64 best_error = G_MAXUINT64;
|
||||||
|
guint64 a;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (duration == 0))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Use a limited precision conversion by default for more sensible results,
|
||||||
|
* unless the frame duration is absurdly small (high speed cameras?) */
|
||||||
|
if (duration > 100000) {
|
||||||
|
best_n = 10000;
|
||||||
|
best_d = duration / 100000;
|
||||||
|
} else {
|
||||||
|
best_n = GST_SECOND;
|
||||||
|
best_d = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (common_den); i++) {
|
||||||
|
gint d = common_den[i];
|
||||||
|
gint n = gst_util_uint64_scale_round (d, GST_SECOND, duration);
|
||||||
|
|
||||||
|
/* For NTSC framerates, round to the nearest 1000 fps */
|
||||||
|
if (d == 1001) {
|
||||||
|
n += 500;
|
||||||
|
n -= (n % 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > 0) {
|
||||||
|
/* See what duration the given framerate should be */
|
||||||
|
a = gst_util_uint64_scale_int (GST_SECOND, d, n);
|
||||||
|
/* Compute absolute error */
|
||||||
|
a = (a < duration) ? (duration - a) : (a - duration);
|
||||||
|
if (a < 2) {
|
||||||
|
/* Really precise - take this option */
|
||||||
|
if (dest_n)
|
||||||
|
*dest_n = n;
|
||||||
|
if (dest_d)
|
||||||
|
*dest_d = d;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/* If within 0.1%, remember this denominator */
|
||||||
|
if (a * 1000 < duration && a < best_error) {
|
||||||
|
best_error = a;
|
||||||
|
best_n = n;
|
||||||
|
best_d = d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set results */
|
||||||
|
gcd = gst_util_greatest_common_divisor (best_n, best_d);
|
||||||
|
if (gcd) {
|
||||||
|
best_n /= gcd;
|
||||||
|
best_d /= gcd;
|
||||||
|
}
|
||||||
|
if (dest_n)
|
||||||
|
*dest_n = best_n;
|
||||||
|
if (dest_d)
|
||||||
|
*dest_d = best_d;
|
||||||
|
|
||||||
|
return (best_error != G_MAXUINT64);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_video_alignment_reset:
|
* gst_video_alignment_reset:
|
||||||
* @align: a #GstVideoAlignment
|
* @align: a #GstVideoAlignment
|
||||||
|
|
|
@ -100,6 +100,9 @@ gboolean gst_video_calculate_display_ratio (guint * dar_n,
|
||||||
guint display_par_n,
|
guint display_par_n,
|
||||||
guint display_par_d);
|
guint display_par_d);
|
||||||
|
|
||||||
|
gboolean gst_video_guess_framerate (GstClockTime duration,
|
||||||
|
gint * dest_n, gint * dest_d);
|
||||||
|
|
||||||
/* convert/encode video sample from one format to another */
|
/* convert/encode video sample from one format to another */
|
||||||
|
|
||||||
typedef void (*GstVideoConvertSampleCallback) (GstSample * sample, GError *error, gpointer user_data);
|
typedef void (*GstVideoConvertSampleCallback) (GstSample * sample, GError *error, gpointer user_data);
|
||||||
|
|
Loading…
Reference in a new issue