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 | return ff_request_frame(outlink->src->inputs[1]); | 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]; | 624 | for (int i = 0; i < 4 && frame->data[i]; i++) { |
| 625 | uint8_t *out[4]; | 625 | if (i == 1 && is_pal) |
| 626 | int in_stride[4],out_stride[4]; | 626 | break; |
| 627 | int i; | 627 | frame->data[i] += frame->linesize[i] * dir; |
| 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); | ||
| 637 | } | 628 | } |
| 638 | if (scale->input_is_pal) | 629 | } |
| 639 | in[1] = cur_pic->data[1]; | 630 | |
| 640 | if (scale->output_is_pal) | 631 | static int scale_field(ScaleContext *scale, AVFrame *dst, AVFrame *src, |
| 641 | out[1] = out_buf->data[1]; | 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, | 652 | ret = sws_scale_frame(scale->isws[field], dst, src); |
| 644 | out,out_stride); | 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 | static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) | 672 | static int scale_frame(AVFilterLink *link, AVFrame *in, AVFrame **frame_out) |
| @@ -800,11 +825,11 @@ scale: · 152 unmodified lines | |||
| 800 | INT_MAX); | 825 | INT_MAX); |
| 801 | 826 | ||
| 802 | if (scale->interlaced>0 || (scale->interlaced<0 && in->interlaced_frame)) { | 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 | if (ret >= 0) | 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 | } else { | 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 | av_frame_free(&in); | 835 | av_frame_free(&in); |