|
MythTV
0.26-pre
|
00001 /* 00002 * Field-order deinterlacer 00003 * 00004 * Written by Paul Gardiner (mythtv@glidos.net), based on overal 00005 * structure of yadif deinterlacer. 00006 */ 00007 #include <stdlib.h> 00008 #include <stdio.h> 00009 00010 #include "config.h" 00011 #if HAVE_STDINT_H 00012 #include <stdint.h> 00013 #endif 00014 #include <inttypes.h> 00015 00016 #include <string.h> 00017 #include <math.h> 00018 00019 #include "filter.h" 00020 #include "frame.h" 00021 00022 #define NREFS 2 00023 #define NCHANS 3 00024 00025 typedef struct ThisFilter 00026 { 00027 VideoFilter vf; 00028 00029 long long last_framenr; 00030 00031 uint8_t *ref[NREFS + 1][NCHANS]; 00032 int stride[NCHANS]; 00033 int8_t got_frames[NREFS + 1]; 00034 00035 int width; 00036 int height; 00037 00038 TF_STRUCT; 00039 } ThisFilter; 00040 00041 00042 static void AllocFilter(ThisFilter* filter, int width, int height) 00043 { 00044 int i, j; 00045 if ((width != filter->width) || height != filter->height) 00046 { 00047 for (i = 0; i < NCHANS * NREFS; i++) 00048 { 00049 uint8_t **p = &filter->ref[i / NCHANS][i % NCHANS]; 00050 if (*p) free(*p); 00051 *p = NULL; 00052 } 00053 for (i = 0; i < NCHANS; i++) 00054 { 00055 int is_chroma = !!i; 00056 int w = ((width + 31) & (~31)) >> is_chroma; 00057 int h = ((height + 31) & (~31)) >> is_chroma; 00058 00059 filter->stride[i] = w; 00060 for (j = 0; j < NREFS; j++) 00061 { 00062 filter->ref[j][i] = 00063 (uint8_t*)calloc(w * h * sizeof(uint8_t), 1); 00064 } 00065 } 00066 filter->width = width; 00067 filter->height = height; 00068 memset(filter->got_frames, 0, sizeof(filter->got_frames)); 00069 } 00070 } 00071 00072 static inline void * memcpy_pic(void * dst, const void * src, 00073 int bytesPerLine, int height, 00074 int dstStride, int srcStride) 00075 { 00076 int i; 00077 void *retval = dst; 00078 00079 if (dstStride == srcStride) 00080 { 00081 if (srcStride < 0) 00082 { 00083 src = (const uint8_t*)src + (height - 1) * srcStride; 00084 dst = (uint8_t*)dst + (height - 1) * dstStride; 00085 srcStride = -srcStride; 00086 } 00087 memcpy(dst, src, srcStride * height); 00088 } 00089 else 00090 { 00091 for (i = 0; i < height; i++) 00092 { 00093 memcpy(dst, src, bytesPerLine); 00094 src = (const uint8_t*)src + srcStride; 00095 dst = (uint8_t*)dst + dstStride; 00096 } 00097 } 00098 return retval; 00099 } 00100 00101 static void store_ref(struct ThisFilter *p, uint8_t *src, int src_offsets[3], 00102 int src_stride[3], int width, int height) 00103 { 00104 int i; 00105 00106 memcpy (p->ref[NREFS], p->ref[0], sizeof(uint8_t *) * NCHANS); 00107 memmove(p->ref[0], p->ref[1], sizeof(uint8_t *) * NREFS * NCHANS); 00108 memcpy (&p->got_frames[NREFS], &p->got_frames[0], sizeof(uint8_t)); 00109 memmove(&p->got_frames[0], &p->got_frames[1], sizeof(uint8_t) * NREFS); 00110 00111 for (i = 0; i < NCHANS; i++) 00112 { 00113 int is_chroma = !!i; 00114 memcpy_pic(p->ref[NREFS-1][i], src + src_offsets[i], 00115 width >> is_chroma, height >> is_chroma, 00116 p->stride[i], src_stride[i]); 00117 } 00118 p->got_frames[NREFS - 1] = 1; 00119 } 00120 00121 static void filter_func(struct ThisFilter *p, uint8_t *dst, 00122 int dst_offsets[3], int dst_stride[3], int width, 00123 int height, int parity, int tff, int dirty) 00124 { 00125 int i, y; 00126 uint8_t nr_p, nr_c; 00127 nr_c = NREFS - 1; 00128 nr_p = p->got_frames[NREFS - 2] ? (NREFS - 2) : nr_c; 00129 00130 for (i = 0; i < NCHANS; i++) 00131 { 00132 int is_chroma = !!i; 00133 int w = width >> is_chroma; 00134 int h = height >> is_chroma; 00135 int refs = p->stride[i]; 00136 00137 for (y = 0; y < h; y++) 00138 { 00139 int do_copy = dirty; 00140 uint8_t *dst2 = dst + dst_offsets[i] + y * dst_stride[i]; 00141 uint8_t *src = &p->ref[nr_c][i][y * refs]; 00142 int field = parity ^ tff; 00143 if (((y ^ (1 - field)) & 1) && !parity) 00144 { 00145 src = &p->ref[nr_p][i][y * refs]; 00146 do_copy = 1; 00147 } 00148 if (do_copy) 00149 memcpy(dst2, src, w); 00150 } 00151 } 00152 } 00153 00154 static int FieldorderDeint (VideoFilter * f, VideoFrame * frame, int field) 00155 { 00156 ThisFilter *filter = (ThisFilter *) f; 00157 TF_VARS; 00158 00159 AllocFilter(filter, frame->width, frame->height); 00160 00161 int dirty = 1; 00162 if (filter->last_framenr != frame->frameNumber) 00163 { 00164 if (filter->last_framenr != (frame->frameNumber - 1)) 00165 { 00166 memset(filter->got_frames, 0, sizeof(filter->got_frames)); 00167 } 00168 store_ref(filter, frame->buf, frame->offsets, 00169 frame->pitches, frame->width, frame->height); 00170 dirty = 0; 00171 } 00172 00173 filter_func( 00174 filter, frame->buf, frame->offsets, frame->pitches, 00175 frame->width, frame->height, field, frame->top_field_first, 00176 dirty); 00177 00178 filter->last_framenr = frame->frameNumber; 00179 00180 return 0; 00181 } 00182 00183 00184 static void CleanupFieldorderDeintFilter(VideoFilter * filter) 00185 { 00186 int i; 00187 ThisFilter* f = (ThisFilter*)filter; 00188 for (i = 0; i < NCHANS * NREFS; i++) 00189 { 00190 uint8_t **p= &f->ref[i / NCHANS][i % NCHANS]; 00191 if (*p) free(*p); 00192 *p= NULL; 00193 } 00194 } 00195 00196 static VideoFilter *FieldorderDeintFilter(VideoFrameType inpixfmt, 00197 VideoFrameType outpixfmt, 00198 int *width, int *height, 00199 char *options, int threads) 00200 { 00201 ThisFilter *filter; 00202 (void) height; 00203 (void) options; 00204 00205 filter = (ThisFilter *) malloc (sizeof(ThisFilter)); 00206 if (filter == NULL) 00207 { 00208 fprintf (stderr, "FieldorderDeint: failed to allocate memory for filter.\n"); 00209 return NULL; 00210 } 00211 00212 filter->width = 0; 00213 filter->height = 0; 00214 memset(filter->ref, 0, sizeof(filter->ref)); 00215 00216 AllocFilter(filter, *width, *height); 00217 00218 filter->vf.filter = &FieldorderDeint; 00219 filter->vf.cleanup = &CleanupFieldorderDeintFilter; 00220 return (VideoFilter *) filter; 00221 } 00222 00223 static FmtConv FmtList[] = 00224 { 00225 { FMT_YV12, FMT_YV12 } , 00226 FMT_NULL 00227 }; 00228 00229 ConstFilterInfo filter_table[] = 00230 { 00231 { 00232 filter_init: &FieldorderDeintFilter, 00233 name: "fieldorderdoubleprocessdeint", 00234 descript: "avoids synchronisation problems when matching an " 00235 "interlaced video mode to an interlaced source", 00236 formats: FmtList, 00237 libname: NULL 00238 }, FILT_NULL 00239 }; 00240 00241 /* vim: set expandtab tabstop=4 shiftwidth=4: */
1.7.6.1