Message ID | 20210712110709.15532-7-anton@khirnov.net |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel,1/8] tools/venc_data_dump: factor out demux/decode code | expand |
Context | Check | Description |
---|---|---|
andriy/x86_make | success | Make finished |
andriy/x86_make_fate | success | Make fate finished |
andriy/PPC64_make | success | Make finished |
andriy/PPC64_make_fate | success | Make fate finished |
On Mon, Jul 12, 2021 at 01:07:07PM +0200, Anton Khirnov wrote: > --- > libavfilter/vf_scale.c | 73 ++++++++++++++++++++++++++++-------------- > 1 file changed, 49 insertions(+), 24 deletions(-) crashes: ./ffmpeg -i ~/tickets/5264/gbrap16.tif -vf format=yuva444p,scale=alphablend=checkerboard,format=yuv420p -y file.png Stream mapping: Stream #0:0 -> #0:0 (tiff (native) -> png (native)) Press [q] to stop, [?] for help ==19419== Invalid read of size 4 ==19419== at 0x1223964: av_frame_ref (frame.c:330) ==19419== by 0x1190B34: sws_frame_start (swscale.c:1069) ==19419== by 0x1190EA4: sws_scale_frame (swscale.c:1153) ==19419== by 0x3E7493: scale_frame (vf_scale.c:821) ==19419== by 0x3E752D: filter_frame (vf_scale.c:837) ==19419== by 0x29B314: ff_filter_frame_framed (avfilter.c:969) ==19419== by 0x29BBCF: ff_filter_frame_to_filter (avfilter.c:1117) ==19419== by 0x29BDDF: ff_filter_activate_default (avfilter.c:1166) ==19419== by 0x29C003: ff_filter_activate (avfilter.c:1324) ==19419== by 0x2A0EBB: ff_filter_graph_run_once (avfiltergraph.c:1400) ==19419== by 0x2A2139: push_frame (buffersrc.c:157) ==19419== by 0x2A26B6: av_buffersrc_add_frame_flags (buffersrc.c:225) ==19419== by 0x24FC90: ifilter_send_frame (ffmpeg.c:2241) ==19419== by 0x24FF72: send_frame_to_filters (ffmpeg.c:2315) ==19419== by 0x250D26: decode_video (ffmpeg.c:2512) ==19419== by 0x2517BA: process_input_packet (ffmpeg.c:2674) ==19419== by 0x25799F: process_input (ffmpeg.c:4403) ==19419== by 0x2599A4: transcode_step (ffmpeg.c:4758) ==19419== by 0x259B0C: transcode (ffmpeg.c:4812) ==19419== by 0x25A470: main (ffmpeg.c:5017) ==19419== Address 0x68 is not stack'd, malloc'd or (recently) free'd ==19419== ==19419== [...]
On 7/12/2021 4:39 PM, Michael Niedermayer wrote: > On Mon, Jul 12, 2021 at 01:07:07PM +0200, Anton Khirnov wrote: >> --- >> libavfilter/vf_scale.c | 73 ++++++++++++++++++++++++++++-------------- >> 1 file changed, 49 insertions(+), 24 deletions(-) > > crashes: > > ./ffmpeg -i ~/tickets/5264/gbrap16.tif -vf format=yuva444p,scale=alphablend=checkerboard,format=yuv420p -y file.png > > Stream mapping: > Stream #0:0 -> #0:0 (tiff (native) -> png (native)) > Press [q] to stop, [?] for help > ==19419== Invalid read of size 4 > ==19419== at 0x1223964: av_frame_ref (frame.c:330) > ==19419== by 0x1190B34: sws_frame_start (swscale.c:1069) > ==19419== by 0x1190EA4: sws_scale_frame (swscale.c:1153) > ==19419== by 0x3E7493: scale_frame (vf_scale.c:821) > ==19419== by 0x3E752D: filter_frame (vf_scale.c:837) > ==19419== by 0x29B314: ff_filter_frame_framed (avfilter.c:969) > ==19419== by 0x29BBCF: ff_filter_frame_to_filter (avfilter.c:1117) > ==19419== by 0x29BDDF: ff_filter_activate_default (avfilter.c:1166) > ==19419== by 0x29C003: ff_filter_activate (avfilter.c:1324) > ==19419== by 0x2A0EBB: ff_filter_graph_run_once (avfiltergraph.c:1400) > ==19419== by 0x2A2139: push_frame (buffersrc.c:157) > ==19419== by 0x2A26B6: av_buffersrc_add_frame_flags (buffersrc.c:225) > ==19419== by 0x24FC90: ifilter_send_frame (ffmpeg.c:2241) > ==19419== by 0x24FF72: send_frame_to_filters (ffmpeg.c:2315) > ==19419== by 0x250D26: decode_video (ffmpeg.c:2512) > ==19419== by 0x2517BA: process_input_packet (ffmpeg.c:2674) > ==19419== by 0x25799F: process_input (ffmpeg.c:4403) > ==19419== by 0x2599A4: transcode_step (ffmpeg.c:4758) > ==19419== by 0x259B0C: transcode (ffmpeg.c:4812) > ==19419== by 0x25A470: main (ffmpeg.c:5017) > ==19419== Address 0x68 is not stack'd, malloc'd or (recently) free'd > ==19419== > ==19419== Both c->frame_src and c->frame_dst need to be allocated earlier in sws_init_context(). There seem to be some cases where that function will return early with a success code.
diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 39ab3a4b28..cdff3ab7ed 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -620,29 +620,54 @@ static int request_frame_ref(AVFilterLink *outlink) return ff_request_frame(outlink->src->inputs[1]); } -static int scale_slice(ScaleContext *scale, AVFrame *out_buf, AVFrame *cur_pic, struct SwsContext *sws, int y, int h, int mul, int field) +static void frame_offset(AVFrame *frame, int dir, int is_pal) { - const uint8_t *in[4]; - uint8_t *out[4]; - int in_stride[4],out_stride[4]; - int i; - - for (i=0; i<4; i++) { - int vsub= ((i+1)&2) ? scale->vsub : 0; - ptrdiff_t in_offset = ((y>>vsub)+field) * cur_pic->linesize[i]; - ptrdiff_t out_offset = field * out_buf->linesize[i]; - in_stride[i] = cur_pic->linesize[i] * mul; - out_stride[i] = out_buf->linesize[i] * mul; - in[i] = FF_PTR_ADD(cur_pic->data[i], in_offset); - out[i] = FF_PTR_ADD(out_buf->data[i], out_offset); - } - if (scale->input_is_pal) - in[1] = cur_pic->data[1]; - if (scale->output_is_pal) - out[1] = out_buf->data[1]; + for (int i = 0; i < 4 && frame->data[i]; i++) { + if (i == 1 && is_pal) + break; + frame->data[i] += frame->linesize[i] * dir; + } +} + +static int scale_field(ScaleContext *scale, AVFrame *dst, AVFrame *src, + int field) +{ + int orig_h_src = src->height; + int orig_h_dst = dst->height; + int ret; + + // offset the data pointers for the bottom field + if (field) { + frame_offset(src, 1, scale->input_is_pal); + frame_offset(dst, 1, scale->output_is_pal); + } + + // take every second line + for (int i = 0; i < 4; i++) { + src->linesize[i] *= 2; + dst->linesize[i] *= 2; + } + src->height /= 2; + dst->height /= 2; - return sws_scale(sws, in, in_stride, y/mul, h, - out,out_stride); + ret = sws_scale_frame(scale->isws[field], dst, src); + if (ret < 0) + return ret; + + // undo the changes we made above + for (int i = 0; i < 4; i++) { + src->linesize[i] /= 2; + dst->linesize[i] /= 2; + } + src->height = orig_h_src; + dst->height = orig_h_dst; + + if (field) { + frame_offset(src, -1, scale->input_is_pal); + frame_offset(dst, -1, scale->output_is_pal); + } + + return 0; } static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) @@ -789,11 +814,11 @@ scale: INT_MAX); if (scale->interlaced>0 || (scale->interlaced<0 && in->interlaced_frame)) { - ret = scale_slice(scale, out, in, scale->isws[0], 0, (link->h+1)/2, 2, 0); + ret = scale_field(scale, out, in, 0); if (ret >= 0) - ret = scale_slice(scale, out, in, scale->isws[1], 0, link->h /2, 2, 1); + ret = scale_field(scale, out, in, 1); } else { - ret = scale_slice(scale, out, in, scale->sws, 0, link->h, 1, 0); + ret = sws_scale_frame(scale->sws, out, in); } av_frame_free(&in);