2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "img_format.h"
34 static const struct vf_priv_s
{
42 //===========================================================================//
44 static int config(struct vf_instance
*vf
,
45 int width
, int height
, int d_width
, int d_height
,
46 unsigned int flags
, unsigned int outfmt
){
47 struct MPOpts
*opts
= vf
->opts
;
48 // calculate the missing parameters:
49 if(vf
->priv
->crop_w
<=0 || vf
->priv
->crop_w
>width
) vf
->priv
->crop_w
=width
;
50 if(vf
->priv
->crop_h
<=0 || vf
->priv
->crop_h
>height
) vf
->priv
->crop_h
=height
;
51 if(vf
->priv
->crop_x
<0) vf
->priv
->crop_x
=(width
-vf
->priv
->crop_w
)/2;
52 if(vf
->priv
->crop_y
<0) vf
->priv
->crop_y
=(height
-vf
->priv
->crop_h
)/2;
54 if(!IMGFMT_IS_RGB(outfmt
) && !IMGFMT_IS_BGR(outfmt
)){
75 if(vf
->priv
->crop_w
+vf
->priv
->crop_x
>width
||
76 vf
->priv
->crop_h
+vf
->priv
->crop_y
>height
){
77 mp_tmsg(MSGT_VFILTER
, MSGL_WARN
, "[CROP] Bad position/width/height - cropped area outside of the original!\n");
80 if(!opts
->screen_size_x
&& !opts
->screen_size_y
){
81 d_width
=d_width
*vf
->priv
->crop_w
/width
;
82 d_height
=d_height
*vf
->priv
->crop_h
/height
;
84 return vf_next_config(vf
,vf
->priv
->crop_w
,vf
->priv
->crop_h
,d_width
,d_height
,flags
,outfmt
);
87 static int put_image(struct vf_instance
*vf
, mp_image_t
*mpi
, double pts
){
89 if (mpi
->flags
&MP_IMGFLAG_DRAW_CALLBACK
)
90 return vf_next_put_image(vf
,vf
->dmpi
, pts
);
91 dmpi
=vf_get_image(vf
->next
,mpi
->imgfmt
,
93 vf
->priv
->crop_w
, vf
->priv
->crop_h
);
94 if(mpi
->flags
&MP_IMGFLAG_PLANAR
){
95 dmpi
->planes
[0]=mpi
->planes
[0]+
96 vf
->priv
->crop_y
*mpi
->stride
[0]+vf
->priv
->crop_x
;
97 dmpi
->planes
[1]=mpi
->planes
[1]+
98 (vf
->priv
->crop_y
>>mpi
->chroma_y_shift
)*mpi
->stride
[1]+(vf
->priv
->crop_x
>>mpi
->chroma_x_shift
);
99 dmpi
->planes
[2]=mpi
->planes
[2]+
100 (vf
->priv
->crop_y
>>mpi
->chroma_y_shift
)*mpi
->stride
[2]+(vf
->priv
->crop_x
>>mpi
->chroma_x_shift
);
101 dmpi
->stride
[1]=mpi
->stride
[1];
102 dmpi
->stride
[2]=mpi
->stride
[2];
104 dmpi
->planes
[0]=mpi
->planes
[0]+
105 vf
->priv
->crop_y
*mpi
->stride
[0]+
106 vf
->priv
->crop_x
*(mpi
->bpp
/8);
107 dmpi
->planes
[1]=mpi
->planes
[1]; // passthrough rgb8 palette
109 dmpi
->stride
[0]=mpi
->stride
[0];
110 dmpi
->width
=mpi
->width
;
111 return vf_next_put_image(vf
,dmpi
, pts
);
114 static void start_slice(struct vf_instance
*vf
, mp_image_t
*mpi
){
115 vf
->dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
, mpi
->type
, mpi
->flags
,
116 vf
->priv
->crop_w
, vf
->priv
->crop_h
);
119 static void draw_slice(struct vf_instance
*vf
,
120 unsigned char** src
, int* stride
, int w
,int h
, int x
, int y
){
121 unsigned char *src2
[3];
123 if (vf
->dmpi
->flags
& MP_IMGFLAG_PLANAR
) {
127 //mp_msg(MSGT_VFILTER, MSGL_V, "crop slice %d %d %d %d ->", w,h,x,y);
128 if ((x
-= vf
->priv
->crop_x
) < 0) {
131 if (vf
->dmpi
->flags
& MP_IMGFLAG_PLANAR
) {
132 src2
[1] += x
>>vf
->dmpi
->chroma_x_shift
;
133 src2
[2] += x
>>vf
->dmpi
->chroma_x_shift
;
138 if ((y
-= vf
->priv
->crop_y
) < 0) {
140 src2
[0] += y
*stride
[0];
141 if (vf
->dmpi
->flags
& MP_IMGFLAG_PLANAR
) {
142 src2
[1] += (y
>>vf
->dmpi
->chroma_y_shift
)*stride
[1];
143 src2
[2] += (y
>>vf
->dmpi
->chroma_y_shift
)*stride
[2];
148 if (x
+w
> vf
->priv
->crop_w
) w
= vf
->priv
->crop_w
-x
;
149 if (y
+h
> vf
->priv
->crop_h
) h
= vf
->priv
->crop_h
-y
;
150 //mp_msg(MSGT_VFILTER, MSGL_V, "%d %d %d %d\n", w,h,x,y);
151 if (w
<= 0 || h
<= 0) return;
152 vf_next_draw_slice(vf
,src2
,stride
,w
,h
,x
,y
);
155 //===========================================================================//
157 static int vf_open(vf_instance_t
*vf
, char *args
){
159 vf
->put_image
=put_image
;
160 vf
->start_slice
=start_slice
;
161 vf
->draw_slice
=draw_slice
;
162 vf
->default_reqs
=VFCAP_ACCEPT_STRIDE
;
163 mp_msg(MSGT_VFILTER
, MSGL_INFO
, "Crop: %d x %d, %d ; %d\n",
171 #define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
172 static const m_option_t vf_opts_fields
[] = {
173 {"w", ST_OFF(crop_w
), CONF_TYPE_INT
, M_OPT_MIN
,0 ,0, NULL
},
174 {"h", ST_OFF(crop_h
), CONF_TYPE_INT
, M_OPT_MIN
,0 ,0, NULL
},
175 {"x", ST_OFF(crop_x
), CONF_TYPE_INT
, M_OPT_MIN
,-1 ,0, NULL
},
176 {"y", ST_OFF(crop_y
), CONF_TYPE_INT
, M_OPT_MIN
,-1 ,0, NULL
},
177 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
180 static const m_struct_t vf_opts
= {
182 sizeof(struct vf_priv_s
),
187 const vf_info_t vf_info_crop
= {
196 //===========================================================================//