qtmux: Fix timescale of timecode tracks
authorSebastian Dröge <sebastian@centricular.com>
Fri, 14 Apr 2017 10:38:53 +0000 (13:38 +0300)
committerSebastian Dröge <sebastian@centricular.com>
Fri, 14 Apr 2017 10:38:53 +0000 (13:38 +0300)
They should have ideally the same timescale of the video track, which we
can't guarantee here as in theory timecode configuration and video
framerate could be different. However we should set a correct timescale
based on the framerate given in the timecode configuration, and not just
use the framerate numerator.

gst/isomp4/atoms.c
gst/isomp4/atoms.h
gst/isomp4/gstqtmux.c

index af6eaeb..b19f018 100644 (file)
@@ -3779,6 +3779,23 @@ atom_trak_add_audio_entry (AtomTRAK * trak, AtomsContext * context,
   return mp4a;
 }
 
+/* return number of centiframes per second */
+guint
+atom_framerate_to_timescale (gint n, gint d)
+{
+  if (n == 0)
+    return 10000;
+
+  if (d != 1 && d != 1001) {
+    /* otherwise there are probably rounding errors and we should rather guess
+     * if it's close enough to a well known framerate */
+    gst_video_guess_framerate (gst_util_uint64_scale (d, GST_SECOND, n), &n,
+        &d);
+  }
+
+  return gst_util_uint64_scale (n, 100, d);
+}
+
 static SampleTableEntryTMCD *
 atom_trak_add_timecode_entry (AtomTRAK * trak, AtomsContext * context,
     GstVideoTimeCode * tc)
@@ -3790,7 +3807,8 @@ atom_trak_add_timecode_entry (AtomTRAK * trak, AtomsContext * context,
   trak->mdia.hdlr.handler_type = FOURCC_tmcd;
   g_free (trak->mdia.hdlr.name);
   trak->mdia.hdlr.name = g_strdup ("Time Code Media Handler");
-  trak->mdia.mdhd.time_info.timescale = tc->config.fps_n / tc->config.fps_d;
+  trak->mdia.mdhd.time_info.timescale =
+      atom_framerate_to_timescale (tc->config.fps_n, tc->config.fps_d);
 
   tmcd->se.kind = TIMECODE;
   tmcd->se.data_reference_index = 1;
@@ -3799,8 +3817,9 @@ atom_trak_add_timecode_entry (AtomTRAK * trak, AtomsContext * context,
     tmcd->tc_flags |= TC_DROP_FRAME;
   tmcd->name.language_code = 0;
   tmcd->name.name = g_strdup ("Tape");
-  tmcd->timescale = tc->config.fps_n;
-  tmcd->frame_duration = tc->config.fps_d;
+  tmcd->timescale =
+      atom_framerate_to_timescale (tc->config.fps_n, tc->config.fps_d);
+  tmcd->frame_duration = 100;
   if (tc->config.fps_d == 1001)
     tmcd->n_frames = tc->config.fps_n / 1000;
   else
index 949b790..c7a5d8b 100644 (file)
@@ -938,6 +938,8 @@ void       atom_moov_chunks_set_offset (AtomMOOV *moov, guint32 offset);
 void       atom_moov_add_trak          (AtomMOOV *moov, AtomTRAK *trak);
 guint      atom_moov_get_trak_count    (AtomMOOV *moov);
 
+guint      atom_framerate_to_timescale (gint fps_n, gint fps_d);
+
 guint64    atom_mvhd_copy_data         (AtomMVHD * atom, guint8 ** buffer,
                                         guint64 * size, guint64 * offset);
 void       atom_stco64_chunks_set_offset (AtomSTCO64 * stco64, guint32 offset);
index 9c3c4c9..761278c 100644 (file)
@@ -4049,23 +4049,6 @@ refuse_renegotiation:
   }
 }
 
-/* return number of centiframes per second */
-static guint
-adjust_rate (gint n, gint d)
-{
-  if (n == 0)
-    return 10000;
-
-  if (d != 1 && d != 1001) {
-    /* otherwise there are probably rounding errors and we should rather guess
-     * if it's close enough to a well known framerate */
-    gst_video_guess_framerate (gst_util_uint64_scale (d, GST_SECOND, n), &n,
-        &d);
-  }
-
-  return gst_util_uint64_scale (n, 100, d);
-}
-
 static gboolean
 gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
 {
@@ -4141,7 +4124,8 @@ gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
   /* bring frame numerator into a range that ensures both reasonable resolution
    * as well as a fair duration */
   rate = qtmux->trak_timescale ?
-      qtmux->trak_timescale : adjust_rate (framerate_num, framerate_den);
+      qtmux->trak_timescale : atom_framerate_to_timescale (framerate_num,
+      framerate_den);
   GST_DEBUG_OBJECT (qtmux, "Rate of video track selected: %" G_GUINT32_FORMAT,
       rate);