baseparse: Fix integer overflow in bitrate calculation
[platform/upstream/gstreamer.git] / libs / gst / base / gstbaseparse.c
index 4b45280..99283b8 100644 (file)
@@ -1084,7 +1084,8 @@ gst_base_parse_negotiate_default_caps (GstBaseParse * parse)
   GST_INFO_OBJECT (parse,
       "Chose default caps %" GST_PTR_FORMAT " for initial gap", default_caps);
 
-  gst_caps_unref (sinkcaps);
+  if (sinkcaps)
+    gst_caps_unref (sinkcaps);
   gst_caps_unref (caps);
 
   return default_caps;
@@ -1795,7 +1796,9 @@ static void
 gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame)
 {
   guint64 data_len, frame_dur;
-  gint overhead, frame_bitrate;
+  gint overhead;
+  guint frame_bitrate;
+  guint64 frame_bitrate64;
   GstBuffer *buffer = frame->buffer;
 
   overhead = frame->overhead;
@@ -1808,11 +1811,17 @@ gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame)
   /* duration should be valid by now,
    * either set by subclass or maybe based on fps settings */
   if (GST_BUFFER_DURATION_IS_VALID (buffer) && parse->priv->acc_duration != 0) {
+    guint64 avg_bitrate;
+
     /* Calculate duration of a frame from buffer properties */
     frame_dur = GST_BUFFER_DURATION (buffer);
-    parse->priv->avg_bitrate = (8 * parse->priv->data_bytecount * GST_SECOND) /
-        parse->priv->acc_duration;
+    avg_bitrate = gst_util_uint64_scale (GST_SECOND,
+        8 * parse->priv->data_bytecount, parse->priv->acc_duration);
+
+    if (avg_bitrate > G_MAXUINT)
+      return;
 
+    parse->priv->avg_bitrate = avg_bitrate;
   } else {
     /* No way to figure out frame duration (is this even possible?) */
     return;
@@ -1822,15 +1831,21 @@ gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame)
   if (parse->priv->bitrate) {
     parse->priv->avg_bitrate = parse->priv->bitrate;
     /* spread this (confirmed) info ASAP */
-    if (parse->priv->posted_avg_bitrate != parse->priv->avg_bitrate)
+    if (parse->priv->post_avg_bitrate &&
+        parse->priv->posted_avg_bitrate != parse->priv->avg_bitrate)
       parse->priv->tags_changed = TRUE;
   }
 
-  if (frame_dur)
-    frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur;
-  else
+  if (!frame_dur)
     return;
 
+  frame_bitrate64 = gst_util_uint64_scale (GST_SECOND, 8 * data_len, frame_dur);
+
+  if (frame_bitrate64 > G_MAXUINT)
+    return;
+
+  frame_bitrate = (guint) frame_bitrate64;
+
   GST_LOG_OBJECT (parse, "frame bitrate %u, avg bitrate %u", frame_bitrate,
       parse->priv->avg_bitrate);
 
@@ -3858,7 +3873,11 @@ gst_base_parse_set_frame_rate (GstBaseParse * parse, guint fps_num,
         gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num);
     /* aim for about 1.5s to estimate duration */
     if (parse->priv->update_interval < 0) {
-      parse->priv->update_interval = fps_num * 3 / (fps_den * 2);
+      guint64 interval = gst_util_uint64_scale (fps_num, 3,
+          G_GUINT64_CONSTANT (2) * fps_den);
+
+      parse->priv->update_interval = MIN (interval, G_MAXINT);
+
       GST_LOG_OBJECT (parse, "estimated update interval to %d frames",
           parse->priv->update_interval);
     }
@@ -4103,8 +4122,8 @@ gst_base_parse_src_query_default (GstBaseParse * parse, GstQuery * query)
           if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &duration)
               || duration == -1) {
             /* seekable if we still have a chance to get duration later on */
-            seekable =
-                parse->priv->upstream_seekable && parse->priv->update_interval;
+            seekable = parse->priv->upstream_seekable &&
+                (parse->priv->update_interval > 0);
           } else {
             seekable = parse->priv->upstream_seekable;
             GST_LOG_OBJECT (parse, "already determine upstream seekabled: %d",