[FFmpeg-devel] [PATCH] avcodec/snow: ensure current_picture is writable before modifying its data

James Almer jamrial at gmail.com
Fri May 29 20:20:37 EEST 2020


current_picture was not writable here because a reference existed in
at least avctx->coded_frame, and potentially elsewhere if the caller
created new ones from it.

Signed-off-by: James Almer <jamrial at gmail.com>
---
For that matter, there are two filters that depend on whatever
s->mpvencdsp.draw_edges is doing on this buffer, accessing it through
avctx->coded_frame after passing their input to this encoder.
This is very hacky and the main blocker to remove coded_frame in the
next bump, so it must be changed.

If mpvencdsp.draw_edges needs to be accessed from lavfi, then it could
be shared, or its code duplicated. But the current snow usage from lavfi
is crazy and beyond the scope of coded_frame, which was meant to export
quality stats and not work as some sort of interface to access lavc image
processing features.

 libavcodec/snowenc.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index 3f2a75a670..3543574ec5 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -1624,10 +1624,20 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         s->lambda = 0;
     }//else keep previous frame's qlog until after motion estimation
 
+#if FF_API_CODED_FRAME
+FF_DISABLE_DEPRECATION_WARNINGS
+    av_frame_unref(avctx->coded_frame);
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
     if (s->current_picture->data[0]) {
         int w = s->avctx->width;
         int h = s->avctx->height;
 
+        ret = av_frame_make_writable(s->current_picture);
+        if (ret < 0)
+            return ret;
+
         s->mpvencdsp.draw_edges(s->current_picture->data[0],
                                 s->current_picture->linesize[0], w   , h   ,
                                 EDGE_WIDTH  , EDGE_WIDTH  , EDGE_TOP | EDGE_BOTTOM);
@@ -1645,7 +1655,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     ff_snow_frame_start(s);
 #if FF_API_CODED_FRAME
 FF_DISABLE_DEPRECATION_WARNINGS
-    av_frame_unref(avctx->coded_frame);
     ret = av_frame_ref(avctx->coded_frame, s->current_picture);
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
-- 
2.26.2



More information about the ffmpeg-devel mailing list