diff mbox series

[FFmpeg-devel,17/25] avformat/matroskaenc: Avoid temporary buffers when reformatting H.2645

Message ID AM7PR03MB66601340699BD3D6DC065A008F569@AM7PR03MB6660.eurprd03.prod.outlook.com
State Accepted
Commit d328467dd3007116dcc41aba7af0f560a022b456
Headers show
Series [FFmpeg-devel,01/25] avformat/matroskaenc: Fix potential overflow | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_aarch64_jetson success Make finished
andriy/make_fate_aarch64_jetson success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

Andreas Rheinhardt Jan. 16, 2022, 11:03 p.m. UTC
Do this by using the new NALUList API. This avoids an allocation
of a dynamic buffer per packet as well as the (re)allocation
of the actual buffer as well as copying the data around.

This improves performance: The time for one call to write_packet
decreased from 703501 to 357900 decicyles when remuxing a 5min
14000 kb/s H.264 transport stream.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavformat/matroskaenc.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 0446cd6ca9..e247f1029c 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -199,6 +199,8 @@  typedef struct MatroskaMuxContext {
     mkv_cues            cues;
     int64_t             cues_pos;
 
+    NALUList            h2645_nalu_list;
+
     AVPacket           *cur_audio_pkt;
 
     unsigned            nb_attachments;
@@ -746,6 +748,7 @@  static void mkv_deinit(AVFormatContext *s)
     ffio_free_dyn_buf(&mkv->track.bc);
     ffio_free_dyn_buf(&mkv->tags.bc);
 
+    av_freep(&mkv->h2645_nalu_list.nalus);
     av_freep(&mkv->cues.entries);
     av_freep(&mkv->tracks);
 }
@@ -2347,6 +2350,21 @@  static int mkv_blockgroup_size(int pkt_size, int track_num_size)
 }
 
 #if CONFIG_MATROSKA_MUXER
+static int mkv_reformat_h2645(MatroskaMuxContext *mkv, AVIOContext *pb,
+                              const AVPacket *pkt, int *size)
+{
+    int ret;
+    if (pb) {
+        ff_nal_units_write_list(&mkv->h2645_nalu_list, pb, pkt->data);
+    } else {
+        ret = ff_nal_units_create_list(&mkv->h2645_nalu_list, pkt->data, pkt->size);
+        if (ret < 0)
+            return ret;
+        *size = ret;
+    }
+    return 0;
+}
+
 static int mkv_reformat_wavpack(MatroskaMuxContext *mkv, AVIOContext *pb,
                                 const AVPacket *pkt, int *size)
 {
@@ -2426,13 +2444,6 @@  static int mkv_write_block(AVFormatContext *s, AVIOContext *pb,
            pkt->size, pkt->pts, pkt->dts, pkt->duration, avio_tell(pb),
            mkv->cluster_pos, track_number, keyframe != 0);
 
-#if CONFIG_MATROSKA_MUXER
-    if ((par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 ||
-         par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6) &&
-        (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1)) {
-        err = ff_avc_parse_nal_units_buf(pkt->data, &data, &size);
-    } else
-#endif
     if (track->reformat) {
         err = track->reformat(mkv, NULL, pkt, &size);
     } else
@@ -2489,8 +2500,6 @@  static int mkv_write_block(AVFormatContext *s, AVIOContext *pb,
         track->reformat(mkv, pb, pkt, &size);
     } else {
     avio_write(pb, data + offset, size);
-    if (data != pkt->data)
-        av_free(data);
     }
 
     if (blockid == MATROSKA_ID_BLOCK && !keyframe)
@@ -3110,6 +3119,13 @@  static int mkv_init(struct AVFormatContext *s)
         case AV_CODEC_ID_WAVPACK:
             track->reformat = mkv_reformat_wavpack;
             break;
+        case AV_CODEC_ID_H264:
+        case AV_CODEC_ID_HEVC:
+            if ((par->codec_id == AV_CODEC_ID_H264 && par->extradata_size > 0 ||
+                 par->codec_id == AV_CODEC_ID_HEVC && par->extradata_size > 6) &&
+                (AV_RB24(par->extradata) == 1 || AV_RB32(par->extradata) == 1))
+                track->reformat = mkv_reformat_h2645;
+            break;
 #endif
         case AV_CODEC_ID_AV1:
             track->reformat = mkv_reformat_av1;