From c50be8f146b7883b0f900c57468e152cb64f6ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 5 Dec 2018 19:37:13 +0200 Subject: [PATCH] qtdemux: Put framerate into the closedcaption caps if it can be calculated from the stream Using the same calculation used for video streams. --- gst/isomp4/qtdemux.c | 138 +++++++++++++++++++++++++------------------ 1 file changed, 81 insertions(+), 57 deletions(-) diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c index a58557a5f2..105bda133d 100644 --- a/gst/isomp4/qtdemux.c +++ b/gst/isomp4/qtdemux.c @@ -8329,67 +8329,75 @@ gst_qtdemux_configure_protected_caps (GstQTDemux * qtdemux, return TRUE; } +static gboolean +gst_qtdemux_guess_framerate (GstQTDemux * qtdemux, QtDemuxStream * stream) +{ + /* fps is calculated base on the duration of the average framerate since + * qt does not have a fixed framerate. */ + gboolean fps_available = TRUE; + guint32 first_duration = 0; + + if (stream->n_samples > 0) + first_duration = stream->samples[0].duration; + + if ((stream->n_samples == 1 && first_duration == 0) + || (qtdemux->fragmented && stream->n_samples_moof == 1)) { + /* still frame */ + CUR_STREAM (stream)->fps_n = 0; + CUR_STREAM (stream)->fps_d = 1; + } else { + if (stream->duration == 0 || stream->n_samples < 2) { + CUR_STREAM (stream)->fps_n = stream->timescale; + CUR_STREAM (stream)->fps_d = 1; + fps_available = FALSE; + } else { + GstClockTime avg_duration; + guint64 duration; + guint32 n_samples; + + /* duration and n_samples can be updated for fragmented format + * so, framerate of fragmented format is calculated using data in a moof */ + if (qtdemux->fragmented && stream->n_samples_moof > 0 + && stream->duration_moof > 0) { + n_samples = stream->n_samples_moof; + duration = stream->duration_moof; + } else { + n_samples = stream->n_samples; + duration = stream->duration; + } + + /* Calculate a framerate, ignoring the first sample which is sometimes truncated */ + /* stream->duration is guint64, timescale, n_samples are guint32 */ + avg_duration = + gst_util_uint64_scale_round (duration - + first_duration, GST_SECOND, + (guint64) (stream->timescale) * (n_samples - 1)); + + GST_LOG_OBJECT (qtdemux, + "Calculating avg sample duration based on stream (or moof) duration %" + G_GUINT64_FORMAT + " minus first sample %u, leaving %d samples gives %" + GST_TIME_FORMAT, duration, first_duration, + n_samples - 1, GST_TIME_ARGS (avg_duration)); + + gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n, + &CUR_STREAM (stream)->fps_d); + + GST_DEBUG_OBJECT (qtdemux, + "Calculating framerate, timescale %u gave fps_n %d fps_d %d", + stream->timescale, CUR_STREAM (stream)->fps_n, + CUR_STREAM (stream)->fps_d); + } + } + + return fps_available; +} + static gboolean gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream) { if (stream->subtype == FOURCC_vide) { - /* fps is calculated base on the duration of the average framerate since - * qt does not have a fixed framerate. */ - gboolean fps_available = TRUE; - guint32 first_duration = 0; - - if (stream->n_samples > 0) - first_duration = stream->samples[0].duration; - - if ((stream->n_samples == 1 && first_duration == 0) - || (qtdemux->fragmented && stream->n_samples_moof == 1)) { - /* still frame */ - CUR_STREAM (stream)->fps_n = 0; - CUR_STREAM (stream)->fps_d = 1; - } else { - if (stream->duration == 0 || stream->n_samples < 2) { - CUR_STREAM (stream)->fps_n = stream->timescale; - CUR_STREAM (stream)->fps_d = 1; - fps_available = FALSE; - } else { - GstClockTime avg_duration; - guint64 duration; - guint32 n_samples; - - /* duration and n_samples can be updated for fragmented format - * so, framerate of fragmented format is calculated using data in a moof */ - if (qtdemux->fragmented && stream->n_samples_moof > 0 - && stream->duration_moof > 0) { - n_samples = stream->n_samples_moof; - duration = stream->duration_moof; - } else { - n_samples = stream->n_samples; - duration = stream->duration; - } - - /* Calculate a framerate, ignoring the first sample which is sometimes truncated */ - /* stream->duration is guint64, timescale, n_samples are guint32 */ - avg_duration = - gst_util_uint64_scale_round (duration - - first_duration, GST_SECOND, - (guint64) (stream->timescale) * (n_samples - 1)); - - GST_LOG_OBJECT (qtdemux, - "Calculating avg sample duration based on stream (or moof) duration %" - G_GUINT64_FORMAT - " minus first sample %u, leaving %d samples gives %" - GST_TIME_FORMAT, duration, first_duration, - n_samples - 1, GST_TIME_ARGS (avg_duration)); - - gst_video_guess_framerate (avg_duration, &CUR_STREAM (stream)->fps_n, - &CUR_STREAM (stream)->fps_d); - - GST_DEBUG_OBJECT (qtdemux, - "Calculating framerate, timescale %u gave fps_n %d fps_d %d", - stream->timescale, CUR_STREAM (stream)->fps_n, - CUR_STREAM (stream)->fps_d); - } - } + gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream); if (CUR_STREAM (stream)->caps) { CUR_STREAM (stream)->caps = @@ -8509,6 +8517,22 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream) } } + else if (stream->subtype == FOURCC_clcp) { + gboolean fps_available = gst_qtdemux_guess_framerate (qtdemux, stream); + + if (CUR_STREAM (stream)->caps) { + CUR_STREAM (stream)->caps = + gst_caps_make_writable (CUR_STREAM (stream)->caps); + + /* set framerate if calculated framerate is reliable */ + if (fps_available) { + gst_caps_set_simple (CUR_STREAM (stream)->caps, + "framerate", GST_TYPE_FRACTION, CUR_STREAM (stream)->fps_n, + CUR_STREAM (stream)->fps_d, NULL); + } + } + } + if (stream->pad) { GstCaps *prev_caps = NULL;