| 671 | | for( i_x = 0; i_x < i_width; i_x++ ) |
|---|
| 672 | | { |
|---|
| 673 | | if( p_trans ) |
|---|
| 674 | | i_trans = ( p_trans[i_x] * i_alpha ) / 255; |
|---|
| 675 | | if( !i_trans ) |
|---|
| 676 | | { |
|---|
| 677 | | /* Completely transparent. Don't change pixel */ |
|---|
| 678 | | continue; |
|---|
| 679 | | } |
|---|
| 680 | | else if( i_trans == MAX_TRANS ) |
|---|
| 681 | | { |
|---|
| 682 | | /* Completely opaque. Completely overwrite underlying pixel */ |
|---|
| 683 | | yuv_to_rgb( &r, &g, &b, |
|---|
| 684 | | p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] ); |
|---|
| 685 | | |
|---|
| 686 | | p_dst[i_x * i_pix_pitch] = r; |
|---|
| 687 | | p_dst[i_x * i_pix_pitch + 1] = g; |
|---|
| 688 | | p_dst[i_x * i_pix_pitch + 2] = b; |
|---|
| 689 | | continue; |
|---|
| 690 | | } |
|---|
| 691 | | |
|---|
| 692 | | /* Blending */ |
|---|
| 693 | | yuv_to_rgb( &r, &g, &b, |
|---|
| 694 | | p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] ); |
|---|
| 695 | | |
|---|
| 696 | | p_dst[i_x * i_pix_pitch] = ( r * i_trans + |
|---|
| 697 | | (uint16_t)p_src1[i_x * i_pix_pitch] * |
|---|
| 698 | | (MAX_TRANS - i_trans) ) >> TRANS_BITS; |
|---|
| 699 | | p_dst[i_x * i_pix_pitch + 1] = ( g * i_trans + |
|---|
| 700 | | (uint16_t)p_src1[i_x * i_pix_pitch + 1] * |
|---|
| 701 | | (MAX_TRANS - i_trans) ) >> TRANS_BITS; |
|---|
| 702 | | p_dst[i_x * i_pix_pitch + 2] = ( b * i_trans + |
|---|
| 703 | | (uint16_t)p_src1[i_x * i_pix_pitch + 2] * |
|---|
| 704 | | (MAX_TRANS - i_trans) ) >> TRANS_BITS; |
|---|
| 705 | | } |
|---|
| 706 | | } |
|---|
| 707 | | |
|---|
| 708 | | #undef MAX_TRANS |
|---|
| 709 | | #undef TRANS_BITS |
|---|
| 710 | | |
|---|
| 711 | | return; |
|---|
| 712 | | } |
|---|
| 713 | | |
|---|
| 714 | | static void BlendYUVPacked( filter_t *p_filter, picture_t *p_dst_pic, |
|---|
| 715 | | picture_t *p_dst_orig, picture_t *p_src, |
|---|
| 716 | | int i_x_offset, int i_y_offset, |
|---|
| 717 | | int i_width, int i_height, int i_alpha ) |
|---|
| 718 | | { |
|---|
| 719 | | int i_src1_pitch, i_src2_pitch, i_dst_pitch; |
|---|
| 720 | | uint8_t *p_dst, *p_src1, *p_src2_y; |
|---|
| 721 | | uint8_t *p_src2_u, *p_src2_v; |
|---|
| 722 | | uint8_t *p_trans; |
|---|
| 723 | | int i_x, i_y, i_pix_pitch, i_trans = 0; |
|---|
| 724 | | vlc_bool_t b_even = !((i_x_offset + p_filter->fmt_out.video.i_x_offset)%2); |
|---|
| 725 | | int i_l_offset = 0, i_u_offset = 0, i_v_offset = 0; |
|---|
| 726 | | |
|---|
| 727 | | if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','Y','2') ) |
|---|
| 728 | | { |
|---|
| 729 | | i_l_offset = 0; |
|---|
| 730 | | i_u_offset = 1; |
|---|
| 731 | | i_v_offset = 3; |
|---|
| 732 | | } |
|---|
| 733 | | else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('U','Y','V','Y') ) |
|---|
| 734 | | { |
|---|
| 735 | | i_l_offset = 1; |
|---|
| 736 | | i_u_offset = 0; |
|---|
| 737 | | i_v_offset = 2; |
|---|
| 738 | | } |
|---|
| 739 | | else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','Y','U') ) |
|---|
| 740 | | { |
|---|
| 741 | | i_l_offset = 0; |
|---|
| 742 | | i_u_offset = 3; |
|---|
| 743 | | i_v_offset = 1; |
|---|
| 744 | | } |
|---|
| 745 | | |
|---|
| 746 | | i_pix_pitch = 2; |
|---|
| 747 | | i_dst_pitch = p_dst_pic->p->i_pitch; |
|---|
| 748 | | p_dst = p_dst_pic->p->p_pixels + i_x_offset * i_pix_pitch + |
|---|
| 749 | | p_filter->fmt_out.video.i_x_offset * i_pix_pitch + |
|---|
| 750 | | p_dst_pic->p->i_pitch * |
|---|
| 751 | | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| 752 | | |
|---|
| 753 | | i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch; |
|---|
| 754 | | p_src1 = p_dst_orig->p->p_pixels + i_x_offset * i_pix_pitch + |
|---|
| 755 | | p_filter->fmt_out.video.i_x_offset * i_pix_pitch + |
|---|
| 756 | | p_dst_orig->p->i_pitch * |
|---|
| 757 | | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| 758 | | |
|---|
| 759 | | i_src2_pitch = p_src->p[Y_PLANE].i_pitch; |
|---|
| 760 | | p_src2_y = p_src->p[Y_PLANE].p_pixels + |
|---|
| 761 | | p_filter->fmt_in.video.i_x_offset + |
|---|
| 762 | | p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset; |
|---|
| 763 | | p_src2_u = p_src->p[U_PLANE].p_pixels + |
|---|
| 764 | | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| 765 | | p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| 766 | | p_src2_v = p_src->p[V_PLANE].p_pixels + |
|---|
| 767 | | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| 768 | | p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| 769 | | |
|---|
| 770 | | if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','V','1','2') || |
|---|
| 771 | | p_filter->fmt_in.video.i_chroma == VLC_FOURCC('I','4','2','0') ) |
|---|
| 772 | | { |
|---|
| 773 | | p_trans = NULL; |
|---|
| 774 | | i_trans = i_alpha; |
|---|
| 775 | | } |
|---|
| 776 | | else |
|---|
| 777 | | { |
|---|
| 778 | | p_trans = p_src->p[A_PLANE].p_pixels + |
|---|
| 779 | | p_filter->fmt_in.video.i_x_offset + |
|---|
| 780 | | p_src->p[A_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset; |
|---|
| 781 | | } |
|---|
| 782 | | |
|---|
| 783 | | i_width = (i_width >> 1) << 1; /* Needs to be a multiple of 2 */ |
|---|
| 784 | | |
|---|
| 785 | | #define MAX_TRANS 255 |
|---|
| 786 | | #define TRANS_BITS 8 |
|---|
| 787 | | |
|---|
| 788 | | /* Draw until we reach the bottom of the subtitle */ |
|---|
| 789 | | for( i_y = 0; i_y < i_height; i_y++, p_trans += p_trans?i_src2_pitch:0, |
|---|
| 790 | | p_dst += i_dst_pitch, p_src1 += i_src1_pitch, |
|---|
| 791 | | p_src2_y += i_src2_pitch, p_src2_u += i_src2_pitch, |
|---|
| 792 | | p_src2_v += i_src2_pitch ) |
|---|
| 793 | | { |
|---|
| 794 | | /* Draw until we reach the end of the line */ |
|---|
| | 778 | /*********************************************************************** |
|---|
| | 779 | * I420, YV12 |
|---|
| | 780 | ***********************************************************************/ |
|---|
| | 781 | static void BlendI420I420( filter_t *p_filter, picture_t *p_dst, |
|---|
| | 782 | picture_t *p_dst_orig, picture_t *p_src, |
|---|
| | 783 | int i_x_offset, int i_y_offset, |
|---|
| | 784 | int i_width, int i_height, int i_alpha ) |
|---|
| | 785 | { |
|---|
| | 786 | int i_src1_pitch, i_src2_pitch, i_dst_pitch; |
|---|
| | 787 | uint8_t *p_src1_y, *p_src2_y, *p_dst_y; |
|---|
| | 788 | uint8_t *p_src1_u, *p_src2_u, *p_dst_u; |
|---|
| | 789 | uint8_t *p_src1_v, *p_src2_v, *p_dst_v; |
|---|
| | 790 | int i_x, i_y; |
|---|
| | 791 | vlc_bool_t b_even_scanline = i_y_offset % 2; |
|---|
| | 792 | |
|---|
| | 793 | i_dst_pitch = p_dst->p[Y_PLANE].i_pitch; |
|---|
| | 794 | p_dst_y = p_dst->p[Y_PLANE].p_pixels + i_x_offset + |
|---|
| | 795 | p_filter->fmt_out.video.i_x_offset + |
|---|
| | 796 | p_dst->p[Y_PLANE].i_pitch * |
|---|
| | 797 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| | 798 | p_dst_u = p_dst->p[U_PLANE].p_pixels + i_x_offset/2 + |
|---|
| | 799 | p_filter->fmt_out.video.i_x_offset/2 + |
|---|
| | 800 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 * |
|---|
| | 801 | p_dst->p[U_PLANE].i_pitch; |
|---|
| | 802 | p_dst_v = p_dst->p[V_PLANE].p_pixels + i_x_offset/2 + |
|---|
| | 803 | p_filter->fmt_out.video.i_x_offset/2 + |
|---|
| | 804 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 * |
|---|
| | 805 | p_dst->p[V_PLANE].i_pitch; |
|---|
| | 806 | |
|---|
| | 807 | i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch; |
|---|
| | 808 | p_src1_y = p_dst_orig->p[Y_PLANE].p_pixels + i_x_offset + |
|---|
| | 809 | p_filter->fmt_out.video.i_x_offset + |
|---|
| | 810 | p_dst_orig->p[Y_PLANE].i_pitch * |
|---|
| | 811 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| | 812 | p_src1_u = p_dst_orig->p[U_PLANE].p_pixels + i_x_offset/2 + |
|---|
| | 813 | p_filter->fmt_out.video.i_x_offset/2 + |
|---|
| | 814 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 * |
|---|
| | 815 | p_dst_orig->p[U_PLANE].i_pitch; |
|---|
| | 816 | p_src1_v = p_dst_orig->p[V_PLANE].p_pixels + i_x_offset/2 + |
|---|
| | 817 | p_filter->fmt_out.video.i_x_offset/2 + |
|---|
| | 818 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 * |
|---|
| | 819 | p_dst_orig->p[V_PLANE].i_pitch; |
|---|
| | 820 | |
|---|
| | 821 | i_src2_pitch = p_src->p[Y_PLANE].i_pitch; |
|---|
| | 822 | p_src2_y = p_src->p[Y_PLANE].p_pixels + |
|---|
| | 823 | p_filter->fmt_in.video.i_x_offset + |
|---|
| | 824 | p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset; |
|---|
| | 825 | p_src2_u = p_src->p[U_PLANE].p_pixels + |
|---|
| | 826 | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| | 827 | p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| | 828 | p_src2_v = p_src->p[V_PLANE].p_pixels + |
|---|
| | 829 | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| | 830 | p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| | 831 | |
|---|
| | 832 | #define MAX_TRANS 255 |
|---|
| | 833 | #define TRANS_BITS 8 |
|---|
| | 834 | |
|---|
| | 835 | /* Draw until we reach the bottom of the subtitle */ |
|---|
| | 836 | for( i_y = 0; i_y < i_height; i_y++, |
|---|
| | 837 | p_dst_y += i_dst_pitch, p_src1_y += i_src1_pitch, |
|---|
| | 838 | p_src2_y += i_src2_pitch ) |
|---|
| | 839 | { |
|---|
| | 840 | if( b_even_scanline ) |
|---|
| | 841 | { |
|---|
| | 842 | p_dst_u += i_dst_pitch/2; |
|---|
| | 843 | p_dst_v += i_dst_pitch/2; |
|---|
| | 844 | p_src1_u += i_src1_pitch/2; |
|---|
| | 845 | p_src1_v += i_src1_pitch/2; |
|---|
| | 846 | } |
|---|
| | 847 | b_even_scanline = !b_even_scanline; |
|---|
| | 848 | |
|---|
| | 849 | /* Draw until we reach the end of the line */ |
|---|
| | 850 | for( i_x = 0; i_x < i_width; i_x++ ) |
|---|
| | 851 | { |
|---|
| | 852 | if( i_alpha == MAX_TRANS ) |
|---|
| | 853 | { |
|---|
| | 854 | /* Completely opaque. Completely overwrite underlying pixel */ |
|---|
| | 855 | p_dst_y[i_x] = p_src2_y[i_x]; |
|---|
| | 856 | |
|---|
| | 857 | if( b_even_scanline && i_x % 2 == 0 ) |
|---|
| | 858 | { |
|---|
| | 859 | p_dst_u[i_x/2] = p_src2_u[i_x/2]; |
|---|
| | 860 | p_dst_v[i_x/2] = p_src2_v[i_x/2]; |
|---|
| | 861 | } |
|---|
| | 862 | continue; |
|---|
| | 863 | } |
|---|
| | 864 | |
|---|
| | 865 | /* Blending */ |
|---|
| | 866 | p_dst_y[i_x] = ( (uint16_t)p_src2_y[i_x] * i_alpha + |
|---|
| | 867 | (uint16_t)p_src1_y[i_x] * (MAX_TRANS - i_alpha) ) |
|---|
| | 868 | >> TRANS_BITS; |
|---|
| | 869 | |
|---|
| | 870 | if( b_even_scanline && i_x % 2 == 0 ) |
|---|
| | 871 | { |
|---|
| | 872 | p_dst_u[i_x/2] = ( (uint16_t)p_src2_u[i_x/2] * i_alpha + |
|---|
| | 873 | (uint16_t)p_src1_u[i_x/2] * (MAX_TRANS - i_alpha) ) |
|---|
| | 874 | >> TRANS_BITS; |
|---|
| | 875 | p_dst_v[i_x/2] = ( (uint16_t)p_src2_v[i_x/2] * i_alpha + |
|---|
| | 876 | (uint16_t)p_src1_v[i_x/2] * (MAX_TRANS - i_alpha) ) |
|---|
| | 877 | >> TRANS_BITS; |
|---|
| | 878 | } |
|---|
| | 879 | } |
|---|
| | 880 | if( i_y%2 == 1 ) |
|---|
| | 881 | { |
|---|
| | 882 | p_src2_u += i_src2_pitch/2; |
|---|
| | 883 | p_src2_v += i_src2_pitch/2; |
|---|
| | 884 | } |
|---|
| | 885 | } |
|---|
| | 886 | |
|---|
| | 887 | #undef MAX_TRANS |
|---|
| | 888 | #undef TRANS_BITS |
|---|
| | 889 | |
|---|
| | 890 | return; |
|---|
| | 891 | } |
|---|
| | 892 | static void BlendI420I420_no_alpha( filter_t *p_filter, picture_t *p_dst, |
|---|
| | 893 | picture_t *p_dst_orig, picture_t *p_src, |
|---|
| | 894 | int i_x_offset, int i_y_offset, |
|---|
| | 895 | int i_width, int i_height ) |
|---|
| | 896 | { |
|---|
| | 897 | int i_src1_pitch, i_src2_pitch, i_dst_pitch; |
|---|
| | 898 | uint8_t *p_src1_y, *p_src2_y, *p_dst_y; |
|---|
| | 899 | uint8_t *p_src1_u, *p_src2_u, *p_dst_u; |
|---|
| | 900 | uint8_t *p_src1_v, *p_src2_v, *p_dst_v; |
|---|
| | 901 | int i_y; |
|---|
| | 902 | vlc_bool_t b_even_scanline = i_y_offset % 2; |
|---|
| | 903 | |
|---|
| | 904 | i_dst_pitch = p_dst->p[Y_PLANE].i_pitch; |
|---|
| | 905 | p_dst_y = p_dst->p[Y_PLANE].p_pixels + i_x_offset + |
|---|
| | 906 | p_filter->fmt_out.video.i_x_offset + |
|---|
| | 907 | p_dst->p[Y_PLANE].i_pitch * |
|---|
| | 908 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| | 909 | p_dst_u = p_dst->p[U_PLANE].p_pixels + i_x_offset/2 + |
|---|
| | 910 | p_filter->fmt_out.video.i_x_offset/2 + |
|---|
| | 911 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 * |
|---|
| | 912 | p_dst->p[U_PLANE].i_pitch; |
|---|
| | 913 | p_dst_v = p_dst->p[V_PLANE].p_pixels + i_x_offset/2 + |
|---|
| | 914 | p_filter->fmt_out.video.i_x_offset/2 + |
|---|
| | 915 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 * |
|---|
| | 916 | p_dst->p[V_PLANE].i_pitch; |
|---|
| | 917 | |
|---|
| | 918 | i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch; |
|---|
| | 919 | p_src1_y = p_dst_orig->p[Y_PLANE].p_pixels + i_x_offset + |
|---|
| | 920 | p_filter->fmt_out.video.i_x_offset + |
|---|
| | 921 | p_dst_orig->p[Y_PLANE].i_pitch * |
|---|
| | 922 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| | 923 | p_src1_u = p_dst_orig->p[U_PLANE].p_pixels + i_x_offset/2 + |
|---|
| | 924 | p_filter->fmt_out.video.i_x_offset/2 + |
|---|
| | 925 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 * |
|---|
| | 926 | p_dst_orig->p[U_PLANE].i_pitch; |
|---|
| | 927 | p_src1_v = p_dst_orig->p[V_PLANE].p_pixels + i_x_offset/2 + |
|---|
| | 928 | p_filter->fmt_out.video.i_x_offset/2 + |
|---|
| | 929 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 * |
|---|
| | 930 | p_dst_orig->p[V_PLANE].i_pitch; |
|---|
| | 931 | |
|---|
| | 932 | i_src2_pitch = p_src->p[Y_PLANE].i_pitch; |
|---|
| | 933 | p_src2_y = p_src->p[Y_PLANE].p_pixels + |
|---|
| | 934 | p_filter->fmt_in.video.i_x_offset + |
|---|
| | 935 | p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset; |
|---|
| | 936 | p_src2_u = p_src->p[U_PLANE].p_pixels + |
|---|
| | 937 | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| | 938 | p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| | 939 | p_src2_v = p_src->p[V_PLANE].p_pixels + |
|---|
| | 940 | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| | 941 | p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| | 942 | |
|---|
| | 943 | i_width &= ~1; |
|---|
| | 944 | |
|---|
| | 945 | /* Draw until we reach the bottom of the subtitle */ |
|---|
| | 946 | for( i_y = 0; i_y < i_height; i_y++, |
|---|
| | 947 | p_dst_y += i_dst_pitch, p_src1_y += i_src1_pitch, |
|---|
| | 948 | p_src2_y += i_src2_pitch ) |
|---|
| | 949 | { |
|---|
| | 950 | /* Completely opaque. Completely overwrite underlying pixel */ |
|---|
| | 951 | p_filter->p_libvlc->pf_memcpy( p_dst_y, p_src2_y, i_width ); |
|---|
| | 952 | if( b_even_scanline ) |
|---|
| | 953 | { |
|---|
| | 954 | p_dst_u += i_dst_pitch/2; |
|---|
| | 955 | p_dst_v += i_dst_pitch/2; |
|---|
| | 956 | p_src1_u += i_src1_pitch/2; |
|---|
| | 957 | p_src1_v += i_src1_pitch/2; |
|---|
| | 958 | } |
|---|
| | 959 | else |
|---|
| | 960 | { |
|---|
| | 961 | p_filter->p_libvlc->pf_memcpy( p_dst_u, p_src2_u, i_width/2 ); |
|---|
| | 962 | p_filter->p_libvlc->pf_memcpy( p_dst_v, p_src2_v, i_width/2 ); |
|---|
| | 963 | } |
|---|
| | 964 | b_even_scanline = !b_even_scanline; |
|---|
| | 965 | if( i_y%2 == 1 ) |
|---|
| | 966 | { |
|---|
| | 967 | p_src2_u += i_src2_pitch/2; |
|---|
| | 968 | p_src2_v += i_src2_pitch/2; |
|---|
| | 969 | } |
|---|
| | 970 | } |
|---|
| | 971 | |
|---|
| | 972 | return; |
|---|
| | 973 | } |
|---|
| | 974 | |
|---|
| | 975 | static void BlendI420R16( filter_t *p_filter, picture_t *p_dst_pic, |
|---|
| | 976 | picture_t *p_dst_orig, picture_t *p_src, |
|---|
| | 977 | int i_x_offset, int i_y_offset, |
|---|
| | 978 | int i_width, int i_height, int i_alpha ) |
|---|
| | 979 | { |
|---|
| | 980 | int i_src1_pitch, i_src2_pitch, i_dst_pitch; |
|---|
| | 981 | uint8_t *p_dst, *p_src1, *p_src2_y; |
|---|
| | 982 | uint8_t *p_src2_u, *p_src2_v; |
|---|
| | 983 | int i_x, i_y, i_pix_pitch; |
|---|
| | 984 | int r, g, b; |
|---|
| | 985 | |
|---|
| | 986 | i_pix_pitch = p_dst_pic->p->i_pixel_pitch; |
|---|
| | 987 | i_dst_pitch = p_dst_pic->p->i_pitch; |
|---|
| | 988 | p_dst = p_dst_pic->p->p_pixels + i_x_offset * i_pix_pitch + |
|---|
| | 989 | p_filter->fmt_out.video.i_x_offset * i_pix_pitch + |
|---|
| | 990 | p_dst_pic->p->i_pitch * |
|---|
| | 991 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| | 992 | |
|---|
| | 993 | i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch; |
|---|
| | 994 | p_src1 = p_dst_orig->p->p_pixels + i_x_offset * i_pix_pitch + |
|---|
| | 995 | p_filter->fmt_out.video.i_x_offset * i_pix_pitch + |
|---|
| | 996 | p_dst_orig->p->i_pitch * |
|---|
| | 997 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| | 998 | |
|---|
| | 999 | i_src2_pitch = p_src->p[Y_PLANE].i_pitch; |
|---|
| | 1000 | p_src2_y = p_src->p[Y_PLANE].p_pixels + |
|---|
| | 1001 | p_filter->fmt_in.video.i_x_offset + |
|---|
| | 1002 | p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset; |
|---|
| | 1003 | p_src2_u = p_src->p[U_PLANE].p_pixels + |
|---|
| | 1004 | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| | 1005 | p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| | 1006 | p_src2_v = p_src->p[V_PLANE].p_pixels + |
|---|
| | 1007 | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| | 1008 | p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| | 1009 | |
|---|
| | 1010 | #define MAX_TRANS 255 |
|---|
| | 1011 | #define TRANS_BITS 8 |
|---|
| | 1012 | |
|---|
| | 1013 | /* Draw until we reach the bottom of the subtitle */ |
|---|
| | 1014 | for( i_y = 0; i_y < i_height; i_y++, |
|---|
| | 1015 | p_dst += i_dst_pitch, p_src1 += i_src1_pitch, |
|---|
| | 1016 | p_src2_y += i_src2_pitch ) |
|---|
| | 1017 | { |
|---|
| | 1018 | /* Draw until we reach the end of the line */ |
|---|
| | 1019 | for( i_x = 0; i_x < i_width; i_x++ ) |
|---|
| | 1020 | { |
|---|
| | 1021 | if( i_alpha == MAX_TRANS ) |
|---|
| | 1022 | { |
|---|
| | 1023 | /* Completely opaque. Completely overwrite underlying pixel */ |
|---|
| | 1024 | yuv_to_rgb( &r, &g, &b, |
|---|
| | 1025 | p_src2_y[i_x], p_src2_u[i_x/2], p_src2_v[i_x/2] ); |
|---|
| | 1026 | |
|---|
| | 1027 | ((uint16_t *)(&p_dst[i_x * i_pix_pitch]))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); |
|---|
| | 1028 | continue; |
|---|
| | 1029 | } |
|---|
| | 1030 | |
|---|
| | 1031 | /* Blending */ |
|---|
| | 1032 | /* FIXME: do the blending */ |
|---|
| | 1033 | yuv_to_rgb( &r, &g, &b, |
|---|
| | 1034 | p_src2_y[i_x], p_src2_u[i_x/2], p_src2_v[i_x/2] ); |
|---|
| | 1035 | |
|---|
| | 1036 | ((uint16_t *)(&p_dst[i_x * i_pix_pitch]))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); |
|---|
| | 1037 | } |
|---|
| | 1038 | if( i_y%2 == 1 ) |
|---|
| | 1039 | { |
|---|
| | 1040 | p_src2_u += i_src2_pitch/2; |
|---|
| | 1041 | p_src2_v += i_src2_pitch/2; |
|---|
| | 1042 | } |
|---|
| | 1043 | } |
|---|
| | 1044 | |
|---|
| | 1045 | #undef MAX_TRANS |
|---|
| | 1046 | #undef TRANS_BITS |
|---|
| | 1047 | |
|---|
| | 1048 | return; |
|---|
| | 1049 | } |
|---|
| | 1050 | |
|---|
| | 1051 | static void BlendI420R24( filter_t *p_filter, picture_t *p_dst_pic, |
|---|
| | 1052 | picture_t *p_dst_orig, picture_t *p_src, |
|---|
| | 1053 | int i_x_offset, int i_y_offset, |
|---|
| | 1054 | int i_width, int i_height, int i_alpha ) |
|---|
| | 1055 | { |
|---|
| | 1056 | int i_src1_pitch, i_src2_pitch, i_dst_pitch; |
|---|
| | 1057 | uint8_t *p_dst, *p_src1, *p_src2_y; |
|---|
| | 1058 | uint8_t *p_src2_u, *p_src2_v; |
|---|
| | 1059 | int i_x, i_y, i_pix_pitch; |
|---|
| | 1060 | int r, g, b; |
|---|
| | 1061 | |
|---|
| | 1062 | i_pix_pitch = p_dst_pic->p->i_pixel_pitch; |
|---|
| | 1063 | i_dst_pitch = p_dst_pic->p->i_pitch; |
|---|
| | 1064 | p_dst = p_dst_pic->p->p_pixels + i_x_offset * i_pix_pitch + |
|---|
| | 1065 | p_filter->fmt_out.video.i_x_offset * i_pix_pitch + |
|---|
| | 1066 | p_dst_pic->p->i_pitch * |
|---|
| | 1067 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| | 1068 | |
|---|
| | 1069 | i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch; |
|---|
| | 1070 | p_src1 = p_dst_orig->p->p_pixels + i_x_offset * i_pix_pitch + |
|---|
| | 1071 | p_filter->fmt_out.video.i_x_offset * i_pix_pitch + |
|---|
| | 1072 | p_dst_orig->p->i_pitch * |
|---|
| | 1073 | ( i_y_offset + p_filter->fmt_out.video.i_y_offset ); |
|---|
| | 1074 | |
|---|
| | 1075 | i_src2_pitch = p_src->p[Y_PLANE].i_pitch; |
|---|
| | 1076 | p_src2_y = p_src->p[Y_PLANE].p_pixels + |
|---|
| | 1077 | p_filter->fmt_in.video.i_x_offset + |
|---|
| | 1078 | p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset; |
|---|
| | 1079 | p_src2_u = p_src->p[U_PLANE].p_pixels + |
|---|
| | 1080 | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| | 1081 | p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| | 1082 | p_src2_v = p_src->p[V_PLANE].p_pixels + |
|---|
| | 1083 | p_filter->fmt_in.video.i_x_offset/2 + |
|---|
| | 1084 | p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2; |
|---|
| | 1085 | |
|---|
| | 1086 | #define MAX_TRANS 255 |
|---|
| | 1087 | #define TRANS_BITS 8 |
|---|
| | 1088 | |
|---|
| | 1089 | /* Draw until we reach the bottom of the subtitle */ |
|---|
| | 1090 | for( i_y = 0; i_y < i_height; i_y++, |
|---|
| | 1091 | p_dst += i_dst_pitch, p_src1 += i_src1_pitch, |
|---|
| | 1092 | p_src2_y += i_src2_pitch, p_src2_u += i_src2_pitch, |
|---|
| | 1093 | p_src2_v += i_src2_pitch ) |
|---|
| | 1094 | { |
|---|
| | 1095 | /* Draw until we reach the end of the line */ |
|---|
| | 1096 | for( i_x = 0; i_x < i_width; i_x++ ) |
|---|
| | 1097 | { |
|---|
| | 1098 | if( i_alpha == MAX_TRANS ) |
|---|
| | 1099 | { |
|---|
| | 1100 | /* Completely opaque. Completely overwrite underlying pixel */ |
|---|
| | 1101 | yuv_to_rgb( &r, &g, &b, |
|---|
| | 1102 | p_src2_y[i_x], p_src2_u[i_x/2], p_src2_v[i_x/2] ); |
|---|
| | 1103 | |
|---|
| | 1104 | p_dst[i_x * i_pix_pitch] = r; |
|---|
| | 1105 | p_dst[i_x * i_pix_pitch + 1] = g; |
|---|
| | 1106 | p_dst[i_x * i_pix_pitch + 2] = b; |
|---|
| | 1107 | continue; |
|---|
| | 1108 | } |
|---|
| | 1109 | |
|---|
| | 1110 | /* Blending */ |
|---|
| | 1111 | yuv_to_rgb( &r, &g, &b, |
|---|
| | 1112 | p_src2_y[i_x], p_src2_u[i_x/2], p_src2_v[i_x/2] ); |
|---|
| | 1113 | |
|---|
| | 1114 | p_dst[i_x * i_pix_pitch] = ( r * i_alpha + |
|---|
| | 1115 | (uint16_t)p_src1[i_x * i_pix_pitch] * |
|---|
| | 1116 | (MAX_TRANS - i_alpha) ) >> TRANS_BITS; |
|---|
| | 1117 | p_dst[i_x * i_pix_pitch + 1] = ( g * i_alpha + |
|---|
| | 1118 | (uint16_t)p_src1[i_x * i_pix_pitch + 1] * |
|---|
| | 1119 | (MAX_TRANS - i_alpha) ) >> TRANS_BITS; |
|---|
| | 1120 | p_dst[i_x * i_pix_pitch + 2] = ( b * i_alpha + |
|---|
| | 1121 | (uint16_t)p_src1[i_x * i_pix_pitch + 2] * |
|---|
| | 1122 | (MAX_TRANS - i_alpha) ) >> TRANS_BITS; |
|---|
| | 1123 | } |
|---|
| | 1124 | if( i_y%2 == 1 ) |
|---|
| | 1125 | { |
|---|
| | 1126 | p_src2_u += i_src2_pitch/2; |
|---|
| | 1127 | p_src2_v += i_src2_pitch/2; |
|---|
| | 1128 | } |
|---|
| | 1129 | } |
|---|
| | 1130 | |
|---|
| | 1131 | #undef MAX_TRANS |
|---|
| | 1132 | #undef TRANS_BITS |
|---|
| | 1133 | |
|---|
| | 1134 | return; |
|---|
| | 1135 | } |
|---|
| | 1136 | |
|---|
| | 1137 | static void BlendI420YUVPacked( filter_t *p_filter, picture_t *p_dst_pic, |
|---|
| | 1138 | picture_t *p_dst_orig, picture_t *p_src, |
|---|
| | 1139 | int i_x_offset, int i_y_offset, |
|---|
| | 1140 | int i_width, int i_height, int i_alpha ) |
|---|
| | 1141 | { |
|---|
| | 1142 | int i_src1_pitch, i_src2_pitch, i_dst_pitch; |
|---|
| | 1143 | uint8_t *p_dst, *p_src1, *p_src2_y; |
|---|
| | 1144 | uint8_t *p_src2_u, *p_src2_v; |
|---|
| | 1145 | int i_x, i_y, i_pix_pitch; |
|---|
| | 1146 | vlc_bool_t b_even = !((i_x_offset + p_filter->fmt_out.video.i_x_offset)%2); |
|---|
| | 1147 | int i_l_offset = 0, i_u_offset = 0, i_v_offset = 0; |
|---|
| | 1148 | |
|---|
| | 1149 | if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','Y','2') ) |
|---|
| | 1150 | { |
|---|
| | 1151 | i_l_offset = 0; |
|---|
| | 1152 | i_u_offset = 1; |
|---|
| |
|---|