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