summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeungha Yang <sh.yang@lge.com>2016-01-26 22:37:30 +0900
committerSebastian Dröge <sebastian@centricular.com>2016-01-29 11:01:44 +0100
commit7873bede3134b15e5066e8d14e54d1f5054d2063 (patch)
tree578208281e4597e7602005921a8aa6f17122ce19
parent0391a93a3519c2ea4c375e9668b481c851e59d08 (diff)
downloadgstreamer-plugins-good-7873bede3134b15e5066e8d14e54d1f5054d2063.tar.gz
qtdemux: fix framerate calculation for fragmented format
qtdemux calculates framerate using duration and the number of sample. In case of fragmented mp4 format, however, the number of sample can be figure out after parsing every moof box. Because qtdemux does not parse every moof in QTDEMUX_STATE_HEADER state, it will cause incorrect framerate calculation. This patch will triger gst_qtdemux_configure_stream() for every new moof. Then, framerate will be calculated by using duration and n_samples of the moof. https://bugzilla.gnome.org/show_bug.cgi?id=760774
-rw-r--r--gst/isomp4/qtdemux.c45
1 files changed, 39 insertions, 6 deletions
diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c
index f0b368bf8..de5f5d559 100644
--- a/gst/isomp4/qtdemux.c
+++ b/gst/isomp4/qtdemux.c
@@ -253,6 +253,9 @@ struct _QtDemuxStream
gboolean all_keyframe; /* TRUE when all samples are keyframes (no stss) */
guint32 first_duration; /* duration in timescale of first sample, used for figuring out
the framerate, in timescale units */
+ guint32 n_samples_moof; /* sample count in a moof */
+ guint64 duration_moof; /* duration in timescale of a moof, used for figure out
+ * the framerate of fragmented format stream */
guint32 offset_in_sample;
guint32 max_buffer_size;
@@ -1817,6 +1820,8 @@ _create_stream (void)
stream->protection_scheme_type = 0;
stream->protection_scheme_version = 0;
stream->protection_scheme_info = NULL;
+ stream->n_samples_moof = 0;
+ stream->duration_moof = 0;
g_queue_init (&stream->protection_scheme_event_queue);
return stream;
}
@@ -2293,6 +2298,9 @@ gst_qtdemux_stream_flush_samples_data (GstQTDemux * qtdemux,
stream->stbl_index = -1;
stream->n_samples = 0;
stream->time_position = 0;
+
+ stream->n_samples_moof = 0;
+ stream->duration_moof = 0;
}
static void
@@ -2898,6 +2906,7 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
sample->keyframe = ismv ? ((sflags & 0xff) == 0x40) : !(sflags & 0x10000);
*running_offset += size;
timestamp += dur;
+ stream->duration_moof += dur;
sample++;
}
@@ -2905,6 +2914,7 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
check_update_duration (qtdemux, QTSTREAMTIME_TO_GSTTIME (stream, timestamp));
stream->n_samples += samples_count;
+ stream->n_samples_moof += samples_count;
if (stream->pending_seek != NULL)
stream->pending_seek = NULL;
@@ -3498,6 +3508,10 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
if (qtdemux->upstream_format_is_time)
gst_qtdemux_stream_flush_samples_data (qtdemux, stream);
+ /* initialise moof sample data */
+ stream->n_samples_moof = 0;
+ stream->duration_moof = 0;
+
/* Track Run node */
trun_node =
qtdemux_tree_get_child_by_type_full (traf_node, FOURCC_trun,
@@ -3514,6 +3528,10 @@ qtdemux_parse_moof (GstQTDemux * qtdemux, const guint8 * buffer, guint length,
* base is end of current traf */
base_offset = running_offset;
running_offset = -1;
+
+ if (stream->n_samples_moof && stream->duration_moof)
+ stream->new_caps = TRUE;
+
next:
/* iterate all siblings */
traf_node = qtdemux_tree_get_sibling_by_type (traf_node, FOURCC_traf);
@@ -6940,19 +6958,34 @@ gst_qtdemux_configure_stream (GstQTDemux * qtdemux, QtDemuxStream * stream)
stream->fps_n = stream->timescale;
stream->fps_d = 1;
} 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 */
- GstClockTime avg_duration =
- gst_util_uint64_scale_round (stream->duration -
+ avg_duration =
+ gst_util_uint64_scale_round (duration -
stream->first_duration, GST_SECOND,
- (guint64) (stream->timescale) * (stream->n_samples - 1));
+ (guint64) (stream->timescale) * (n_samples - 1));
GST_LOG_OBJECT (qtdemux,
- "Calculating avg sample duration based on stream duration %"
+ "Calculating avg sample duration based on stream (or moof) duration %"
G_GUINT64_FORMAT
" minus first sample %u, leaving %d samples gives %"
- GST_TIME_FORMAT, stream->duration, stream->first_duration,
- stream->n_samples - 1, GST_TIME_ARGS (avg_duration));
+ GST_TIME_FORMAT, duration, stream->first_duration,
+ n_samples - 1, GST_TIME_ARGS (avg_duration));
gst_video_guess_framerate (avg_duration, &stream->fps_n,
&stream->fps_d);