The code currently use cur_buf as the target of the copy, but cur_buf can be cleared by the filter if it has given the reference away or stored it elsewhere as soon as start_frame. The code still relies on the fact that the reference is not destroyed until end_frame. All filters currently follow that condition. An av_assert1() is added to check it; it should at least cause very visible errors in valgrind.
Unified · Split
| @@ -669,6 +669,15 @@ struct AVFilterLink { · 668 unmodified lines | ||
| 669 | 669 | * called with more samples, it will split them. |
| 670 | 670 | */ |
| 671 | 671 | int max_samples; |
| 672 | + | |
| 673 | + /** | |
| 674 | + * The buffer reference currently being received across the link by the | |
| 675 | + * destination filter. This is used internally by the filter system to | |
| 676 | + * allow automatic copying of buffers which do not have sufficient | |
| 677 | + * permissions for the destination. This should not be accessed directly | |
| 678 | + * by the filters. | |
| 679 | + */ | |
| 680 | + AVFilterBufferRef *cur_buf_copy; | |
| 672 | 681 | }; |
| 673 | 682 | |
| 674 | 683 | /** |
| @@ -20,6 +20,7 @@ · 19 unmodified lines | ||
| 20 | 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 21 | 21 | */ |
| 22 | 22 | |
| 23 | +#include "libavutil/avassert.h" | |
| 23 | 24 | #include "libavutil/imgutils.h" |
| 24 | 25 | |
| 25 | 26 | #include "avfilter.h" |
| @@ -223,6 +224,7 @@ static void clear_link(AVFilterLink *link) · 197 unmodified lines | ||
| 223 | 224 | avfilter_unref_bufferp(&link->cur_buf); |
| 224 | 225 | avfilter_unref_bufferp(&link->src_buf); |
| 225 | 226 | avfilter_unref_bufferp(&link->out_buf); |
| 227 | + link->cur_buf_copy = NULL; /* we do not own the reference */ | |
| 226 | 228 | } |
| 227 | 229 | |
| 228 | 230 | /* XXX: should we do the duplicating of the picture ref here, instead of |
| @@ -265,6 +267,8 @@ int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) · 36 unmodified lines | ||
| 265 | 267 | else |
| 266 | 268 | link->cur_buf = picref; |
| 267 | 269 | |
| 270 | + link->cur_buf_copy = link->cur_buf; | |
| 271 | + | |
| 268 | 272 | while(cmd && cmd->time <= picref->pts * av_q2d(link->time_base)){ |
| 269 | 273 | av_log(link->dst, AV_LOG_DEBUG, |
| 270 | 274 | "Processing command time:%f command:%s arg:%s\n", |
| @@ -278,6 +282,10 @@ int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) · 7 unmodified lines | ||
| 278 | 282 | ff_update_link_current_pts(link, pts); |
| 279 | 283 | if (ret < 0) |
| 280 | 284 | clear_link(link); |
| 285 | + else | |
| 286 | + /* incoming buffers must not be freed in start frame, | |
| 287 | + because they can still be in use by the automatic copy mechanism */ | |
| 288 | + av_assert1(link->cur_buf_copy->buf->refcount > 0); | |
| 281 | 289 | |
| 282 | 290 | return ret; |
| 283 | 291 | } |
| @@ -348,22 +356,22 @@ int ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) · 64 unmodified lines | ||
| 348 | 356 | if (link->src_buf->data[i]) { |
| 349 | 357 | src[i] = link->src_buf-> data[i] + |
| 350 | 358 | (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i]; |
| 351 | − dst[i] = link->cur_buf->data[i] + | |
| 352 | − (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i]; | |
| 359 | + dst[i] = link->cur_buf_copy->data[i] + | |
| 360 | + (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf_copy->linesize[i]; | |
| 353 | 361 | } else |
| 354 | 362 | src[i] = dst[i] = NULL; |
| 355 | 363 | } |
| 356 | 364 | |
| 357 | 365 | for (i = 0; i < 4; i++) { |
| 358 | 366 | int planew = |
| 359 | − av_image_get_linesize(link->format, link->cur_buf->video->w, i); | |
| 367 | + av_image_get_linesize(link->format, link->cur_buf_copy->video->w, i); | |
| 360 | 368 | |
| 361 | 369 | if (!src[i]) continue; |
| 362 | 370 | |
| 363 | 371 | for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) { |
| 364 | 372 | memcpy(dst[i], src[i], planew); |
| 365 | 373 | src[i] += link->src_buf->linesize[i]; |
| 366 | − dst[i] += link->cur_buf->linesize[i]; | |
| 374 | + dst[i] += link->cur_buf_copy->linesize[i]; | |
| 367 | 375 | } |
| 368 | 376 | } |
| 369 | 377 | } |
| @@ -373,6 +381,10 @@ int ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) · 3 unmodified lines | ||
| 373 | 381 | ret = draw_slice(link, y, h, slice_dir); |
| 374 | 382 | if (ret < 0) |
| 375 | 383 | clear_link(link); |
| 384 | + else | |
| 385 | + /* incoming buffers must not be freed in start frame, | |
| 386 | + because they can still be in use by the automatic copy mechanism */ | |
| 387 | + av_assert1(link->cur_buf_copy->buf->refcount > 0); | |
| 376 | 388 | return ret; |
| 377 | 389 | } |
| 378 | 390 | |