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