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.
28 #include "img_format.h"
35 static const struct vf_priv_s
{
43 //===========================================================================//
45 static int config(struct vf_instance
* vf
,
46 int width
, int height
, int d_width
, int d_height
,
47 unsigned int flags
, unsigned int outfmt
){
48 struct MPOpts
*opts
= vf
->opts
;
49 // calculate the missing parameters:
50 if(vf
->priv
->crop_w
<=0 || vf
->priv
->crop_w
>width
) vf
->priv
->crop_w
=width
;
51 if(vf
->priv
->crop_h
<=0 || vf
->priv
->crop_h
>height
) vf
->priv
->crop_h
=height
;
52 if(vf
->priv
->crop_x
<0) vf
->priv
->crop_x
=(width
-vf
->priv
->crop_w
)/2;
53 if(vf
->priv
->crop_y
<0) vf
->priv
->crop_y
=(height
-vf
->priv
->crop_h
)/2;
55 if(!IMGFMT_IS_RGB(outfmt
) && !IMGFMT_IS_BGR(outfmt
)){
76 if(vf
->priv
->crop_w
+vf
->priv
->crop_x
>width
||
77 vf
->priv
->crop_h
+vf
->priv
->crop_y
>height
){
78 mp_tmsg(MSGT_VFILTER
, MSGL_WARN
, "[CROP] Bad position/width/height - cropped area outside of the original!\n");
81 if(!opts
->screen_size_x
&& !opts
->screen_size_y
){
82 d_width
=d_width
*vf
->priv
->crop_w
/width
;
83 d_height
=d_height
*vf
->priv
->crop_h
/height
;
85 return vf_next_config(vf
,vf
->priv
->crop_w
,vf
->priv
->crop_h
,d_width
,d_height
,flags
,outfmt
);
88 static int put_image(struct vf_instance
* vf
, mp_image_t
*mpi
, double pts
){
90 if (mpi
->flags
&MP_IMGFLAG_DRAW_CALLBACK
)
91 return vf_next_put_image(vf
,vf
->dmpi
, pts
);
92 dmpi
=vf_get_image(vf
->next
,mpi
->imgfmt
,
94 vf
->priv
->crop_w
, vf
->priv
->crop_h
);
95 if(mpi
->flags
&MP_IMGFLAG_PLANAR
){
96 dmpi
->planes
[0]=mpi
->planes
[0]+
97 vf
->priv
->crop_y
*mpi
->stride
[0]+vf
->priv
->crop_x
;
98 dmpi
->planes
[1]=mpi
->planes
[1]+
99 (vf
->priv
->crop_y
>>mpi
->chroma_y_shift
)*mpi
->stride
[1]+(vf
->priv
->crop_x
>>mpi
->chroma_x_shift
);
100 dmpi
->planes
[2]=mpi
->planes
[2]+
101 (vf
->priv
->crop_y
>>mpi
->chroma_y_shift
)*mpi
->stride
[2]+(vf
->priv
->crop_x
>>mpi
->chroma_x_shift
);
102 dmpi
->stride
[1]=mpi
->stride
[1];
103 dmpi
->stride
[2]=mpi
->stride
[2];
105 dmpi
->planes
[0]=mpi
->planes
[0]+
106 vf
->priv
->crop_y
*mpi
->stride
[0]+
107 vf
->priv
->crop_x
*(mpi
->bpp
/8);
108 dmpi
->planes
[1]=mpi
->planes
[1]; // passthrough rgb8 palette
110 dmpi
->stride
[0]=mpi
->stride
[0];
111 dmpi
->width
=mpi
->width
;
112 return vf_next_put_image(vf
,dmpi
, pts
);
115 static void start_slice(struct vf_instance
* vf
, mp_image_t
*mpi
){
116 vf
->dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
, mpi
->type
, mpi
->flags
,
117 vf
->priv
->crop_w
, vf
->priv
->crop_h
);
120 static void draw_slice(struct vf_instance
* vf
,
121 unsigned char** src
, int* stride
, int w
,int h
, int x
, int y
){
122 unsigned char *src2
[3];
124 if (vf
->dmpi
->flags
& MP_IMGFLAG_PLANAR
) {
128 //mp_msg(MSGT_VFILTER, MSGL_V, "crop slice %d %d %d %d ->", w,h,x,y);
129 if ((x
-= vf
->priv
->crop_x
) < 0) {
132 if (vf
->dmpi
->flags
& MP_IMGFLAG_PLANAR
) {
133 src2
[1] += x
>>vf
->dmpi
->chroma_x_shift
;
134 src2
[2] += x
>>vf
->dmpi
->chroma_x_shift
;
139 if ((y
-= vf
->priv
->crop_y
) < 0) {
141 src2
[0] += y
*stride
[0];
142 if (vf
->dmpi
->flags
& MP_IMGFLAG_PLANAR
) {
143 src2
[1] += (y
>>vf
->dmpi
->chroma_y_shift
)*stride
[1];
144 src2
[2] += (y
>>vf
->dmpi
->chroma_y_shift
)*stride
[2];
149 if (x
+w
> vf
->priv
->crop_w
) w
= vf
->priv
->crop_w
-x
;
150 if (y
+h
> vf
->priv
->crop_h
) h
= vf
->priv
->crop_h
-y
;
151 //mp_msg(MSGT_VFILTER, MSGL_V, "%d %d %d %d\n", w,h,x,y);
152 if (w
<= 0 || h
<= 0) return;
153 vf_next_draw_slice(vf
,src2
,stride
,w
,h
,x
,y
);
156 //===========================================================================//
158 static int vf_open(vf_instance_t
*vf
, char *args
){
160 vf
->put_image
=put_image
;
161 vf
->start_slice
=start_slice
;
162 vf
->draw_slice
=draw_slice
;
163 vf
->default_reqs
=VFCAP_ACCEPT_STRIDE
;
164 mp_msg(MSGT_VFILTER
, MSGL_INFO
, "Crop: %d x %d, %d ; %d\n",
172 #define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f)
173 static const m_option_t vf_opts_fields
[] = {
174 {"w", ST_OFF(crop_w
), CONF_TYPE_INT
, M_OPT_MIN
,0 ,0, NULL
},
175 {"h", ST_OFF(crop_h
), CONF_TYPE_INT
, M_OPT_MIN
,0 ,0, NULL
},
176 {"x", ST_OFF(crop_x
), CONF_TYPE_INT
, M_OPT_MIN
,-1 ,0, NULL
},
177 {"y", ST_OFF(crop_y
), CONF_TYPE_INT
, M_OPT_MIN
,-1 ,0, NULL
},
178 { NULL
, NULL
, 0, 0, 0, 0, NULL
}
181 static const m_struct_t vf_opts
= {
183 sizeof(struct vf_priv_s
),
188 const vf_info_t vf_info_crop
= {
197 //===========================================================================//