|
MythTV
0.26-pre
|
00001 /* taken from mplayer */ 00002 /* inverse telecine video filter */ 00003 /* requires MMX support to work */ 00004 00005 #include <stdlib.h> 00006 #include <stdio.h> 00007 00008 #ifdef HAVE_STDINT_H 00009 #include <stdint.h> 00010 #endif 00011 00012 #include <string.h> 00013 00014 #include "config.h" 00015 #include "filter.h" 00016 #include "frame.h" 00017 00018 #include "pullup.h" 00019 00020 typedef struct ThisFilter 00021 { 00022 VideoFilter vf; 00023 00024 struct pullup_context *context; 00025 int height; 00026 int width; 00027 int progressive_frame_seen; 00028 int interlaced_frame_seen; 00029 int apply_filter; 00030 } ThisFilter; 00031 00032 static void SetupFilter(ThisFilter *vf, int width, int height, int *pitches); 00033 00034 static inline void * memcpy_pic(void * dst, const void * src, int height, int dstStride, int srcStride) 00035 { 00036 void *retval=dst; 00037 00038 if (dstStride == srcStride) 00039 { 00040 memcpy(dst, src, srcStride*height); 00041 } 00042 00043 return retval; 00044 } 00045 00046 static int 00047 IvtcFilter (VideoFilter *vf, VideoFrame *frame, int field) 00048 { 00049 (void)field; 00050 ThisFilter *filter = (ThisFilter *) vf; 00051 00052 if (!frame->interlaced_frame) 00053 { 00054 filter->progressive_frame_seen = 1; 00055 } 00056 00057 if (filter->progressive_frame_seen && 00058 frame->interlaced_frame) 00059 { 00060 filter->interlaced_frame_seen = 1; 00061 } 00062 00063 if (!frame->interlaced_frame && 00064 !filter->apply_filter && 00065 filter->interlaced_frame_seen && 00066 filter->progressive_frame_seen) 00067 { 00068 fprintf(stderr,"turning on inverse telecine filter"); 00069 filter->apply_filter = 1; 00070 } 00071 00072 if (!filter->apply_filter) 00073 return 1; 00074 00075 SetupFilter(filter, frame->width, frame->height, (int*)frame->pitches); 00076 00077 struct pullup_buffer *b; 00078 struct pullup_frame *f; 00079 int ypitch = filter->context->stride[0]; 00080 int height = filter->height; 00081 int cpitch = filter->context->stride[1]; 00082 int cheight = filter->height >> 1; 00083 int p = frame->top_field_first ^ 1; 00084 00085 struct pullup_context *c = filter->context; 00086 if (c->bpp[0] == 0) 00087 c->bpp[0] = c->bpp[1] = c->bpp[2] = frame->bpp; 00088 00089 b = pullup_get_buffer(c,2); 00090 if (!b) 00091 { 00092 f = pullup_get_frame(c); 00093 pullup_release_frame(f); 00094 return 0; 00095 } 00096 00097 memcpy_pic(b->planes[0], frame->buf + frame->offsets[0], 00098 height, ypitch, ypitch); 00099 memcpy_pic(b->planes[1], frame->buf + frame->offsets[1], 00100 cheight, cpitch, cpitch); 00101 memcpy_pic(b->planes[2], frame->buf + frame->offsets[2], 00102 cheight, cpitch, cpitch); 00103 00104 pullup_submit_field(c, b, p); 00105 pullup_submit_field(c, b, p^1); 00106 if (frame->repeat_pict) 00107 pullup_submit_field(c, b, p); 00108 00109 pullup_release_buffer(b, 2); 00110 00111 f = pullup_get_frame(c); 00112 00113 if (!f) 00114 return 0; 00115 00116 00117 if (f->length < 2) 00118 { 00119 pullup_release_frame(f); 00120 f = pullup_get_frame(c); 00121 if (!f) 00122 return 0; 00123 if (f->length < 2) 00124 { 00125 pullup_release_frame(f); 00126 if (!frame->repeat_pict) 00127 return 0; 00128 f = pullup_get_frame(c); 00129 if (!f) 00130 return 0; 00131 if (f->length < 2) 00132 { 00133 pullup_release_frame(f); 00134 return 0; 00135 } 00136 } 00137 } 00138 00139 if (!f->buffer) 00140 { 00141 pullup_pack_frame(c, f); 00142 } 00143 00144 if (!f->buffer) 00145 return 0; 00146 00147 memcpy_pic(frame->buf + frame->offsets[0], f->buffer->planes[0], 00148 height, ypitch, ypitch); 00149 memcpy_pic(frame->buf + frame->offsets[1], f->buffer->planes[1], 00150 cheight, cpitch, cpitch); 00151 memcpy_pic(frame->buf + frame->offsets[2], f->buffer->planes[2], 00152 cheight, cpitch, cpitch); 00153 00154 pullup_release_frame(f); 00155 00156 return 1; 00157 } 00158 00159 static void 00160 IvtcFilterCleanup( VideoFilter * filter) 00161 { 00162 pullup_free_context((((ThisFilter *)filter)->context)); 00163 } 00164 00165 static void SetupFilter(ThisFilter *vf, int width, int height, int *pitches) 00166 { 00167 if (vf->width == width && 00168 vf->height == height && 00169 vf->context->stride[0] == pitches[0] && 00170 vf->context->stride[1] == pitches[1] && 00171 vf->context->stride[2] == pitches[2]) 00172 { 00173 return; 00174 } 00175 00176 vf->width = width; 00177 vf->height = height; 00178 00179 vf->context->w[0] = width; 00180 vf->context->w[1] = width >> 1; 00181 vf->context->w[2] = width >> 1; 00182 vf->context->w[3] = 0; 00183 vf->context->h[0] = height; 00184 vf->context->h[1] = height >> 1; 00185 vf->context->h[2] = height >> 1; 00186 vf->context->h[3] = 0; 00187 vf->context->stride[0] = pitches[0]; 00188 vf->context->stride[1] = pitches[1]; 00189 vf->context->stride[2] = pitches[2]; 00190 vf->context->stride[3] = 0; 00191 } 00192 00193 static VideoFilter *NewIvtcFilter(VideoFrameType inpixfmt, 00194 VideoFrameType outpixfmt, 00195 int *width, int *height, char *options, 00196 int threads) 00197 { 00198 (void) threads; 00199 00200 ThisFilter *filter; 00201 00202 options = NULL; 00203 if (inpixfmt != FMT_YV12) 00204 return NULL; 00205 if (outpixfmt != FMT_YV12) 00206 return NULL; 00207 00208 filter = malloc (sizeof (ThisFilter)); 00209 00210 if (filter == NULL) 00211 { 00212 fprintf (stderr, "Ivtc: failed to allocate memory for filter\n"); 00213 return NULL; 00214 } 00215 00216 memset(filter, 0, sizeof(ThisFilter)); 00217 filter->progressive_frame_seen = 0; 00218 filter->interlaced_frame_seen = 0; 00219 filter->apply_filter = 0; 00220 filter->context = pullup_alloc_context(); 00221 struct pullup_context *c = filter->context; 00222 c->metric_plane = 0; 00223 c->strict_breaks = 0; 00224 c->junk_left = c->junk_right = 1; 00225 c->junk_top = c->junk_bottom = 4; 00226 c->verbose = 0; 00227 c->format = PULLUP_FMT_Y; 00228 c->nplanes = 4; 00229 pullup_preinit_context(c); 00230 c->bpp[0] = c->bpp[1] = c->bpp[2] = 0; 00231 c->background[1] = c->background[2] = 128; 00232 00233 int pitches[3] = { *width, *width >> 1, *width >> 1 }; 00234 SetupFilter(filter, *width, *height, pitches); 00235 00236 #if HAVE_MMX 00237 c->cpu |= PULLUP_CPU_MMX; 00238 #endif 00239 00240 pullup_init_context(c); 00241 filter->vf.filter = &IvtcFilter; 00242 filter->vf.cleanup = &IvtcFilterCleanup; 00243 return (VideoFilter *) filter; 00244 } 00245 00246 static FmtConv FmtList[] = 00247 { 00248 { FMT_YV12, FMT_YV12 }, 00249 FMT_NULL 00250 }; 00251 00252 ConstFilterInfo filter_table[] = 00253 { 00254 { 00255 filter_init: &NewIvtcFilter, 00256 name: "ivtc", 00257 descript: "inverse telecine filter", 00258 formats: FmtList, 00259 libname: NULL 00260 }, 00261 FILT_NULL 00262 }; 00263
1.7.6.1