00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdio.h>
00011
00012 #ifdef HAVE_STDINT_H
00013 #include <stdint.h>
00014 #endif
00015
00016 #include <stdlib.h>
00017 #include <string.h>
00018
00019 #include "config.h"
00020 #include "filter.h"
00021 #include "frame.h"
00022 #include "dsputil.h"
00023
00024 #ifdef MMX
00025 #include "i386/mmx.h"
00026 #endif
00027
00028
00029
00030 typedef struct ThisFilter
00031 {
00032 VideoFilter vf;
00033
00034 int yp1, yp2, xp1, xp2;
00035
00036 TF_STRUCT;
00037
00038 } ThisFilter;
00039
00040 int crop(VideoFilter *f, VideoFrame *frame)
00041 {
00042 ThisFilter *tf = (ThisFilter*) f;
00043 uint64_t *ybuf = (uint64_t*) (frame->buf + frame->offsets[0]);
00044 uint64_t *ubuf = (uint64_t*) (frame->buf + frame->offsets[1]);
00045 uint64_t *vbuf = (uint64_t*) (frame->buf + frame->offsets[2]);
00046 const uint64_t Y_black = 0x1010101010101010LL;
00047 const uint64_t UV_black = 0x8080808080808080LL;
00048 int x, y, sz, t1, t2;
00049
00050 TF_VARS;
00051
00052 TF_START;
00053
00054 if (frame->pitches[1] != frame->pitches[2])
00055 return -1;
00056
00057
00058 sz = (frame->pitches[0] * frame->height) >> 3;
00059 for (y = 0; (y < tf->yp1 * frame->pitches[0] << 1) && (y < sz); y += 2)
00060 {
00061 ybuf[y + 0] = Y_black;
00062 ybuf[y + 1] = Y_black;
00063 }
00064
00065
00066 for (y = ((frame->height >> 4) - tf->yp2) * frame->pitches[0] << 1;
00067 y < sz; y += 2)
00068 {
00069 ybuf[y + 0] = Y_black;
00070 ybuf[y + 1] = Y_black;
00071 }
00072
00073
00074 sz = (frame->pitches[1] * (frame->height >> 1)) >> 3;
00075 for (y = 0; (y < tf->yp1 * frame->pitches[1]) && (y < sz); y++)
00076 {
00077 ubuf[y] = UV_black;
00078 vbuf[y] = UV_black;
00079 }
00080
00081
00082 for (y = ((frame->height >> 4) - tf->yp2) * frame->pitches[1]; y < sz; y++)
00083 {
00084 ubuf[y] = UV_black;
00085 vbuf[y] = UV_black;
00086 }
00087
00088
00089 sz = (frame->pitches[0] * frame->height) >> 3;
00090 t1 = frame->pitches[0] << 1;
00091 t2 = frame->pitches[0] >> 3;
00092 for (y = tf->yp1 * t1;
00093 (y < ((frame->height >> 4) - tf->yp2) * t1) && (y < sz); y += t2)
00094 {
00095 for (x = 0; (x < (tf->xp1 << 1)) && (x < t1); x += 2)
00096 {
00097 ybuf[y + x + 0] = Y_black;
00098 ybuf[y + x + 1] = Y_black;
00099 }
00100
00101 for (x = t2 - (tf->xp2 << 1); (x < t2) && (x < t1); x += 2)
00102 {
00103 ybuf[y + x + 0] = Y_black;
00104 ybuf[y + x + 1] = Y_black;
00105 }
00106 }
00107
00108
00109 sz = (frame->pitches[1] * (frame->height >> 1)) >> 3;
00110 t1 = (frame->pitches[1] * ((frame->height >> 4) - tf->yp2) << 2) >> 2;
00111 t2 = frame->pitches[1] >> 3;
00112 for (y = (frame->pitches[1] * tf->yp1) >> 1; (y < t1) && (y < sz); y += t2)
00113 {
00114 for (x = 0; x < tf->xp1; x++)
00115 {
00116 ubuf[y + x] = UV_black;
00117 vbuf[y + x] = UV_black;
00118 }
00119
00120 for (x = t2 - tf->xp2; x < t2; x++)
00121 {
00122 ubuf[y + x] = UV_black;
00123 vbuf[y + x] = UV_black;
00124 }
00125 }
00126
00127 TF_END(tf, "Crop: ");
00128 return 0;
00129 }
00130
00131 #ifdef MMX
00132 int cropMMX(VideoFilter *f, VideoFrame *frame)
00133 {
00134 ThisFilter *tf = (ThisFilter*) f;
00135 uint64_t *ybuf = (uint64_t*) (frame->buf + frame->offsets[0]);
00136 uint64_t *ubuf = (uint64_t*) (frame->buf + frame->offsets[1]);
00137 uint64_t *vbuf = (uint64_t*) (frame->buf + frame->offsets[2]);
00138 const uint64_t Y_black = 0x1010101010101010LL;
00139 const uint64_t UV_black = 0x8080808080808080LL;
00140 int x, y, sz, t1, t2;
00141
00142 TF_VARS;
00143
00144 TF_START;
00145
00146 if (frame->pitches[1] != frame->pitches[2])
00147 return -1;
00148
00149 asm volatile("emms\n\t");
00150
00151 asm volatile("movq (%1),%%mm0 \n\t"
00152 "movq (%0),%%mm1 \n\t"
00153 : : "r" (&UV_black), "r"(&Y_black));
00154
00155
00156 sz = (frame->pitches[0] * frame->height) >> 3;
00157 for (y = 0; (y < tf->yp1 * frame->pitches[0] << 1) && (y < sz); y += 2)
00158 {
00159 asm volatile("movq %%mm0, (%0) \n\t"
00160 "movq %%mm0, 8(%0) \n\t"
00161 : : "r" (ybuf + y));
00162 }
00163
00164
00165 for (y = ((frame->height >> 4) - tf->yp2) * frame->pitches[0] << 1;
00166 y < sz; y += 2)
00167 {
00168 asm volatile("movq %%mm0, (%0) \n\t"
00169 "movq %%mm0, 8(%0) \n\t"
00170 : : "r" (ybuf + y));
00171 }
00172
00173
00174 sz = (frame->pitches[1] * (frame->height >> 1)) >> 3;
00175 for (y = 0; (y < tf->yp1 * frame->pitches[1]) && (y < sz); y++)
00176 {
00177 asm volatile("movq %%mm1, (%0) \n\t"
00178 "movq %%mm1, (%1) \n\t"
00179 : : "r" (ubuf + y), "r" (vbuf + y));
00180 }
00181
00182
00183 for (y = ((frame->height >> 4) - tf->yp2) * frame->pitches[1]; y < sz; y++)
00184 {
00185 asm volatile("movq %%mm1, (%0) \n\t"
00186 "movq %%mm1, (%1) \n\t"
00187 : : "r" (ubuf + y), "r" (vbuf + y));
00188 }
00189
00190
00191 sz = (frame->pitches[0] * frame->height) >> 3;
00192 t1 = frame->pitches[0] << 1;
00193 t2 = frame->pitches[0] >> 3;
00194 for (y = tf->yp1 * t1;
00195 (y < ((frame->height >> 4) - tf->yp2) * t1) && (y < sz); y += t2)
00196 {
00197 for (x = 0; (x < (tf->xp1 << 1)) && (x < t1); x += 2)
00198 {
00199 asm volatile("movq %%mm0, (%0) \n\t"
00200 "movq %%mm0, 8(%0) \n\t"
00201 : : "r" (ybuf + y + x));
00202 }
00203
00204 for (x = t2 - (tf->xp2 << 1); (x < t2) && (x < t1); x += 2)
00205 {
00206 asm volatile("movq %%mm0, (%0) \n\t"
00207 "movq %%mm0, 8(%0) \n\t"
00208 : : "r" (ybuf + y + x));
00209 }
00210 }
00211
00212
00213 sz = (frame->pitches[1] * (frame->height >> 1)) >> 3;
00214 t1 = (frame->pitches[1] * ((frame->height >> 4) - tf->yp2) << 2) >> 2;
00215 t2 = frame->pitches[1] >> 3;
00216 for (y = (frame->pitches[1] * tf->yp1) >> 1; (y < t1) && (y < sz); y += t2)
00217 {
00218 for (x = 0; x < tf->xp1; x++)
00219 {
00220 asm volatile("movq %%mm1, (%0) \n\t"
00221 "movq %%mm1, (%1) \n\t"
00222 : : "r" (ubuf + y + x), "r" (vbuf + y + x));
00223 }
00224
00225 for (x = t2 - tf->xp2; x < t2; x++)
00226 {
00227 asm volatile("movq %%mm1, (%0) \n\t"
00228 "movq %%mm1, (%1) \n\t"
00229 : : "r" (ubuf + y + x), "r" (vbuf + y + x));
00230 }
00231 }
00232
00233 asm volatile("emms\n\t");
00234
00235 TF_END(tf, "CropMMX: ");
00236 return 0;
00237 }
00238 #endif
00239
00240 VideoFilter *new_filter(VideoFrameType inpixfmt, VideoFrameType outpixfmt,
00241 int *width, int *height, char *options)
00242 {
00243 ThisFilter *filter;
00244
00245 (void) width;
00246 (void) height;
00247
00248 if (inpixfmt != FMT_YV12 || outpixfmt != FMT_YV12)
00249 {
00250 fprintf(stderr,
00251 "crop: Attempt to initialize with unsupported format\n");
00252
00253 return NULL;
00254 }
00255
00256 filter = malloc(sizeof(ThisFilter));
00257 if (filter == NULL)
00258 {
00259 fprintf(stderr, "crop: Couldn't allocate memory for filter\n");
00260 return NULL;
00261 }
00262
00263 filter->yp1 = filter->yp2 = filter->xp1 = filter->xp2 = 1;
00264
00265 if (options)
00266 {
00267 unsigned int param1, param2, param3, param4;
00268 if (sscanf(options, "%u:%u:%u:%u",
00269 ¶m1, ¶m2, ¶m3, ¶m4) == 4)
00270 {
00271 filter->yp1 = param1;
00272 filter->yp2 = param3;
00273 filter->xp1 = param2;
00274 filter->xp2 = param4;
00275 }
00276 }
00277
00278 filter->vf.cleanup = NULL;
00279 filter->vf.filter = &crop;
00280
00281 #ifdef MMX
00282 if (mm_support() & MM_MMX)
00283 filter->vf.filter = &cropMMX;
00284 #endif
00285
00286 TF_INIT(filter);
00287
00288 return (VideoFilter*) filter;
00289 }
00290
00291 static FmtConv FmtList[] =
00292 {
00293 { FMT_YV12, FMT_YV12 },
00294 FMT_NULL
00295 };
00296
00297 FilterInfo filter_table[] =
00298 {
00299 {
00300 symbol: "new_filter",
00301 name: "crop",
00302 descript: "crops picture by macroblock intervals",
00303 formats: FmtList,
00304 libname: NULL
00305 },
00306 FILT_NULL
00307 };