Showing the changes to libavfilter (1 of 1 file). Show all
Unified · Split
| @@ -619,29 +619,54 @@ static int request_frame_ref(AVFilterLink *outlink) · 618 unmodified lines | ||
| 619 | 619 | return ff_request_frame(outlink->src->inputs[1]); |
| 620 | 620 | } |
| 621 | 621 | |
| 622 | −static int scale_slice(ScaleContext *scale, AVFrame *out_buf, AVFrame *cur_pic, struct SwsContext *sws, int y, int h, int mul, int field) | |
| 622 | +static void frame_offset(AVFrame *frame, int dir, int is_pal) | |
| 623 | 623 | { |
| 624 | − const uint8_t *in[4]; | |
| 625 | − uint8_t *out[4]; | |
| 626 | − int in_stride[4],out_stride[4]; | |
| 627 | − int i; | |
| 628 | − | |
| 629 | − for (i=0; i<4; i++) { | |
| 630 | − int vsub= ((i+1)&2) ? scale->vsub : 0; | |
| 631 | − ptrdiff_t in_offset = ((y>>vsub)+field) * cur_pic->linesize[i]; | |
| 632 | − ptrdiff_t out_offset = field * out_buf->linesize[i]; | |
| 633 | − in_stride[i] = cur_pic->linesize[i] * mul; | |
| 634 | − out_stride[i] = out_buf->linesize[i] * mul; | |
| 635 | − in[i] = FF_PTR_ADD(cur_pic->data[i], in_offset); | |
| 636 | − out[i] = FF_PTR_ADD(out_buf->data[i], out_offset); | |
| 624 | + for (int i = 0; i < 4 && frame->data[i]; i++) { | |
| 625 | + if (i == 1 && is_pal) | |
| 626 | + break; | |
| 627 | + frame->data[i] += frame->linesize[i] * dir; | |
| 637 | 628 | } |
| 638 | − if (scale->input_is_pal) | |
| 639 | − in[1] = cur_pic->data[1]; | |
| 640 | − if (scale->output_is_pal) | |
| 641 | − out[1] = out_buf->data[1]; | |
| 629 | +} | |
| 630 | + | |
| 631 | +static int scale_field(ScaleContext *scale, AVFrame *dst, AVFrame *src, | |
| 632 | + int field) | |
| 633 | +{ | |
| 634 | + int orig_h_src = src->height; | |
| 635 | + int orig_h_dst = dst->height; | |
| 636 | + int ret; | |
| 637 | + | |
| 638 | + // offset the data pointers for the bottom field | |
| 639 | + if (field) { | |
| 640 | + frame_offset(src, 1, scale->input_is_pal); | |
| 641 | + frame_offset(dst, 1, scale->output_is_pal); | |
| 642 | + } | |
| 643 | + | |
| 644 | + // take every second line | |
| 645 | + for (int i = 0; i < 4; i++) { | |
| 646 | + src->linesize[i] *= 2; | |
| 647 | + dst->linesize[i] *= 2; | |
| 648 | + } | |
| 649 | + src->height /= 2; | |
| 650 | + dst->height /= 2; | |
| 642 | 651 | |
| 643 | − return sws_scale(sws, in, in_stride, y/mul, h, | |
| 644 | − out,out_stride); | |
| 652 | + ret = sws_scale_frame(scale->isws[field], dst, src); | |
| 653 | + if (ret < 0) | |
| 654 | + return ret; | |
| 655 | + | |
| 656 | + // undo the changes we made above | |
| 657 | + for (int i = 0; i < 4; i++) { | |
| 658 | + src->linesize[i] /= 2; | |
| 659 | + dst->linesize[i] /= 2; | |
| 660 | + } | |
| 661 | + src->height = orig_h_src; | |
| 662 | + dst->height = orig_h_dst; | |
| 663 | + | |
| 664 | + if (field) { | |
| 665 | + frame_offset(src, -1, scale->input_is_pal); | |
| 666 | + frame_offset(dst, -1, scale->output_is_pal); | |
| 667 | + } | |
| 668 | + | |
| 669 | + return 0; | |
| 645 | 670 | } |
| 646 | 671 | |
| 647 | 672 | static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) |
| @@ -800,11 +825,11 @@ scale: · 152 unmodified lines | ||
| 800 | 825 | INT_MAX); |
| 801 | 826 | |
| 802 | 827 | if (scale->interlaced>0 || (scale->interlaced<0 && in->interlaced_frame)) { |
| 803 | − ret = scale_slice(scale, out, in, scale->isws[0], 0, (link->h+1)/2, 2, 0); | |
| 828 | + ret = scale_field(scale, out, in, 0); | |
| 804 | 829 | if (ret >= 0) |
| 805 | − ret = scale_slice(scale, out, in, scale->isws[1], 0, link->h /2, 2, 1); | |
| 830 | + ret = scale_field(scale, out, in, 1); | |
| 806 | 831 | } else { |
| 807 | − ret = scale_slice(scale, out, in, scale->sws, 0, link->h, 1, 0); | |
| 832 | + ret = sws_scale_frame(scale->sws, out, in); | |
| 808 | 833 | } |
| 809 | 834 | |
| 810 | 835 | av_frame_free(&in); |