mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 14:08:56 +00:00
av1parse: calculate framerate from AV1 timing info
When framerate info isn't provided by upstream elements, try to extract it from AV1 timing info, if present. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5041>
This commit is contained in:
parent
dfe67ba7c6
commit
f7b719ae91
1 changed files with 58 additions and 8 deletions
|
@ -110,6 +110,11 @@ struct _GstAV1Parse
|
||||||
gchar *colorimetry;
|
gchar *colorimetry;
|
||||||
GstAV1Profile profile;
|
GstAV1Profile profile;
|
||||||
|
|
||||||
|
gint fps_n;
|
||||||
|
gint fps_d;
|
||||||
|
/* incaps framerate overwrites the AV1 time info */
|
||||||
|
gboolean has_input_fps;
|
||||||
|
|
||||||
GstAV1ParseAligment in_align;
|
GstAV1ParseAligment in_align;
|
||||||
gboolean detect_annex_b;
|
gboolean detect_annex_b;
|
||||||
GstAV1ParseAligment align;
|
GstAV1ParseAligment align;
|
||||||
|
@ -641,7 +646,6 @@ gst_av1_parse_update_src_caps (GstAV1Parse * self, GstCaps * caps)
|
||||||
GstStructure *s = NULL;
|
GstStructure *s = NULL;
|
||||||
gint width, height;
|
gint width, height;
|
||||||
gint par_n = 0, par_d = 0;
|
gint par_n = 0, par_d = 0;
|
||||||
gint fps_n = 0, fps_d = 0;
|
|
||||||
const gchar *profile = NULL;
|
const gchar *profile = NULL;
|
||||||
|
|
||||||
if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (self))))
|
if (G_UNLIKELY (!gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (self))))
|
||||||
|
@ -685,14 +689,11 @@ gst_av1_parse_update_src_caps (GstAV1Parse * self, GstCaps * caps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s && gst_structure_has_field (s, "framerate")) {
|
if (self->fps_n > 0 && self->fps_d > 0) {
|
||||||
gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fps_n > 0 && fps_d > 0) {
|
|
||||||
gst_caps_set_simple (final_caps, "framerate",
|
gst_caps_set_simple (final_caps, "framerate",
|
||||||
GST_TYPE_FRACTION, fps_n, fps_d, NULL);
|
GST_TYPE_FRACTION, self->fps_n, self->fps_d, NULL);
|
||||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE (self), fps_n, fps_d, 0, 0);
|
gst_base_parse_set_frame_rate (GST_BASE_PARSE (self),
|
||||||
|
self->fps_n, self->fps_d, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When not RGB, the chroma format is needed. */
|
/* When not RGB, the chroma format is needed. */
|
||||||
|
@ -878,6 +879,15 @@ gst_av1_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps)
|
||||||
if (profile)
|
if (profile)
|
||||||
self->profile = gst_av1_parse_profile_from_string (profile);
|
self->profile = gst_av1_parse_profile_from_string (profile);
|
||||||
|
|
||||||
|
if (gst_structure_has_field (str, "framerate")) {
|
||||||
|
gst_structure_get_fraction (str, "framerate", &self->fps_n, &self->fps_d);
|
||||||
|
self->has_input_fps = TRUE;
|
||||||
|
} else {
|
||||||
|
self->fps_n = 0;
|
||||||
|
self->fps_d = 1;
|
||||||
|
self->has_input_fps = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* get upstream align from caps */
|
/* get upstream align from caps */
|
||||||
align = gst_av1_parse_alignment_from_caps (caps);
|
align = gst_av1_parse_alignment_from_caps (caps);
|
||||||
if (align == GST_AV1_PARSE_ALIGN_ERROR) {
|
if (align == GST_AV1_PARSE_ALIGN_ERROR) {
|
||||||
|
@ -1195,6 +1205,34 @@ gst_av1_parse_cache_one_obu (GstAV1Parse * self, GstBuffer * buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_av1_parse_calculate_framerate (GstAV1TimingInfo * ti,
|
||||||
|
gint * fps_n, gint * fps_d)
|
||||||
|
{
|
||||||
|
/* To calculate framerate, we use this formula:
|
||||||
|
*
|
||||||
|
* time_scale 1
|
||||||
|
* fps = ------------------------- x ---------------------------------
|
||||||
|
* num_units_in_display_tick num_ticks_per_picture_minus_1 + 1
|
||||||
|
*/
|
||||||
|
if (ti->equal_picture_interval) {
|
||||||
|
gint gcd;
|
||||||
|
|
||||||
|
*fps_n = ti->time_scale;
|
||||||
|
*fps_d = ti->num_units_in_display_tick *
|
||||||
|
(ti->num_ticks_per_picture_minus_1 + 1);
|
||||||
|
|
||||||
|
gcd = gst_util_greatest_common_divisor (*fps_n, *fps_d);
|
||||||
|
if (gcd) {
|
||||||
|
*fps_n /= gcd;
|
||||||
|
*fps_d /= gcd;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*fps_n = 0;
|
||||||
|
*fps_d = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstAV1ParserResult
|
static GstAV1ParserResult
|
||||||
gst_av1_parse_handle_sequence_obu (GstAV1Parse * self, GstAV1OBU * obu)
|
gst_av1_parse_handle_sequence_obu (GstAV1Parse * self, GstAV1OBU * obu)
|
||||||
{
|
{
|
||||||
|
@ -1270,6 +1308,18 @@ gst_av1_parse_handle_sequence_obu (GstAV1Parse * self, GstAV1OBU * obu)
|
||||||
self->update_caps = TRUE;
|
self->update_caps = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!self->has_input_fps) {
|
||||||
|
gint fps_n, fps_d;
|
||||||
|
|
||||||
|
gst_av1_parse_calculate_framerate (&seq_header.timing_info, &fps_n, &fps_d);
|
||||||
|
|
||||||
|
if (self->fps_n != fps_n || self->fps_d != fps_d) {
|
||||||
|
self->fps_n = fps_n;
|
||||||
|
self->fps_d = fps_d;
|
||||||
|
self->update_caps = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val = (self->parser->state.operating_point_idc >> 8) & 0x0f;
|
val = (self->parser->state.operating_point_idc >> 8) & 0x0f;
|
||||||
for (i = 0; i < (1 << GST_AV1_MAX_SPATIAL_LAYERS); i++) {
|
for (i = 0; i < (1 << GST_AV1_MAX_SPATIAL_LAYERS); i++) {
|
||||||
if (val & (1 << i))
|
if (val & (1 << i))
|
||||||
|
|
Loading…
Reference in a new issue