diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 2c4d3c338f..6f0760fa69 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -170,12 +170,8 @@ typedef struct MatroskaMuxContext {
  * offset, 4 bytes for target EBML ID */
 #define MAX_SEEKENTRY_SIZE 21
 
-/** per-cuepoint-track - 5 1-byte EBML IDs, 5 1-byte EBML sizes, 3 8-byte uint max
- * and one 1-byte uint for the track number (this assumes MAX_TRACKS to be <= 255) */
-#define MAX_CUETRACKPOS_SIZE 35
-
-/** per-cuepoint - 1 1-byte EBML ID, 1 1-byte EBML size, 8-byte uint max */
-#define MAX_CUEPOINT_CONTENT_SIZE(num_tracks) 10 + MAX_CUETRACKPOS_SIZE * num_tracks
+/** 4 * (1-byte EBML ID, 1-byte EBML size, 8-byte uint max) */
+#define MAX_CUETRACKPOS_SIZE 40
 
 /** Seek preroll value for opus */
 #define OPUS_SEEK_PREROLL 80000000
@@ -509,58 +505,54 @@ static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int tracknum, i
 static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tracks, int num_tracks)
 {
     MatroskaMuxContext *mkv = s->priv_data;
-    AVIOContext *dyn_cp, *pb = s->pb;
+    AVIOContext *dyn_cp, *pb = s->pb, *cuepoint;
     int64_t currentpos;
-    int i, j, ret;
+    int ret;
 
     currentpos = avio_tell(pb);
     ret = start_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CUES);
     if (ret < 0)
         return ret;
 
-    for (i = 0; i < cues->num_entries; i++) {
-        ebml_master cuepoint, track_positions;
-        mkv_cuepoint *entry = &cues->entries[i];
-        uint64_t pts = entry->pts;
-        int ctp_nb = 0;
-
-        // Calculate the number of entries, so we know the element size
-        for (j = 0; j < num_tracks; j++)
-            tracks[j].has_cue = 0;
-        for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) {
-            int idx = entry[j].stream_idx;
+    ret = avio_open_dyn_buf(&cuepoint);
+    if (ret < 0) {
+        ffio_free_dyn_buf(&dyn_cp);
+        return ret;
+    }
 
-            av_assert0(idx >= 0 && idx < num_tracks);
-            if (tracks[idx].has_cue && s->streams[idx]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
-                continue;
-            tracks[idx].has_cue = 1;
-            ctp_nb ++;
-        }
+    for (mkv_cuepoint *entry = cues->entries, *end = entry + cues->num_entries;
+         entry < end;) {
+        uint64_t pts = entry->pts;
+        uint8_t *buf;
+        int size;
 
-        cuepoint = start_ebml_master(dyn_cp, MATROSKA_ID_POINTENTRY, MAX_CUEPOINT_CONTENT_SIZE(ctp_nb));
-        put_ebml_uint(dyn_cp, MATROSKA_ID_CUETIME, pts);
+        put_ebml_uint(cuepoint, MATROSKA_ID_CUETIME, pts);
 
         // put all the entries from different tracks that have the exact same
         // timestamp into the same CuePoint
-        for (j = 0; j < num_tracks; j++)
+        for (int j = 0; j < num_tracks; j++)
             tracks[j].has_cue = 0;
-        for (j = 0; j < cues->num_entries - i && entry[j].pts == pts; j++) {
-            int idx = entry[j].stream_idx;
+        do {
+            ebml_master track_positions;
+            int idx = entry->stream_idx;
 
+            av_assert0(idx >= 0 && idx < num_tracks);
             if (tracks[idx].has_cue && s->streams[idx]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE)
                 continue;
             tracks[idx].has_cue = 1;
-            track_positions = start_ebml_master(dyn_cp, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE);
-            put_ebml_uint(dyn_cp, MATROSKA_ID_CUETRACK           , entry[j].tracknum   );
-            put_ebml_uint(dyn_cp, MATROSKA_ID_CUECLUSTERPOSITION , entry[j].cluster_pos);
-            put_ebml_uint(dyn_cp, MATROSKA_ID_CUERELATIVEPOSITION, entry[j].relative_pos);
-            if (entry[j].duration != -1)
-                put_ebml_uint(dyn_cp, MATROSKA_ID_CUEDURATION    , entry[j].duration);
-            end_ebml_master(dyn_cp, track_positions);
-        }
-        i += j - 1;
-        end_ebml_master(dyn_cp, cuepoint);
-    }
+            track_positions = start_ebml_master(cuepoint, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE);
+            put_ebml_uint(cuepoint, MATROSKA_ID_CUETRACK           , entry->tracknum   );
+            put_ebml_uint(cuepoint, MATROSKA_ID_CUECLUSTERPOSITION , entry->cluster_pos);
+            put_ebml_uint(cuepoint, MATROSKA_ID_CUERELATIVEPOSITION, entry->relative_pos);
+            if (entry->duration != -1)
+                put_ebml_uint(cuepoint, MATROSKA_ID_CUEDURATION    , entry->duration);
+            end_ebml_master(cuepoint, track_positions);
+        } while (++entry < end && entry->pts == pts);
+        size = avio_get_dyn_buf(cuepoint, &buf);
+        put_ebml_binary(dyn_cp, MATROSKA_ID_POINTENTRY, buf, size);
+        ffio_reset_dyn_buf(cuepoint);
+    }
+    ffio_free_dyn_buf(&cuepoint);
     end_ebml_master_crc32(pb, &dyn_cp, mkv);
 
     return currentpos;
