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 | * called with more samples, it will split them. | 669 | * called with more samples, it will split them. |
| 670 | */ | 670 | */ |
| 671 | int max_samples; | 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 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include "libavutil/avassert.h" | ||
| 23 | #include "libavutil/imgutils.h" | 24 | #include "libavutil/imgutils.h" |
| 24 | 25 | ||
| 25 | #include "avfilter.h" | 26 | #include "avfilter.h" |
| @@ -223,6 +224,7 @@ static void clear_link(AVFilterLink *link) · 197 unmodified lines | |||
| 223 | avfilter_unref_bufferp(&link->cur_buf); | 224 | avfilter_unref_bufferp(&link->cur_buf); |
| 224 | avfilter_unref_bufferp(&link->src_buf); | 225 | avfilter_unref_bufferp(&link->src_buf); |
| 225 | avfilter_unref_bufferp(&link->out_buf); | 226 | avfilter_unref_bufferp(&link->out_buf); |
| 227 | link->cur_buf_copy = NULL; /* we do not own the reference */ | ||
| 226 | } | 228 | } |
| 227 | 229 | ||
| 228 | /* XXX: should we do the duplicating of the picture ref here, instead of | 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 | else | 267 | else |
| 266 | link->cur_buf = picref; | 268 | link->cur_buf = picref; |
| 267 | 269 | ||
| 270 | link->cur_buf_copy = link->cur_buf; | ||
| 271 | |||
| 268 | while(cmd && cmd->time <= picref->pts * av_q2d(link->time_base)){ | 272 | while(cmd && cmd->time <= picref->pts * av_q2d(link->time_base)){ |
| 269 | av_log(link->dst, AV_LOG_DEBUG, | 273 | av_log(link->dst, AV_LOG_DEBUG, |
| 270 | "Processing command time:%f command:%s arg:%s\n", | 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 | ff_update_link_current_pts(link, pts); | 282 | ff_update_link_current_pts(link, pts); |
| 279 | if (ret < 0) | 283 | if (ret < 0) |
| 280 | clear_link(link); | 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 | return ret; | 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 | if (link->src_buf->data[i]) { | 356 | if (link->src_buf->data[i]) { |
| 349 | src[i] = link->src_buf-> data[i] + | 357 | src[i] = link->src_buf-> data[i] + |
| 350 | (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i]; | 358 | (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i]; |
| 351 | dst[i] = link->cur_buf->data[i] + | 359 | dst[i] = link->cur_buf_copy->data[i] + |
| 352 | (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i]; | 360 | (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf_copy->linesize[i]; |
| 353 | } else | 361 | } else |
| 354 | src[i] = dst[i] = NULL; | 362 | src[i] = dst[i] = NULL; |
| 355 | } | 363 | } |
| 356 | 364 | ||
| 357 | for (i = 0; i < 4; i++) { | 365 | for (i = 0; i < 4; i++) { |
| 358 | int planew = | 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 | if (!src[i]) continue; | 369 | if (!src[i]) continue; |
| 362 | 370 | ||
| 363 | for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) { | 371 | for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) { |
| 364 | memcpy(dst[i], src[i], planew); | 372 | memcpy(dst[i], src[i], planew); |
| 365 | src[i] += link->src_buf->linesize[i]; | 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 | ret = draw_slice(link, y, h, slice_dir); | 381 | ret = draw_slice(link, y, h, slice_dir); |
| 374 | if (ret < 0) | 382 | if (ret < 0) |
| 375 | clear_link(link); | 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 | return ret; | 388 | return ret; |
| 377 | } | 389 | } |
| 378 | 390 | ||