MythTV  master
filter_crop.c
Go to the documentation of this file.
1 /*
2  * crop v 0.2
3  * (C)opyright 2003, Debabrata Banerjee
4  * GNU GPL 2 or later
5  *
6  * Pass options as crop=top:left:bottom:right as number of 16 pixel blocks.
7  *
8  */
9 
10 #include <stdio.h>
11 
12 #include "mythconfig.h"
13 #if HAVE_STDINT_H
14 #include <stdint.h>
15 #endif
16 
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #include "filter.h"
21 #include "mythframe.h"
22 #include "libavutil/mem.h"
23 #include "libavutil/cpu.h"
24 
25 #ifdef MMX
26 #include "ffmpeg-mmx.h"
27 #endif
28 
29 //static const char FILTER_NAME[] = "crop";
30 
31 typedef struct ThisFilter
32 {
34 
35  int yp1, yp2, xp1, xp2;
36 
37  TF_STRUCT;
38 
39 } ThisFilter;
40 
41 static int crop(VideoFilter *f, VideoFrame *frame, int field)
42 {
43  (void)field;
44  ThisFilter *tf = (ThisFilter*) f;
45  uint64_t *ybuf = (uint64_t*) (frame->buf + frame->offsets[0]);
46  uint64_t *ubuf = (uint64_t*) (frame->buf + frame->offsets[1]);
47  uint64_t *vbuf = (uint64_t*) (frame->buf + frame->offsets[2]);
48  const uint64_t Y_black = 0x1010101010101010LL; // 8 bytes
49  const uint64_t UV_black = 0x8080808080808080LL; // 8 bytes
50  int x, y, sz, t1, t2;
51 
52  TF_VARS;
53 
54  TF_START;
55 
56  if (frame->pitches[1] != frame->pitches[2])
57  return -1;
58 
59  // Luma top
60  sz = (frame->pitches[0] * frame->height) >> 3; // div 8 bytes
61  for (y = 0; (y < tf->yp1 * frame->pitches[0] << 1) && (y < sz); y += 2)
62  {
63  ybuf[y + 0] = Y_black;
64  ybuf[y + 1] = Y_black;
65  }
66 
67  // Luma bottom
68  for (y = ((frame->height >> 4) - tf->yp2) * frame->pitches[0] << 1;
69  y < sz; y += 2)
70  {
71  ybuf[y + 0] = Y_black;
72  ybuf[y + 1] = Y_black;
73  }
74 
75  // Chroma top
76  sz = (frame->pitches[1] * (frame->height >> 1)) >> 3; // div 8 bytes
77  for (y = 0; (y < tf->yp1 * frame->pitches[1]) && (y < sz); y++)
78  {
79  ubuf[y] = UV_black;
80  vbuf[y] = UV_black;
81  }
82 
83  // Chroma bottom
84  for (y = ((frame->height >> 4) - tf->yp2) * frame->pitches[1]; y < sz; y++)
85  {
86  ubuf[y] = UV_black;
87  vbuf[y] = UV_black;
88  }
89 
90  // Luma left and right
91  sz = (frame->pitches[0] * frame->height) >> 3; // div 8 bytes
92  t1 = frame->pitches[0] << 1;
93  t2 = frame->pitches[0] >> 3;
94  for (y = tf->yp1 * t1;
95  (y < ((frame->height >> 4) - tf->yp2) * t1) && (y < sz); y += t2)
96  {
97  for (x = 0; (x < (tf->xp1 << 1)) && (x < t1); x += 2)
98  {
99  ybuf[y + x + 0] = Y_black;
100  ybuf[y + x + 1] = Y_black;
101  }
102 
103  for (x = t2 - (tf->xp2 << 1); (x < t2) && (x < t1); x += 2)
104  {
105  ybuf[y + x + 0] = Y_black;
106  ybuf[y + x + 1] = Y_black;
107  }
108  }
109 
110  // Chroma left and right
111  sz = (frame->pitches[1] * (frame->height >> 1)) >> 3; // div 8 bytes
112  t1 = (frame->pitches[1] * ((frame->height >> 4) - tf->yp2) << 2) >> 2;
113  t2 = frame->pitches[1] >> 3;
114  for (y = (frame->pitches[1] * tf->yp1) >> 1; (y < t1) && (y < sz); y += t2)
115  {
116  for (x = 0; x < tf->xp1; x++)
117  {
118  ubuf[y + x] = UV_black;
119  vbuf[y + x] = UV_black;
120  }
121 
122  for (x = t2 - tf->xp2; x < t2; x++)
123  {
124  ubuf[y + x] = UV_black;
125  vbuf[y + x] = UV_black;
126  }
127  }
128 
129  TF_END(tf, "Crop: ");
130  return 0;
131 }
132 
133 #ifdef MMX
134 static int cropMMX(VideoFilter *f, VideoFrame *frame, int field)
135 {
136  (void)field;
137  ThisFilter *tf = (ThisFilter*) f;
138  uint64_t *ybuf = (uint64_t*) (frame->buf + frame->offsets[0]);
139  uint64_t *ubuf = (uint64_t*) (frame->buf + frame->offsets[1]);
140  uint64_t *vbuf = (uint64_t*) (frame->buf + frame->offsets[2]);
141  const uint64_t Y_black = 0x1010101010101010LL;
142  const uint64_t UV_black = 0x8080808080808080LL;
143  int x, y, sz, t1, t2;
144 
145  TF_VARS;
146 
147  TF_START;
148 
149  if (frame->pitches[1] != frame->pitches[2])
150  return -1;
151 
152  __asm__ volatile("emms\n\t");
153 
154  __asm__ volatile("movq (%1),%%mm0 \n\t"
155  "movq (%0),%%mm1 \n\t"
156  : : "r" (&UV_black), "r"(&Y_black));
157 
158  // Luma top
159  sz = (frame->pitches[0] * frame->height) >> 3; // div 8 bytes
160  for (y = 0; (y < tf->yp1 * frame->pitches[0] << 1) && (y < sz); y += 2)
161  {
162  __asm__ volatile("movq %%mm0, (%0) \n\t"
163  "movq %%mm0, 8(%0) \n\t"
164  : : "r" (ybuf + y));
165  }
166 
167  // Luma bottom
168  for (y = ((frame->height >> 4) - tf->yp2) * frame->pitches[0] << 1;
169  y < sz; y += 2)
170  {
171  __asm__ volatile("movq %%mm0, (%0) \n\t"
172  "movq %%mm0, 8(%0) \n\t"
173  : : "r" (ybuf + y));
174  }
175 
176  // Chroma top
177  sz = (frame->pitches[1] * (frame->height >> 1)) >> 3; // div 8 bytes
178  for (y = 0; (y < tf->yp1 * frame->pitches[1]) && (y < sz); y++)
179  {
180  __asm__ volatile("movq %%mm1, (%0) \n\t"
181  "movq %%mm1, (%1) \n\t"
182  : : "r" (ubuf + y), "r" (vbuf + y));
183  }
184 
185  // Chroma bottom
186  for (y = ((frame->height >> 4) - tf->yp2) * frame->pitches[1]; y < sz; y++)
187  {
188  __asm__ volatile("movq %%mm1, (%0) \n\t"
189  "movq %%mm1, (%1) \n\t"
190  : : "r" (ubuf + y), "r" (vbuf + y));
191  }
192 
193  // Luma left and right
194  sz = (frame->pitches[0] * frame->height) >> 3; // div 8 bytes
195  t1 = frame->pitches[0] << 1;
196  t2 = frame->pitches[0] >> 3;
197  for (y = tf->yp1 * t1;
198  (y < ((frame->height >> 4) - tf->yp2) * t1) && (y < sz); y += t2)
199  {
200  for (x = 0; (x < (tf->xp1 << 1)) && (x < t1); x += 2)
201  {
202  __asm__ volatile("movq %%mm0, (%0) \n\t"
203  "movq %%mm0, 8(%0) \n\t"
204  : : "r" (ybuf + y + x));
205  }
206 
207  for (x = t2 - (tf->xp2 << 1); (x < t2) && (x < t1); x += 2)
208  {
209  __asm__ volatile("movq %%mm0, (%0) \n\t"
210  "movq %%mm0, 8(%0) \n\t"
211  : : "r" (ybuf + y + x));
212  }
213  }
214 
215  // Chroma left and right
216  sz = (frame->pitches[1] * (frame->height >> 1)) >> 3; // div 8 bytes
217  t1 = (frame->pitches[1] * ((frame->height >> 4) - tf->yp2) << 2) >> 2;
218  t2 = frame->pitches[1] >> 3;
219  for (y = (frame->pitches[1] * tf->yp1) >> 1; (y < t1) && (y < sz); y += t2)
220  {
221  for (x = 0; x < tf->xp1; x++)
222  {
223  __asm__ volatile("movq %%mm1, (%0) \n\t"
224  "movq %%mm1, (%1) \n\t"
225  : : "r" (ubuf + y + x), "r" (vbuf + y + x));
226  }
227 
228  for (x = t2 - tf->xp2; x < t2; x++)
229  {
230  __asm__ volatile("movq %%mm1, (%0) \n\t"
231  "movq %%mm1, (%1) \n\t"
232  : : "r" (ubuf + y + x), "r" (vbuf + y + x));
233  }
234  }
235 
236  __asm__ volatile("emms\n\t");
237 
238  TF_END(tf, "CropMMX: ");
239  return 0;
240 }
241 #endif /* MMX */
242 
244  VideoFrameType outpixfmt,
245  const int *width, const int *height, const char *options,
246  int threads)
247 {
248  ThisFilter *filter;
249 
250  (void) width;
251  (void) height;
252  (void) threads;
253 
254  if (inpixfmt != FMT_YV12 || outpixfmt != FMT_YV12)
255  {
256  fprintf(stderr,
257  "crop: Attempt to initialize with unsupported format\n");
258 
259  return NULL;
260  }
261 
262  filter = malloc(sizeof(ThisFilter));
263  if (filter == NULL)
264  {
265  fprintf(stderr, "crop: Couldn't allocate memory for filter\n");
266  return NULL;
267  }
268 
269  filter->yp1 = filter->yp2 = filter->xp1 = filter->xp2 = 1;
270 
271  if (options)
272  {
273  unsigned int param1, param2, param3, param4;
274  if (sscanf(options, "%20u:%20u:%20u:%20u",
275  &param1, &param2, &param3, &param4) == 4)
276  {
277  filter->yp1 = param1;
278  filter->yp2 = param3;
279  filter->xp1 = param2;
280  filter->xp2 = param4;
281  }
282  }
283 
284  filter->vf.cleanup = NULL;
285  filter->vf.filter = &crop;
286 
287 #ifdef MMX
288  if (av_get_cpu_flags() & AV_CPU_FLAG_MMX)
289  filter->vf.filter = &cropMMX;
290 #endif
291 
292  TF_INIT(filter);
293 
294  return (VideoFilter*) filter;
295 }
296 
297 static FmtConv FmtList[] =
298 {
299  { FMT_YV12, FMT_YV12 },
300  FMT_NULL
301 };
302 
304 {
305  {
307  .name= (char*)"crop",
308  .descript= (char*)"crops picture by macroblock intervals",
309  .formats= FmtList,
310  .libname= NULL
311  },
312  FILT_NULL
313 };
int pitches[3]
Y, U, & V pitches.
Definition: mythframe.h:63
int(* filter)(struct VideoFilter_ *, VideoFrame *, int)
Definition: filter.h:37
init_filter filter_init
Definition: filter.h:28
stderr
Definition: ttvdb.py:1426
#define TF_VARS
Definition: filter.h:112
#define NULL
Definition: H264Parser.h:62
static int crop(VideoFilter *f, VideoFrame *frame, int field)
Definition: filter_crop.c:41
void(* cleanup)(struct VideoFilter_ *)
Definition: filter.h:38
enum FrameType_ VideoFrameType
const FilterInfo filter_table[]
Definition: filter_crop.c:303
int offsets[3]
Y, U, & V offsets.
Definition: mythframe.h:64
VideoFilter vf
Definition: filter_adjust.c:36
static int cropMMX(VideoFilter *f, VideoFrame *frame, int field)
Definition: filter_crop.c:134
int height
Definition: mythframe.h:42
static FmtConv FmtList[]
Definition: filter_crop.c:297
#define FMT_NULL
Definition: filter.h:20
#define TF_END(filter, prefix)
Definition: filter.h:114
static VideoFilter * new_filter(VideoFrameType inpixfmt, VideoFrameType outpixfmt, const int *width, const int *height, const char *options, int threads)
Definition: filter_crop.c:243
#define FILT_NULL
Definition: filter.h:47
struct ThisFilter ThisFilter
#define TF_INIT(filter)
Definition: filter.h:110
#define TF_START
Definition: filter.h:113
unsigned char * buf
Definition: mythframe.h:39