WinGui: Fix another instance of the Caliburn vs Json.net sillyness where objects...
[HandBrake.git] / libhb / cropscale.c
bloba8a995a6c66dfdb53a875f55a7656f7da0e1b84d
1 /* cropscale.c
3 Copyright (c) 2003-2015 HandBrake Team
4 This file is part of the HandBrake source code
5 Homepage: <http://handbrake.fr/>.
6 It may be used under the terms of the GNU General Public License v2.
7 For full terms see the file COPYING file or visit http://www.gnu.org/licenses/gpl-2.0.html
8 */
10 #include "hb.h"
11 #include "hbffmpeg.h"
12 #include "common.h"
13 #include "opencl.h"
15 struct hb_filter_private_s
17 hb_job_t *job;
18 int width_in;
19 int height_in;
20 int pix_fmt;
21 int pix_fmt_out;
22 int width_out;
23 int height_out;
24 int crop[4];
26 /* OpenCL/DXVA2 */
27 int use_dxva;
28 int use_decomb;
29 int use_detelecine;
30 hb_oclscale_t *os; //ocl scaler handler
32 struct SwsContext * context;
35 static int hb_crop_scale_init( hb_filter_object_t * filter,
36 hb_filter_init_t * init );
38 static int hb_crop_scale_work( hb_filter_object_t * filter,
39 hb_buffer_t ** buf_in,
40 hb_buffer_t ** buf_out );
42 static int hb_crop_scale_info( hb_filter_object_t * filter,
43 hb_filter_info_t * info );
45 static void hb_crop_scale_close( hb_filter_object_t * filter );
47 hb_filter_object_t hb_filter_crop_scale =
49 .id = HB_FILTER_CROP_SCALE,
50 .enforce_order = 1,
51 .name = "Crop and Scale",
52 .settings = NULL,
53 .init = hb_crop_scale_init,
54 .work = hb_crop_scale_work,
55 .close = hb_crop_scale_close,
56 .info = hb_crop_scale_info,
59 static int hb_crop_scale_init( hb_filter_object_t * filter,
60 hb_filter_init_t * init )
62 filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) );
63 hb_filter_private_t * pv = filter->private_data;
65 // TODO: add pix format option to settings
66 pv->job = init->job;
67 pv->pix_fmt_out = init->pix_fmt;
68 pv->width_in = init->geometry.width;
69 pv->height_in = init->geometry.height;
70 pv->width_out = init->geometry.width - (init->crop[2] + init->crop[3]);
71 pv->height_out = init->geometry.height - (init->crop[0] + init->crop[1]);
73 /* OpenCL/DXVA2 */
74 pv->use_dxva = hb_hwd_enabled(init->job->h);
75 pv->use_decomb = init->job->use_decomb;
76 pv->use_detelecine = init->job->use_detelecine;
78 if (pv->job->use_opencl && pv->job->title->opencl_support)
80 pv->os = ( hb_oclscale_t * )malloc( sizeof( hb_oclscale_t ) );
81 memset( pv->os, 0, sizeof( hb_oclscale_t ) );
84 memcpy( pv->crop, init->crop, sizeof( int[4] ) );
85 if( filter->settings )
87 sscanf( filter->settings, "%d:%d:%d:%d:%d:%d",
88 &pv->width_out, &pv->height_out,
89 &pv->crop[0], &pv->crop[1], &pv->crop[2], &pv->crop[3] );
91 // Set init values so the next stage in the pipline
92 // knows what it will be getting
93 init->pix_fmt = pv->pix_fmt;
94 init->geometry.width = pv->width_out;
95 init->geometry.height = pv->height_out;
96 memcpy( init->crop, pv->crop, sizeof( int[4] ) );
98 return 0;
101 static int hb_crop_scale_info( hb_filter_object_t * filter,
102 hb_filter_info_t * info )
104 hb_filter_private_t * pv = filter->private_data;
106 if( !pv )
107 return 0;
109 // Set init values so the next stage in the pipline
110 // knows what it will be getting
111 memset( info, 0, sizeof( hb_filter_info_t ) );
112 info->out.pix_fmt = pv->pix_fmt;
113 info->out.geometry.width = pv->width_out;
114 info->out.geometry.height = pv->height_out;
115 memcpy( info->out.crop, pv->crop, sizeof( int[4] ) );
117 int cropped_width = pv->width_in - ( pv->crop[2] + pv->crop[3] );
118 int cropped_height = pv->height_in - ( pv->crop[0] + pv->crop[1] );
120 sprintf( info->human_readable_desc,
121 "source: %d * %d, crop (%d/%d/%d/%d): %d * %d, scale: %d * %d",
122 pv->width_in, pv->height_in,
123 pv->crop[0], pv->crop[1], pv->crop[2], pv->crop[3],
124 cropped_width, cropped_height, pv->width_out, pv->height_out );
126 return 0;
129 static void hb_crop_scale_close( hb_filter_object_t * filter )
131 hb_filter_private_t * pv = filter->private_data;
133 if ( !pv )
135 return;
138 /* OpenCL */
139 if (pv->job->use_opencl && pv->job->title->opencl_support && pv->os)
141 if (hb_ocl != NULL)
143 HB_OCL_BUF_FREE(hb_ocl, pv->os->bicubic_x_weights);
144 HB_OCL_BUF_FREE(hb_ocl, pv->os->bicubic_y_weights);
146 free(pv->os);
149 if( pv->context )
151 sws_freeContext( pv->context );
154 free( pv );
155 filter->private_data = NULL;
158 /* OpenCL */
159 static hb_buffer_t* crop_scale( hb_filter_private_t * pv, hb_buffer_t * in )
161 AVPicture pic_in;
162 AVPicture pic_out;
163 AVPicture pic_crop;
164 hb_buffer_t * out;
165 out = hb_video_buffer_init( pv->width_out, pv->height_out );
167 hb_avpicture_fill( &pic_in, in );
168 hb_avpicture_fill( &pic_out, out );
170 // Crop; this alters the pointer to the data to point to the
171 // correct place for cropped frame
172 av_picture_crop( &pic_crop, &pic_in, in->f.fmt,
173 pv->crop[0], pv->crop[2] );
175 // Use bicubic OpenCL scaling when selected and when downsampling < 4:1;
176 if ((pv->job->use_opencl && pv->job->title->opencl_support) &&
177 (pv->width_out * 4 > pv->width_in) &&
178 (in->cl.buffer != NULL) && (out->cl.buffer != NULL))
180 /* OpenCL */
181 hb_ocl_scale(in, out, pv->crop, pv->os);
183 else
185 if (pv->context == NULL ||
186 pv->width_in != in->f.width ||
187 pv->height_in != in->f.height ||
188 pv->pix_fmt != in->f.fmt)
190 // Something changed, need a new scaling context.
191 if (pv->context != NULL)
193 sws_freeContext(pv->context);
196 pv->context = hb_sws_get_context(in->f.width - (pv->crop[2] + pv->crop[3]),
197 in->f.height - (pv->crop[0] + pv->crop[1]),
198 in->f.fmt, out->f.width, out->f.height,
199 out->f.fmt, SWS_LANCZOS|SWS_ACCURATE_RND);
200 pv->width_in = in->f.width;
201 pv->height_in = in->f.height;
202 pv->pix_fmt = in->f.fmt;
205 if (pv->context == NULL)
207 hb_buffer_close(&out);
208 return NULL;
211 // Scale pic_crop into pic_render according to the
212 // context set up above
213 sws_scale(pv->context,
214 (const uint8_t* const*)pic_crop.data, pic_crop.linesize,
215 0, in->f.height - (pv->crop[0] + pv->crop[1]),
216 pic_out.data, pic_out.linesize);
219 out->s = in->s;
220 hb_buffer_move_subs( out, in );
221 return out;
224 static int hb_crop_scale_work( hb_filter_object_t * filter,
225 hb_buffer_t ** buf_in,
226 hb_buffer_t ** buf_out )
228 hb_filter_private_t * pv = filter->private_data;
229 hb_buffer_t * in = *buf_in;
231 if (in->s.flags & HB_BUF_FLAG_EOF)
233 *buf_out = in;
234 *buf_in = NULL;
235 return HB_FILTER_DONE;
238 if ( !pv )
240 *buf_out = in;
241 *buf_in = NULL;
242 return HB_FILTER_OK;
245 // If width or height were not set, set them now based on the
246 // input width & height
247 if ( pv->width_out <= 0 || pv->height_out <= 0 )
249 pv->width_out = in->f.width - (pv->crop[2] + pv->crop[3]);
250 pv->height_out = in->f.height - (pv->crop[0] + pv->crop[1]);
253 /* OpenCL/DXVA2 */
254 if ((!pv->use_dxva &&
255 !pv->crop[0] && !pv->crop[1] && !pv->crop[2] && !pv->crop[3] &&
256 in->f.fmt == pv->pix_fmt_out && in->f.width == pv->width_out &&
257 in->f.height == pv->height_out) ||
258 (pv->use_dxva && !pv->use_decomb && !pv->use_detelecine &&
259 in->f.width == pv->width_out && in->f.height == pv->height_out))
261 *buf_out = in;
262 *buf_in = NULL;
263 return HB_FILTER_OK;
266 *buf_out = crop_scale(pv, in);
268 return HB_FILTER_OK;