00001
00002
00003
00004
00005 #include <stdlib.h>
00006 #include <stdio.h>
00007
00008 #include "mythconfig.h"
00009 #if HAVE_STDINT_H
00010 #include <stdint.h>
00011 #endif
00012
00013 #include <string.h>
00014
00015 #include "filter.h"
00016 #include "frame.h"
00017
00018 typedef struct BDFilter
00019 {
00020 VideoFilter vf;
00021
00022
00023 unsigned char *tmp_ptr;
00024 int tmp_size;
00025 unsigned char *line_state;
00026 int state_size;
00027 } BDFilter;
00028
00029 #define ODD(_n) (((_n)%2)==1)
00030
00031 static void doSplit(BDFilter *filter, unsigned char *buf, int lines, int width)
00032 {
00033
00034 int i, j, k_start, modv;
00035 unsigned char *line_state = filter->line_state;
00036 unsigned char *tmp = filter->tmp_ptr;
00037
00038 modv = lines - 1;
00039 if (ODD(lines))
00040 modv = lines;
00041 memset(line_state, 0, modv);
00042 k_start = 1;
00043 line_state[0] = 1;
00044 while (k_start < modv)
00045 {
00046 i = j = k_start;
00047 memcpy(tmp, &(buf[i*width]), width);
00048 while (!line_state[j])
00049 {
00050 line_state[j] = 1;
00051 i = j;
00052 j = j * 2 % modv;
00053 memcpy(&(buf[i*width]), &(buf[j*width]), width);
00054 }
00055 memcpy(&(buf[i*width]), tmp, width);
00056 while (k_start < modv && line_state[k_start])
00057 k_start++;
00058 }
00059 }
00060
00061 int bobDeintFilter(VideoFilter *f, VideoFrame *frame, int field)
00062 {
00063 (void)field;
00064 BDFilter *filter = (BDFilter *)(f);
00065 int width = frame->width;
00066 int height = frame->height;
00067 int ymax = height;
00068 int stride = frame->pitches[0];
00069
00070 unsigned char *yoff = frame->buf + frame->offsets[0];
00071 unsigned char *uoff = frame->buf + frame->offsets[1];
00072 unsigned char *voff = frame->buf + frame->offsets[2];
00073
00074 if (filter->tmp_size < width)
00075 {
00076 filter->tmp_ptr = (unsigned char *)realloc(
00077 filter->tmp_ptr, width * sizeof(char));
00078 filter->tmp_size = width;
00079 }
00080 if (filter->state_size < height)
00081 {
00082 filter->line_state = (unsigned char *)realloc(
00083 filter->line_state, height * sizeof(char));
00084 filter->state_size = height;
00085 }
00086
00087 doSplit(filter, yoff, ymax, stride);
00088
00089 stride = frame->pitches[1];
00090 ymax = height >> 1;
00091 doSplit(filter, uoff, ymax, stride);
00092 doSplit(filter, voff, ymax, stride);
00093
00094 return 0;
00095 }
00096
00097 void bobDtor(VideoFilter *f)
00098 {
00099 BDFilter *filter = (BDFilter *)(f);
00100 if (filter->line_state)
00101 free(filter->line_state);
00102 if (filter->tmp_ptr)
00103 free(filter->tmp_ptr);
00104 }
00105
00106 static VideoFilter *new_filter(VideoFrameType inpixfmt,
00107 VideoFrameType outpixfmt,
00108 int *width, int *height, char *options,
00109 int threads)
00110 {
00111 BDFilter *filter;
00112 (void)width;
00113 (void)height;
00114 (void)options;
00115 (void)threads;
00116
00117 if (inpixfmt != FMT_YV12 || outpixfmt != FMT_YV12)
00118 return NULL;
00119
00120 filter = malloc(sizeof(BDFilter));
00121
00122 if (filter == NULL)
00123 {
00124 fprintf(stderr,"Couldn't allocate memory for filter\n");
00125 return NULL;
00126 }
00127
00128 filter->vf.filter = &bobDeintFilter;
00129 filter->tmp_size = 0;
00130 filter->tmp_ptr = NULL;
00131 filter->state_size = 0;
00132 filter->line_state = NULL;
00133 filter->vf.cleanup = &bobDtor;
00134 return (VideoFilter *)filter;
00135 }
00136
00137 static FmtConv FmtList[] =
00138 {
00139 { FMT_YV12, FMT_YV12 },
00140 FMT_NULL
00141 };
00142
00143 ConstFilterInfo filter_table[] =
00144 {
00145 {
00146 filter_init: &new_filter,
00147 name: "bobdeint",
00148 descript: "bob deinterlace filter; splits fields to top and bottom of buffer",
00149 formats: FmtList,
00150 libname: NULL,
00151 },
00152 FILT_NULL
00153 };