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.tags/n0.11
| @@ -140,4 +140,13 @@ int ff_parse_channel_layout(int64_t *ret, const char *arg, void *log_ctx); | |||||
| */ | */ | ||||
| int ff_parse_packing_format(int *ret, const char *arg, void *log_ctx); | int ff_parse_packing_format(int *ret, const char *arg, void *log_ctx); | ||||
| /** | |||||
| * Pass video frame along and keep an internal reference for later use. | |||||
| */ | |||||
| static inline void ff_null_start_frame_keep_ref(AVFilterLink *inlink, | |||||
| AVFilterBufferRef *picref) | |||||
| { | |||||
| avfilter_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(picref, ~0)); | |||||
| } | |||||
| #endif /* AVFILTER_INTERNAL_H */ | #endif /* AVFILTER_INTERNAL_H */ | ||||
| @@ -27,6 +27,7 @@ | |||||
| #include "libavutil/timestamp.h" | #include "libavutil/timestamp.h" | ||||
| #include "avfilter.h" | #include "avfilter.h" | ||||
| #include "bbox.h" | #include "bbox.h" | ||||
| #include "internal.h" | |||||
| typedef struct { | typedef struct { | ||||
| unsigned int frame; | unsigned int frame; | ||||
| @@ -85,6 +86,7 @@ static void end_frame(AVFilterLink *inlink) | |||||
| av_log(ctx, AV_LOG_INFO, "\n"); | av_log(ctx, AV_LOG_INFO, "\n"); | ||||
| bbox->frame++; | bbox->frame++; | ||||
| avfilter_unref_buffer(picref); | |||||
| avfilter_end_frame(inlink->dst->outputs[0]); | avfilter_end_frame(inlink->dst->outputs[0]); | ||||
| } | } | ||||
| @@ -99,7 +101,7 @@ AVFilter avfilter_vf_bbox = { | |||||
| { .name = "default", | { .name = "default", | ||||
| .type = AVMEDIA_TYPE_VIDEO, | .type = AVMEDIA_TYPE_VIDEO, | ||||
| .get_video_buffer = avfilter_null_get_video_buffer, | .get_video_buffer = avfilter_null_get_video_buffer, | ||||
| .start_frame = avfilter_null_start_frame, | |||||
| .start_frame = ff_null_start_frame_keep_ref, | |||||
| .end_frame = end_frame, | .end_frame = end_frame, | ||||
| .min_perms = AV_PERM_READ, }, | .min_perms = AV_PERM_READ, }, | ||||
| { .name = NULL } | { .name = NULL } | ||||
| @@ -180,6 +180,7 @@ static void end_frame(AVFilterLink *inlink) | |||||
| blackdetect->frame_count++; | blackdetect->frame_count++; | ||||
| blackdetect->nb_black_pixels = 0; | blackdetect->nb_black_pixels = 0; | ||||
| avfilter_unref_buffer(picref); | |||||
| avfilter_end_frame(inlink->dst->outputs[0]); | avfilter_end_frame(inlink->dst->outputs[0]); | ||||
| } | } | ||||
| @@ -196,7 +197,7 @@ AVFilter avfilter_vf_blackdetect = { | |||||
| .config_props = config_input, | .config_props = config_input, | ||||
| .draw_slice = draw_slice, | .draw_slice = draw_slice, | ||||
| .get_video_buffer = avfilter_null_get_video_buffer, | .get_video_buffer = avfilter_null_get_video_buffer, | ||||
| .start_frame = avfilter_null_start_frame, | |||||
| .start_frame = ff_null_start_frame_keep_ref, | |||||
| .end_frame = end_frame, }, | .end_frame = end_frame, }, | ||||
| { .name = NULL } | { .name = NULL } | ||||
| }, | }, | ||||
| @@ -28,6 +28,7 @@ | |||||
| */ | */ | ||||
| #include "avfilter.h" | #include "avfilter.h" | ||||
| #include "internal.h" | |||||
| typedef struct { | typedef struct { | ||||
| unsigned int bamount; ///< black amount | unsigned int bamount; ///< black amount | ||||
| @@ -110,6 +111,7 @@ static void end_frame(AVFilterLink *inlink) | |||||
| blackframe->frame++; | blackframe->frame++; | ||||
| blackframe->nblack = 0; | blackframe->nblack = 0; | ||||
| avfilter_unref_buffer(picref); | |||||
| avfilter_end_frame(inlink->dst->outputs[0]); | avfilter_end_frame(inlink->dst->outputs[0]); | ||||
| } | } | ||||
| @@ -126,7 +128,7 @@ AVFilter avfilter_vf_blackframe = { | |||||
| .type = AVMEDIA_TYPE_VIDEO, | .type = AVMEDIA_TYPE_VIDEO, | ||||
| .draw_slice = draw_slice, | .draw_slice = draw_slice, | ||||
| .get_video_buffer = avfilter_null_get_video_buffer, | .get_video_buffer = avfilter_null_get_video_buffer, | ||||
| .start_frame = avfilter_null_start_frame, | |||||
| .start_frame = ff_null_start_frame_keep_ref, | |||||
| .end_frame = end_frame, }, | .end_frame = end_frame, }, | ||||
| { .name = NULL}}, | { .name = NULL}}, | ||||
| @@ -27,6 +27,7 @@ | |||||
| #include "libavutil/pixdesc.h" | #include "libavutil/pixdesc.h" | ||||
| #include "libavutil/timestamp.h" | #include "libavutil/timestamp.h" | ||||
| #include "avfilter.h" | #include "avfilter.h" | ||||
| #include "internal.h" | |||||
| typedef struct { | typedef struct { | ||||
| unsigned int frame; | unsigned int frame; | ||||
| @@ -79,6 +80,7 @@ static void end_frame(AVFilterLink *inlink) | |||||
| av_log(ctx, AV_LOG_INFO, "]\n"); | av_log(ctx, AV_LOG_INFO, "]\n"); | ||||
| showinfo->frame++; | showinfo->frame++; | ||||
| avfilter_unref_buffer(picref); | |||||
| avfilter_end_frame(inlink->dst->outputs[0]); | avfilter_end_frame(inlink->dst->outputs[0]); | ||||
| } | } | ||||
| @@ -92,7 +94,7 @@ AVFilter avfilter_vf_showinfo = { | |||||
| .inputs = (const AVFilterPad[]) {{ .name = "default", | .inputs = (const AVFilterPad[]) {{ .name = "default", | ||||
| .type = AVMEDIA_TYPE_VIDEO, | .type = AVMEDIA_TYPE_VIDEO, | ||||
| .get_video_buffer = avfilter_null_get_video_buffer, | .get_video_buffer = avfilter_null_get_video_buffer, | ||||
| .start_frame = avfilter_null_start_frame, | |||||
| .start_frame = ff_null_start_frame_keep_ref, | |||||
| .end_frame = end_frame, | .end_frame = end_frame, | ||||
| .min_perms = AV_PERM_READ, }, | .min_perms = AV_PERM_READ, }, | ||||
| { .name = NULL}}, | { .name = NULL}}, | ||||