MythTV  master
filter_convert.c
Go to the documentation of this file.
1 /* format conversion filter
2 */
3 
4 #include <stdlib.h>
5 #include <stdio.h>
6 
7 #if HAVE_STDINT_H
8 #include <stdint.h>
9 #endif
10 
11 #include <string.h>
12 #include <math.h>
13 
14 #include "filter.h"
15 #include "mythframe.h"
16 
17 /*
18  Disabled conversion filter Oct 2, 2006 -- dtk
19  This filter is broken. First off the conversion is wrong,
20  422P has the same height as YV12 and twice the width in the chroma,
21  this is written as if the chroma is half the height and has the
22  same width as YV12. Second, this filter assumes that the memory
23  of YV12 is in one block, and that we have allocated width * height * 2
24  bytes. In fact if this is an XVideo surface the memory may be in
25  up to three segments, and we only allocate width * height * 3 / 2
26  bytes when it is continuous. In order for this filter to work
27  we need to change the VideoFilter::filter function to take a
28  separate input and output video frames.
29 */
30 
31 typedef struct ThisFilter
32 {
34 
35  int uoff;
36  int cwidth;
37  int cheight;
38  int icsize;
39  int ocsize;
40  int osize;
41  TF_STRUCT;
42 } ThisFilter;
43 
44 static int
45 Cvt422420 (VideoFilter * f, VideoFrame * frame, int field)
46 {
47  (void)field;
48  ThisFilter * filter = (ThisFilter *) f;
49  int X, Y, field;
50  TF_VARS;
51 
52  TF_START;
53  for (field = 0; field < 2; field++)
54  {
55  uchar *lineout = frame->buf + filter->uoff + field * filter->ocsize;
56  uchar *linein0 = frame->buf + filter->uoff + field * filter->icsize;
57  uchar *linein1 = linein0 + filter->cwidth;
58  for (Y = 0; Y < filter->cheight; Y++)
59  {
60  for (X = 0; X < filter->cwidth; X++)
61  lineout[X] = (linein0[X] + linein1[X]) / 2;
62  lineout += filter->cwidth;
63  linein0 += filter->cwidth * 2;
64  linein1 += filter->cwidth * 2;
65  }
66  }
67  frame->size = filter->osize;
68  frame->codec = FMT_YV12;
69  TF_END(filter, "ConvertYUV422P->YV12: ");
70  return 0;
71 }
72 
73 static int
74 Cvt420422 (VideoFilter * f, VideoFrame * frame, int field)
75 {
76  (void)field;
77  ThisFilter * filter = (ThisFilter *) f;
78  int X, Y, field;
79  unsigned char * lineout0, * lineout1, * linein;
80  TF_VARS;
81 
82  TF_START;
83  for (field = 1; field > -1; field--)
84  {
85  lineout0 = frame->buf + filter->uoff + filter->ocsize + field * filter->ocsize;
86  lineout1 = lineout0 + filter->cwidth;
87  linein = frame->buf + filter->uoff + filter->icsize + field * filter->icsize;
88  for (Y = 0; Y < filter->cheight; Y++)
89  {
90  lineout0 -= filter->cwidth * 2;
91  lineout1 -= filter->cwidth * 2;
92  linein -= filter->cwidth;
93  for (X = 0; X < filter->cwidth; X++)
94  lineout0[X] = lineout1[X] = linein[X];
95  }
96  }
97  frame->size = filter->osize;
98  frame->codec = FMT_YUV422P;
99  TF_END(filter, "ConvertYV12->YUV420P: ");
100  return 0;
101 }
102 
103 VideoFilter *
105  int *width, int *height, char *options, int threads)
106 {
107  ThisFilter *filter;
108 
109  (void) threads;
110  (void) options;
111  if ((inpixfmt != FMT_YUV422P || outpixfmt != FMT_YV12) &&
112  (inpixfmt != FMT_YV12 || outpixfmt != FMT_YUV422P) &&
113  (inpixfmt != outpixfmt))
114  return NULL;
115 
116  filter = malloc (sizeof (ThisFilter));
117  if (filter == NULL)
118  {
119  fprintf (stderr, "Convert: failed to allocate memory for filter\n");
120  return NULL;
121  }
122 
123  if (inpixfmt == FMT_YV12 && outpixfmt == FMT_YUV422P)
124  {
125  filter->vf.filter = &Cvt420422;
126  filter->uoff = *width * *height;
127  filter->cwidth = *width / 2;
128  filter->cheight = *height / 2;
129  filter->icsize = *width * *height / 4;
130  filter->ocsize = *width * *height / 2;
131  filter->osize = *width * *height * 2;
132  }
133  else if (inpixfmt == FMT_YUV422P && outpixfmt == FMT_YV12)
134  {
135  filter->vf.filter = &Cvt422420;
136  filter->uoff = *width * *height;
137  filter->cwidth = *width / 2;
138  filter->cheight = *height / 2;
139  filter->icsize = *width * *height / 2;
140  filter->ocsize = *width * *height / 4;
141  filter->osize = *width * *height * 3 / 2;
142  }
143  else if (inpixfmt == outpixfmt)
144  filter->vf.filter = NULL;
145  filter->vf.cleanup = NULL;
146  TF_INIT(filter);
147  return (VideoFilter *) filter;
148 }
149 
150 #if 0
151 static FmtConv FmtList[] =
152 {
153  { FMT_YV12, FMT_YUV422P },
154  { FMT_YUV422P, FMT_YV12 },
155  FMT_NULL
156 };
157 
159 {
160  {
162  .name= "convert",
163  .descript= "converts between various video types",
164  .formats= FmtList,
165  .libname= NULL
166  },
167  FILT_NULL
168 };
169 #endif
int(* filter)(struct VideoFilter_ *, VideoFrame *, int)
Definition: filter.h:37
init_filter filter_init
Definition: filter.h:28
stderr
Definition: ttvdb.py:1426
#define TF_VARS
Definition: filter.h:112
#define NULL
Definition: H264Parser.h:62
void(* cleanup)(struct VideoFilter_ *)
Definition: filter.h:38
enum FrameType_ VideoFrameType
FmtConv FmtList[]
static int Cvt422420(VideoFilter *f, VideoFrame *frame, int field)
static int Cvt420422(VideoFilter *f, VideoFrame *frame, int field)
VideoFilter vf
Definition: filter_adjust.c:36
VideoFilter * newConvertFilter(VideoFrameType inpixfmt, VideoFrameType outpixfmt, int *width, int *height, char *options, int threads)
#define FMT_NULL
Definition: filter.h:20
#define TF_END(filter, prefix)
Definition: filter.h:114
#define FILT_NULL
Definition: filter.h:47
#define TF_INIT(filter)
Definition: filter.h:110
const FilterInfo filter_table[]
#define TF_START
Definition: filter.h:113
unsigned char * buf
Definition: mythframe.h:39
struct ThisFilter ThisFilter
VideoFrameType codec
Definition: mythframe.h:38