diff --git a/libavformat/avc.c b/libavformat/avc.c
index c106fe5792..0f43b295a4 100644
--- a/libavformat/avc.c
+++ b/libavformat/avc.c
@@ -167,13 +167,32 @@ int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size)
     return 0;
 }
 
+static void write_array(AVIOContext *pb, const uint8_t *const *ps,
+                        const uint16_t *const ps_sizes,
+                        int nb_ps, int array_size, uint8_t reserved)
+{
+    avio_w8(pb, reserved | nb_ps);
+    for (int i = 0; i < array_size; i++) {
+        if (ps_sizes[i]) {
+            avio_wb16(pb, ps_sizes[i]);
+            avio_write(pb, ps[i], ps_sizes[i]);
+            nb_ps--;
+        }
+    }
+    av_assert1(nb_ps == 0);
+}
+
 int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
 {
-    AVIOContext *sps_pb = NULL, *pps_pb = NULL, *sps_ext_pb = NULL;
     const uint8_t *nal, *nal_end, *end;
-    uint8_t *sps, *pps, *sps_ext;
-    uint32_t sps_size = 0, pps_size = 0, sps_ext_size = 0;
     int ret, nb_sps = 0, nb_pps = 0, nb_sps_ext = 0;
+    const uint8_t *sps[H264_MAX_SPS_COUNT];
+    const uint8_t *pps[H264_MAX_PPS_COUNT];
+    const uint8_t *sps_ext[H264_MAX_SPS_COUNT];
+    uint16_t sps_sizes[H264_MAX_SPS_COUNT]     = { 0 };
+    uint16_t pps_sizes[H264_MAX_PPS_COUNT]     = { 0 };
+    uint16_t sps_ext_sizes[H264_MAX_SPS_COUNT] = { 0 };
+    H264SPS seq;
 
     if (len <= 6)
         return AVERROR_INVALIDDATA;
@@ -185,16 +204,6 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
         return 0;
     }
 
-    ret = avio_open_dyn_buf(&sps_pb);
-    if (ret < 0)
-        goto fail;
-    ret = avio_open_dyn_buf(&pps_pb);
-    if (ret < 0)
-        goto fail;
-    ret = avio_open_dyn_buf(&sps_ext_pb);
-    if (ret < 0)
-        goto fail;
-
     /* look for sps and pps */
     nal_end = NULL;
     end     = data + len;
@@ -203,71 +212,63 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len)
         uint8_t nal_type = nal[0] & 0x1f;
 
         if (nal_type == 7) { /* SPS */
-            nb_sps++;
-            if (size > UINT16_MAX || nb_sps >= H264_MAX_SPS_COUNT) {
-                ret = AVERROR_INVALIDDATA;
-                goto fail;
-            }
-            avio_wb16(sps_pb, size);
-            avio_write(sps_pb, nal, size);
-        } else if (nal_type == 8) { /* PPS */
-            nb_pps++;
-            if (size > UINT16_MAX || nb_pps >= H264_MAX_PPS_COUNT) {
-                ret = AVERROR_INVALIDDATA;
-                goto fail;
-            }
-            avio_wb16(pps_pb, size);
-            avio_write(pps_pb, nal, size);
-        } else if (nal_type == 13) { /* SPS_EXT */
-            nb_sps_ext++;
-            if (size > UINT16_MAX || nb_sps_ext >= 256) {
-                ret = AVERROR_INVALIDDATA;
-                goto fail;
+            if (size > UINT16_MAX)
+                return AVERROR_INVALIDDATA;
+            ret = ff_avc_decode_sps(&seq, nal + 1, size - 1);
+            if (ret < 0)
+                return ret;
+            nb_sps           += 1 - !!sps_sizes[seq.id];
+            sps[seq.id]       = nal;
+            sps_sizes[seq.id] = size;
+        } else if (nal_type == H264_NAL_PPS || nal_type == H264_NAL_SPS_EXT) {
+            GetBitContext gb;
+            unsigned id;
+            if (size > UINT16_MAX)
+                return AVERROR_INVALIDDATA;
+            /* No need to unescape here */
+            ret = init_get_bits8(&gb, nal + 1, size - 1);
+            av_assert1(ret >= 0);
+            ret = get_ue_golomb(&gb, &id);
+            if (ret < 0)
+                return ret;
+            if (nal_type == H264_NAL_PPS) {
+                if (id >= H264_MAX_PPS_COUNT)
+                    return AVERROR_INVALIDDATA;
+                nb_pps       += 1 - !!pps_sizes[id];
+                pps[id]       = nal;
+                pps_sizes[id] = size;
+            } else {
+                if (id >= H264_MAX_SPS_COUNT)
+                    return AVERROR_INVALIDDATA;
+                if (!sps_sizes[id])
+                    continue;
+                nb_sps_ext       += 1 - !!sps_ext_sizes[id];
+                sps_ext[id]       = nal;
+                sps_ext_sizes[id] = size;
             }
-            avio_wb16(sps_ext_pb, size);
-            avio_write(sps_ext_pb, nal, size);
         }
     }
