Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
52867 views
1
/*****************************************************************************
2
* crop.c: crop video filter
3
*****************************************************************************
4
* Copyright (C) 2010-2016 x264 project
5
*
6
* Authors: Steven Walters <[email protected]>
7
* James Darnley <[email protected]>
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
22
*
23
* This program is also available under a commercial proprietary license.
24
* For more information, contact us at [email protected].
25
*****************************************************************************/
26
27
#include "video.h"
28
#define NAME "crop"
29
#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, NAME, __VA_ARGS__ )
30
31
cli_vid_filter_t crop_filter;
32
33
typedef struct
34
{
35
hnd_t prev_hnd;
36
cli_vid_filter_t prev_filter;
37
38
int dims[4]; /* left, top, width, height */
39
const x264_cli_csp_t *csp;
40
} crop_hnd_t;
41
42
static void help( int longhelp )
43
{
44
printf( " "NAME":left,top,right,bottom\n" );
45
if( !longhelp )
46
return;
47
printf( " removes pixels from the edges of the frame\n" );
48
}
49
50
static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string )
51
{
52
FAIL_IF_ERROR( x264_cli_csp_is_invalid( info->csp ), "invalid csp %d\n", info->csp )
53
crop_hnd_t *h = calloc( 1, sizeof(crop_hnd_t) );
54
if( !h )
55
return -1;
56
57
h->csp = x264_cli_get_csp( info->csp );
58
static const char *optlist[] = { "left", "top", "right", "bottom", NULL };
59
char **opts = x264_split_options( opt_string, optlist );
60
if( !opts )
61
return -1;
62
63
for( int i = 0; i < 4; i++ )
64
{
65
char *opt = x264_get_option( optlist[i], opts );
66
FAIL_IF_ERROR( !opt, "%s crop value not specified\n", optlist[i] )
67
h->dims[i] = x264_otoi( opt, -1 );
68
FAIL_IF_ERROR( h->dims[i] < 0, "%s crop value `%s' is less than 0\n", optlist[i], opt )
69
int dim_mod = i&1 ? (h->csp->mod_height << info->interlaced) : h->csp->mod_width;
70
FAIL_IF_ERROR( h->dims[i] % dim_mod, "%s crop value `%s' is not a multiple of %d\n", optlist[i], opt, dim_mod )
71
}
72
x264_free_string_array( opts );
73
h->dims[2] = info->width - h->dims[0] - h->dims[2];
74
h->dims[3] = info->height - h->dims[1] - h->dims[3];
75
FAIL_IF_ERROR( h->dims[2] <= 0 || h->dims[3] <= 0, "invalid output resolution %dx%d\n", h->dims[2], h->dims[3] )
76
77
if( info->width != h->dims[2] || info->height != h->dims[3] )
78
x264_cli_log( NAME, X264_LOG_INFO, "cropping to %dx%d\n", h->dims[2], h->dims[3] );
79
else
80
{
81
/* do nothing as the user supplied 0s for all the values */
82
free( h );
83
return 0;
84
}
85
/* done initializing, overwrite values */
86
info->width = h->dims[2];
87
info->height = h->dims[3];
88
89
h->prev_filter = *filter;
90
h->prev_hnd = *handle;
91
*handle = h;
92
*filter = crop_filter;
93
94
return 0;
95
}
96
97
static int get_frame( hnd_t handle, cli_pic_t *output, int frame )
98
{
99
crop_hnd_t *h = handle;
100
if( h->prev_filter.get_frame( h->prev_hnd, output, frame ) )
101
return -1;
102
output->img.width = h->dims[2];
103
output->img.height = h->dims[3];
104
/* shift the plane pointers down 'top' rows and right 'left' columns. */
105
for( int i = 0; i < output->img.planes; i++ )
106
{
107
intptr_t offset = output->img.stride[i] * h->dims[1] * h->csp->height[i];
108
offset += h->dims[0] * h->csp->width[i] * x264_cli_csp_depth_factor( output->img.csp );
109
output->img.plane[i] += offset;
110
}
111
return 0;
112
}
113
114
static int release_frame( hnd_t handle, cli_pic_t *pic, int frame )
115
{
116
crop_hnd_t *h = handle;
117
/* NO filter should ever have a dependent release based on the plane pointers,
118
* so avoid unnecessary unshifting */
119
return h->prev_filter.release_frame( h->prev_hnd, pic, frame );
120
}
121
122
static void free_filter( hnd_t handle )
123
{
124
crop_hnd_t *h = handle;
125
h->prev_filter.free( h->prev_hnd );
126
free( h );
127
}
128
129
cli_vid_filter_t crop_filter = { NAME, help, init, get_frame, release_frame, free_filter, NULL };
130
131