00001
00002
00003
00004
00005
00006 #include <stdlib.h>
00007 #include <stdio.h>
00008
00009 #include "config.h"
00010
00011 #if HAVE_STDINT_H
00012 #include <stdint.h>
00013 #endif
00014
00015 #include <string.h>
00016 #include <math.h>
00017
00018 #include "filter.h"
00019 #include "frame.h"
00020
00021 #include "../mm_arch.h"
00022
00023 #include "color.h"
00024
00025 #if ARCH_X86
00026
00027 #include "greedyhmacros.h"
00028
00029 #define MAXCOMB_DEFAULT 5
00030 #define MOTIONTHRESHOLD_DEFAULT 25
00031 #define MOTIONSENSE_DEFAULT 30
00032
00033 static unsigned int GreedyMaxComb = MAXCOMB_DEFAULT;
00034 static unsigned int GreedyMotionThreshold = MOTIONTHRESHOLD_DEFAULT;
00035 static unsigned int GreedyMotionSense = MOTIONSENSE_DEFAULT;
00036
00037 #define IS_MMX
00038 #define SSE_TYPE MMXT
00039 #define FUNCT_NAME greedyh_filter_mmx
00040 #include "greedyh.asm"
00041 #undef SSE_TYPE
00042 #undef IS_MMX
00043 #undef FUNCT_NAME
00044
00045 #define IS_SSE
00046 #define SSE_TYPE SSE
00047 #define FUNCT_NAME greedyh_filter_sse
00048 #include "greedyh.asm"
00049 #undef SSE_TYPE
00050 #undef IS_SSE
00051 #undef FUNCT_NAME
00052
00053 #define IS_3DNOW
00054 #define FUNCT_NAME greedyh_filter_3dnow
00055 #define SSE_TYPE 3DNOW
00056 #include "greedyh.asm"
00057 #undef SSE_TYPE
00058 #undef IS_3DNOW
00059 #undef FUNCT_NAME
00060
00061
00062 #endif
00063
00064
00065
00066 #ifdef MMX
00067 #include "ffmpeg-mmx.h"
00068
00069 static const mmx_t mm_cpool[] =
00070 {
00071 { 0x0000000000000000LL },
00072 };
00073
00074 #else
00075 #define mmx_t int
00076 #endif
00077
00078 typedef struct ThisFilter
00079 {
00080 VideoFilter vf;
00081
00082 long long frames_nr[2];
00083 int8_t got_frames[2];
00084 unsigned char* frames[2];
00085 unsigned char* deint_frame;
00086 long long last_framenr;
00087
00088 int width;
00089 int height;
00090
00091 int mm_flags;
00092 TF_STRUCT;
00093 } ThisFilter;
00094
00095 static void AllocFilter(ThisFilter* filter, int width, int height)
00096 {
00097 if ((width != filter->width) || height != filter->height)
00098 {
00099 printf("greedyhdeint: size changed from %d x %d -> %d x %d\n", filter->width, filter->height, width, height);
00100 if (filter->frames[0])
00101 {
00102 free(filter->frames[0]);
00103 free(filter->frames[1]);
00104 free(filter->deint_frame);
00105 }
00106 filter->frames[0] = malloc(width * height * 2);
00107 filter->frames[1] = malloc(width * height * 2);
00108 memset(filter->frames[0], 0, width * height * 2);
00109 memset(filter->frames[1], 0, width * height * 2);
00110 filter->deint_frame = malloc(width * height * 2);
00111 filter->width = width;
00112 filter->height = height;
00113 memset(filter->got_frames, 0, sizeof(filter->got_frames));
00114 memset(filter->frames_nr, 0, sizeof(filter->frames_nr));
00115 }
00116 }
00117
00118 #include <sys/time.h>
00119 #include <time.h>
00120
00121 static int GreedyHDeint (VideoFilter * f, VideoFrame * frame, int field)
00122 {
00123 ThisFilter *filter = (ThisFilter *) f;
00124 TF_VARS;
00125
00126 int last_frame = 0;
00127 int cur_frame = 0;
00128 int bottom_field = 0;
00129
00130 AllocFilter((ThisFilter*)f, frame->width, frame->height);
00131
00132 if (filter->last_framenr != frame->frameNumber)
00133 {
00134
00135 cur_frame = (filter->last_framenr + 1) & 1;
00136 last_frame = (filter->last_framenr) & 1;
00137
00138 if (filter->last_framenr != (frame->frameNumber - 1))
00139 {
00140 cur_frame = frame->frameNumber & 1;
00141 last_frame = cur_frame;
00142 }
00143 bottom_field = frame->top_field_first? 0 : 1;
00144 switch(frame->codec)
00145 {
00146 case FMT_YV12:
00147
00148
00149 yv12_to_yuy2(
00150 frame->buf + frame->offsets[0], frame->pitches[0],
00151 frame->buf + frame->offsets[1], frame->pitches[1],
00152 frame->buf + frame->offsets[2], frame->pitches[2],
00153 filter->frames[cur_frame], 2 * frame->width,
00154 frame->width, frame->height,
00155 1 - frame->interlaced_frame);
00156 break;
00157 default:
00158 fprintf(stderr, "Unsupported pixel format.\n");
00159 return 0;
00160 }
00161
00162 }
00163 else
00164 {
00165
00166 cur_frame = (filter->last_framenr) & 1;
00167 last_frame = (filter->last_framenr + 1) & 1;
00168 bottom_field = frame->top_field_first? 1 : 0;
00169 }
00170 filter->got_frames[cur_frame] = 1;
00171 filter->frames_nr[cur_frame] = frame->frameNumber;
00172
00173
00174 if (!filter->got_frames[last_frame])
00175 last_frame = cur_frame;
00176
00177 #ifdef MMX
00178
00179 if (filter->mm_flags & AV_CPU_FLAG_SSE)
00180 {
00181 greedyh_filter_sse(
00182 filter->deint_frame, 2 * frame->width,
00183 filter->frames[cur_frame], filter->frames[last_frame],
00184 bottom_field, field, frame->width, frame->height);
00185 }
00186 else if (filter->mm_flags & AV_CPU_FLAG_3DNOW)
00187 {
00188 greedyh_filter_3dnow(
00189 filter->deint_frame, 2 * frame->width,
00190 filter->frames[cur_frame], filter->frames[last_frame],
00191 bottom_field, field, frame->width, frame->height);
00192 }
00193 else if (filter->mm_flags & AV_CPU_FLAG_MMX)
00194 {
00195 greedyh_filter_mmx(
00196 filter->deint_frame, 2 * frame->width,
00197 filter->frames[cur_frame], filter->frames[last_frame],
00198 bottom_field, field, frame->width, frame->height);
00199 }
00200 else
00201 #endif
00202 {
00203
00204 (void) bottom_field;
00205 }
00206
00207 #if 0
00208 apply_chroma_filter(filter->deint_frame, frame->width * 2,
00209 frame->width, frame->height );
00210 #endif
00211
00212
00213 yuy2_to_yv12(
00214 filter->deint_frame, 2 * frame->width,
00215 frame->buf + frame->offsets[0], frame->pitches[0],
00216 frame->buf + frame->offsets[1], frame->pitches[1],
00217 frame->buf + frame->offsets[2], frame->pitches[2],
00218 frame->width, frame->height);
00219
00220 filter->last_framenr = frame->frameNumber;
00221
00222 return 0;
00223 }
00224
00225 static void CleanupGreedyHDeintFilter(VideoFilter * filter)
00226 {
00227 ThisFilter* f = (ThisFilter*)filter;
00228 free(f->deint_frame);
00229 free(f->frames[0]);
00230 free(f->frames[1]);
00231 }
00232
00233 static VideoFilter* GreedyHDeintFilter(VideoFrameType inpixfmt,
00234 VideoFrameType outpixfmt,
00235 int *width, int *height, char *options,
00236 int threads)
00237 {
00238 ThisFilter *filter;
00239 (void) height;
00240 (void) options;
00241 (void) threads;
00242
00243 filter = (ThisFilter *) malloc (sizeof(ThisFilter));
00244 if (filter == NULL)
00245 {
00246 fprintf (stderr, "GreedyHDeint: failed to allocate memory for filter.\n");
00247 return NULL;
00248 }
00249
00250 filter->width = 0;
00251 filter->height = 0;
00252 memset(filter->frames, 0, sizeof(filter->frames));
00253 filter->deint_frame = 0;
00254
00255 AllocFilter(filter, *width, *height);
00256
00257 init_yuv_conversion();
00258 #ifdef MMX
00259 filter->mm_flags = av_get_cpu_flags();
00260 TF_INIT(filter);
00261 #else
00262 filter->mm_flags = 0;
00263 #endif
00264
00265 filter->vf.filter = &GreedyHDeint;
00266 filter->vf.cleanup = &CleanupGreedyHDeintFilter;
00267 return (VideoFilter *) filter;
00268 }
00269
00270 static FmtConv FmtList[] =
00271 {
00272 { FMT_YV12, FMT_YV12 } ,
00273 FMT_NULL
00274 };
00275
00276 ConstFilterInfo filter_table[] =
00277 {
00278 {
00279 filter_init: &GreedyHDeintFilter,
00280 name: "greedyhdeint",
00281 descript: "combines data from several fields to deinterlace with less motion blur",
00282 formats: FmtList,
00283 libname: NULL
00284 },
00285 {
00286 filter_init: &GreedyHDeintFilter,
00287 name: "greedyhdoubleprocessdeint",
00288 descript: "combines data from several fields to deinterlace with less motion blur",
00289 formats: FmtList,
00290 libname: NULL
00291 },FILT_NULL
00292 };
00293
00294