-    sps_size = avio_get_dyn_buf(sps_pb, &sps);
-    pps_size = avio_get_dyn_buf(pps_pb, &pps);
-    sps_ext_size = avio_get_dyn_buf(sps_ext_pb, &sps_ext);
 
-    if (sps_size < 6 || !pps_size) {
-        ret = AVERROR_INVALIDDATA;
-        goto fail;
-    }
+    if (!nb_sps || nb_sps == H264_MAX_SPS_COUNT ||
+        !nb_pps || nb_pps == H264_MAX_PPS_COUNT)
+        return AVERROR_INVALIDDATA;
 
     avio_w8(pb, 1); /* version */
-    avio_w8(pb, sps[3]); /* profile */
-    avio_w8(pb, sps[4]); /* profile compat */
-    avio_w8(pb, sps[5]); /* level */
+    avio_w8(pb, seq.profile_idc);
+    avio_w8(pb, seq.constraint_set_flags); /* profile compat */
+    avio_w8(pb, seq.level_idc);
     avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
-    avio_w8(pb, 0xe0 | nb_sps); /* 3 bits reserved (111) + 5 bits number of sps */
-
-    avio_write(pb, sps, sps_size);
-    avio_w8(pb, nb_pps); /* number of pps */
-    avio_write(pb, pps, pps_size);
-
-    if (sps[3] != 66 && sps[3] != 77 && sps[3] != 88) {
-        H264SPS seq;
-        ret = ff_avc_decode_sps(&seq, sps + 3, sps_size - 3);
-        if (ret < 0)
-            goto fail;
+    write_array(pb, sps, sps_sizes, nb_sps, H264_MAX_SPS_COUNT, 0xe0);
+    write_array(pb, pps, pps_sizes, nb_pps, H264_MAX_PPS_COUNT, 0x00);
 
+    if (seq.profile_idc != 66 && seq.profile_idc != 77 && seq.profile_idc != 88) {
         avio_w8(pb, 0xfc |  seq.chroma_format_idc); /* 6 bits reserved (111111) + chroma_format_idc */
         avio_w8(pb, 0xf8 | seq.bit_depth_luma_minus8); /* 5 bits reserved (11111) + bit_depth_luma_minus8 */
         avio_w8(pb, 0xf8 | seq.bit_depth_chroma_minus8); /* 5 bits reserved (11111) + bit_depth_chroma_minus8 */
-        avio_w8(pb, nb_sps_ext); /* number of sps ext */
-        if (nb_sps_ext)
-            avio_write(pb, sps_ext, sps_ext_size);
+        write_array(pb, sps_ext, sps_ext_sizes, nb_sps_ext, H264_MAX_SPS_COUNT, 0);
     }
 
-fail:
-    ffio_free_dyn_buf(&sps_pb);
-    ffio_free_dyn_buf(&pps_pb);
-    ffio_free_dyn_buf(&sps_ext_pb);
-
-    return ret;
+    return 0;
 }
 
 int ff_avc_write_annexb_extradata(const uint8_t *in, uint8_t **buf, int *size)
