Browse code

lavfi: create buffer reference in filters which need to access the ref later

Also add internal function ff_null_start_frame_keep_ref().

Fix crash when a following filter (e.g. settb) will unref the reference
passed by start_frame(), and then the reference is accessed in
end_frame() through inlink->cur_buf.

Stefano Sabatini authored on 2012/04/25 07:25:18
Showing 5 changed files
... ...
@@ -140,4 +140,13 @@ int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx);
140 140
  */
141 141
 int ff_parse_packing_format(int *ret, const char *arg, void *log_ctx);
142 142
 
143
+/**
144
+ * Pass video frame along and keep an internal reference for later use.
145
+ */
146
+static inline void ff_null_start_frame_keep_ref(AVFilterLink *inlink,
147
+                                                AVFilterBufferRef *picref)
148
+{
149
+    avfilter_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(picref, ~0));
150
+}
151
+
143 152
 #endif /* AVFILTER_INTERNAL_H */
... ...
@@ -27,6 +27,7 @@
27 27
 #include "libavutil/timestamp.h"
28 28
 #include "avfilter.h"
29 29
 #include "bbox.h"
30
+#include "internal.h"
30 31
 
31 32
 typedef struct {
32 33
     unsigned int frame;
... ...
@@ -85,6 +86,7 @@ static void end_frame(AVFilterLink *inlink)
85 85
     av_log(ctx, AV_LOG_INFO, "\n");
86 86
 
87 87
     bbox->frame++;
88
+    avfilter_unref_buffer(picref);
88 89
     avfilter_end_frame(inlink->dst->outputs[0]);
89 90
 }
90 91
 
... ...
@@ -99,7 +101,7 @@ AVFilter avfilter_vf_bbox = {
99 99
         { .name             = "default",
100 100
           .type             = AVMEDIA_TYPE_VIDEO,
101 101
           .get_video_buffer = avfilter_null_get_video_buffer,
102
-          .start_frame      = avfilter_null_start_frame,
102
+          .start_frame      = ff_null_start_frame_keep_ref,
103 103
           .end_frame        = end_frame,
104 104
           .min_perms        = AV_PERM_READ, },
105 105
         { .name = NULL }
... ...
@@ -180,6 +180,7 @@ static void end_frame(AVFilterLink *inlink)
180 180
 
181 181
     blackdetect->frame_count++;
182 182
     blackdetect->nb_black_pixels = 0;
183
+    avfilter_unref_buffer(picref);
183 184
     avfilter_end_frame(inlink->dst->outputs[0]);
184 185
 }
185 186
 
... ...
@@ -196,7 +197,7 @@ AVFilter avfilter_vf_blackdetect = {
196 196
           .config_props     = config_input,
197 197
           .draw_slice       = draw_slice,
198 198
           .get_video_buffer = avfilter_null_get_video_buffer,
199
-          .start_frame      = avfilter_null_start_frame,
199
+          .start_frame      = ff_null_start_frame_keep_ref,
200 200
           .end_frame        = end_frame, },
201 201
         { .name = NULL }
202 202
     },
... ...
@@ -28,6 +28,7 @@
28 28
  */
29 29
 
30 30
 #include "avfilter.h"
31
+#include "internal.h"
31 32
 
32 33
 typedef struct {
33 34
     unsigned int bamount; ///< black amount
... ...
@@ -110,6 +111,7 @@ static void end_frame(AVFilterLink *inlink)
110 110
 
111 111
     blackframe->frame++;
112 112
     blackframe->nblack = 0;
113
+    avfilter_unref_buffer(picref);
113 114
     avfilter_end_frame(inlink->dst->outputs[0]);
114 115
 }
115 116
 
... ...
@@ -126,7 +128,7 @@ AVFilter avfilter_vf_blackframe = {
126 126
                                     .type             = AVMEDIA_TYPE_VIDEO,
127 127
                                     .draw_slice       = draw_slice,
128 128
                                     .get_video_buffer = avfilter_null_get_video_buffer,
129
-                                    .start_frame      = avfilter_null_start_frame,
129
+                                    .start_frame      = ff_null_start_frame_keep_ref,
130 130
                                     .end_frame        = end_frame, },
131 131
                                   { .name = NULL}},
132 132
 
... ...
@@ -27,6 +27,7 @@
27 27
 #include "libavutil/pixdesc.h"
28 28
 #include "libavutil/timestamp.h"
29 29
 #include "avfilter.h"
30
+#include "internal.h"
30 31
 
31 32
 typedef struct {
32 33
     unsigned int frame;
... ...
@@ -79,6 +80,7 @@ static void end_frame(AVFilterLink *inlink)
79 79
     av_log(ctx, AV_LOG_INFO, "]\n");
80 80
 
81 81
     showinfo->frame++;
82
+    avfilter_unref_buffer(picref);
82 83
     avfilter_end_frame(inlink->dst->outputs[0]);
83 84
 }
84 85
 
... ...
@@ -92,7 +94,7 @@ AVFilter avfilter_vf_showinfo = {
92 92
     .inputs    = (const AVFilterPad[]) {{ .name       = "default",
93 93
                                     .type             = AVMEDIA_TYPE_VIDEO,
94 94
                                     .get_video_buffer = avfilter_null_get_video_buffer,
95
-                                    .start_frame      = avfilter_null_start_frame,
95
+                                    .start_frame      = ff_null_start_frame_keep_ref,
96 96
                                     .end_frame        = end_frame,
97 97
                                     .min_perms        = AV_PERM_READ, },
98 98
                                   { .name = NULL}},