MythTV  0.26-pre
filter_ivtc.c
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends