[FFmpeg-devel] [PATCH 2/2] avdevice/lavfi: use wrapped_avframe

Muhammad Faiz mfcc64 at gmail.com
Mon Nov 9 17:05:18 CET 2015


fix ticket #4985
avoid memory copying from AVFrame to rawvideo

benchmark:
time ffmpeg -f lavfi -i "amovie=audio.mp3, showcqt" -f null -y /dev/null
old:
    real    1m3.766s
    user    1m3.371s
    sys     0m0.184s
new:
    real    0m47.893s
    user    0m47.399s
    sys     0m0.054s

but higher memory usage on ffplay playback because of
packet queueing (it depends on packet size to calculate
memory usage, but wrappped_avframe packet size does not
represent actual allocated memory)
old: about ~40MB
new: about ~180MB

showspectrum filter does not work correctly because it does not
follow frame writability convention (use copy filter for workaround)

patch attached
thanks
-------------- next part --------------
From 297702abfbf0922676188dcfc76f63df53273c93 Mon Sep 17 00:00:00 2001
From: Muhammad Faiz <mfcc64 at gmail.com>
Date: Mon, 9 Nov 2015 17:27:02 +0700
Subject: [PATCH 2/2] avdevice/lavfi: use wrapped_avframe

fix ticket #4985
avoid memory copying from AVFrame to rawvideo

benchmark:
time ffmpeg -f lavfi -i "amovie=audio.mp3, showcqt" -f null -y /dev/null
old:
    real    1m3.766s
    user    1m3.371s
    sys     0m0.184s
new:
    real    0m47.893s
    user    0m47.399s
    sys     0m0.054s

but higher memory usage on ffplay playback because of
packet queueing (it depends on packet size to calculate
memory usage, but wrappped_avframe packet size does not
represent actual allocated memory)
old: about ~40MB
new: about ~180MB

showspectrum filter does not work correctly because it does not
follow frame writability convention (use copy filter for workaround)
---
 libavdevice/lavfi.c   | 39 ++++++++++++++++++++++++++-------------
 libavdevice/version.h |  2 +-
 2 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c
index 3453b4d..93e2723 100644
--- a/libavdevice/lavfi.c
+++ b/libavdevice/lavfi.c
@@ -311,17 +311,13 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx)
         st->codec->codec_type = link->type;
         avpriv_set_pts_info(st, 64, link->time_base.num, link->time_base.den);
         if (link->type == AVMEDIA_TYPE_VIDEO) {
-            st->codec->codec_id   = AV_CODEC_ID_RAWVIDEO;
+            st->codec->codec_id   = AV_CODEC_ID_WRAPPED_AVFRAME;
             st->codec->pix_fmt    = link->format;
             st->codec->time_base  = link->time_base;
             st->codec->width      = link->w;
             st->codec->height     = link->h;
             st       ->sample_aspect_ratio =
             st->codec->sample_aspect_ratio = link->sample_aspect_ratio;
-            avctx->probesize = FFMAX(avctx->probesize,
-                                     link->w * link->h *
-                                     av_get_padded_bits_per_pixel(av_pix_fmt_desc_get(link->format)) *
-                                     30);
         } else if (link->type == AVMEDIA_TYPE_AUDIO) {
             st->codec->codec_id    = av_get_pcm_codec(link->format, -1);
             st->codec->channels    = avfilter_link_get_channels(link);
@@ -375,13 +371,20 @@ static int create_subcc_packet(AVFormatContext *avctx, AVFrame *frame,
     return 0;
 }
 
+/* duplicate from libavcodec/wrapped_avframe.c */
+static void wrapped_avframe_release_buffer(void *unused, uint8_t *data)
+{
+    AVFrame *frame = (AVFrame *)data;
+
+    av_frame_free(&frame);
+}
+
 static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
 {
     LavfiContext *lavfi = avctx->priv_data;
     double min_pts = DBL_MAX;
     int stream_idx, min_pts_sink_idx = 0;
     AVFrame *frame = lavfi->decoded_frame;
-    AVPicture pict;
     AVDictionary *frame_metadata;
     int ret, i;
     int size = 0;
@@ -430,15 +433,25 @@ static int lavfi_read_packet(AVFormatContext *avctx, AVPacket *pkt)
     stream_idx = lavfi->sink_stream_map[min_pts_sink_idx];
 
     if (frame->width /* FIXME best way of testing a video */) {
-        size = avpicture_get_size(frame->format, frame->width, frame->height);
-        if ((ret = av_new_packet(pkt, size)) < 0)
-            return ret;
+        /* duplicate from libavcodec/wrapped_avframe.c */
+        AVFrame *wrapped = av_frame_clone(frame);
 
-        memcpy(pict.data,     frame->data,     4*sizeof(frame->data[0]));
-        memcpy(pict.linesize, frame->linesize, 4*sizeof(frame->linesize[0]));
+        if (!wrapped)
+            return AVERROR(ENOMEM);
+
+        size = sizeof(*wrapped);
+
+        pkt->buf = av_buffer_create((uint8_t *)wrapped, size,
+                                    wrapped_avframe_release_buffer, NULL,
+                                    AV_BUFFER_FLAG_READONLY);
+        if (!pkt->buf) {
+            av_frame_free(&wrapped);
+            return AVERROR(ENOMEM);
+        }
 
-        avpicture_layout(&pict, frame->format, frame->width, frame->height,
-                         pkt->data, size);
+        pkt->data = (uint8_t *) wrapped;
+        pkt->size = size;
+        pkt->flags |= AV_PKT_FLAG_KEY;
     } else if (av_frame_get_channels(frame) /* FIXME test audio */) {
         size = frame->nb_samples * av_get_bytes_per_sample(frame->format) *
                                    av_frame_get_channels(frame);
diff --git a/libavdevice/version.h b/libavdevice/version.h
index 45c9e8d..b226a76 100644
--- a/libavdevice/version.h
+++ b/libavdevice/version.h
@@ -29,7 +29,7 @@
 
 #define LIBAVDEVICE_VERSION_MAJOR  57
 #define LIBAVDEVICE_VERSION_MINOR   0
-#define LIBAVDEVICE_VERSION_MICRO 100
+#define LIBAVDEVICE_VERSION_MICRO 101
 
 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
                                                LIBAVDEVICE_VERSION_MINOR, \
-- 
1.8.3.1



More information about the ffmpeg-devel mailing list