1 /*
2  *  filter_testframe.c
3  *
4  *  Copyright (C) Thomas Oestreich - June 2001
5  *
6  *  This file is part of transcode, a video stream processing tool
7  *
8  *  transcode is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2, or (at your option)
11  *  any later version.
12  *
13  *  transcode is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with GNU Make; see the file COPYING.  If not, write to
20  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23 
24 #define MOD_NAME    "filter_testframe.so"
25 #define MOD_VERSION "v0.1.3 (2003-09-04)"
26 #define MOD_CAP     "generate stream of testframes"
27 #define MOD_AUTHOR  "Thomas Oestreich"
28 
29 #include "transcode.h"
30 #include "filter.h"
31 #include "libtc/optstr.h"
32 
33 static int mode=0;
34 static vob_t *vob=NULL;
35 
generate_rgb_frame(char * buffer,int width,int height)36 static void generate_rgb_frame(char *buffer, int width, int height)
37 {
38   int n, j, row_bytes;
39 
40   row_bytes = width*3;
41 
42   memset(buffer, 0, width*height*3);
43 
44   switch(mode) {
45 
46   case 0:
47 
48       for(n=0; n<height; ++n) {
49 
50 	  if(n & 1) {
51 	      for(j=0; j<row_bytes; ++j) buffer[n*row_bytes+j] = 255;
52 	  } else {
53 	      for(j=0; j<row_bytes; ++j) buffer[n*row_bytes+j] = 0;
54 	  }
55       }
56 
57       break;
58 
59   case 1:
60 
61       for(n=0; n<height*width; n=n+2) {
62 	  buffer[n*3]   = 255;
63 	  buffer[n*3+1] = 255;
64 	  buffer[n*3+2] = 255;
65       }
66 
67       break;
68 
69   case 2:  //red picture
70 
71     for(n=0; n<height*width; ++n) {
72       buffer[n*3]   = 255;
73       buffer[n*3+1] = 0;
74       buffer[n*3+2] = 0;
75     }
76     break;
77 
78   case 3:  //green picture
79 
80     for(n=0; n<height*width; ++n) {
81       buffer[n*3]   = 0;
82       buffer[n*3+1] = 255;
83       buffer[n*3+2] = 0;
84     }
85     break;
86   case 4:  //blue
87 
88     for(n=0; n<height*width; ++n) {
89       buffer[n*3]   = 0;
90       buffer[n*3+1] = 0;
91       buffer[n*3+2] = 255;
92     }
93     break;
94   }
95 }
96 
generate_yuv_frame(char * buffer,int width,int height)97 static void generate_yuv_frame(char *buffer, int width, int height)
98 {
99   int n, j, row_bytes;
100 
101   row_bytes = width;
102 
103   memset(buffer, 0x80, width*height*3/2);
104 
105   switch(mode) {
106 
107   case 0:
108 
109       for(n=0; n<height; ++n) {
110 
111 	  if(n & 1) {
112 	      for(j=0; j<row_bytes; ++j) buffer[n*row_bytes+j]   = 255;
113 	  } else {
114 	      for(j=0; j<row_bytes; ++j) buffer[n*row_bytes+j]   = 0;
115 	  }
116       }
117 
118       break;
119 
120   case 1:
121 
122       for(n=0; n<height*width; ++n) buffer[n]=(n&1)?255:0;
123 
124       break;
125 
126   case 5: // from libavformat
127       {
128 	  static int indx = 0;
129 	  int x, y;
130 	  unsigned char
131 	      *Y = buffer,
132 	      *U = Y + width*height,
133 	      *V = U + (width/2)*(height/2);
134 
135 	  for(y=0;y<height;y++) {
136 	      for(x=0;x<width;x++) {
137 		  Y[y * width + x] = x + y + indx * 3;
138 	      }
139 	  }
140 
141 	  /* Cb and Cr */
142 	  for(y=0;y<height/2;y++) {
143 	      for(x=0;x<width/2;x++) {
144 		  U[y * width/2 + x] = 128 + y + indx * 2;
145 		  V[y * width/2 + x] = 64 + x + indx * 5;
146 	      }
147 	  }
148 	  indx++;
149       }
150       break;
151   }
152 }
153 
154 
155 /*-------------------------------------------------
156  *
157  * single function interface
158  *
159  *-------------------------------------------------*/
160 
161 
is_optstr(char * options)162 static int is_optstr(char *options)
163 {
164     if (strchr(options, 'm')) return 1;
165     if (strchr(options, 'h')) return 1;
166     if (strchr(options, '=')) return 1;
167     return 0;
168 }
169 
tc_filter(frame_list_t * ptr_,char * options)170 int tc_filter(frame_list_t *ptr_, char *options)
171 {
172   vframe_list_t *ptr = (vframe_list_t *)ptr_;
173 
174   if(ptr->tag & TC_FILTER_GET_CONFIG) {
175 
176       optstr_filter_desc (options, MOD_NAME, MOD_CAP, MOD_VERSION, "Thomas Oestreich", "VRYE", "1");
177       optstr_param (options, "mode",   "Choose the test pattern (0-4 interlaced, 5 colorfull)", "%d", "0", "0", "5");
178   }
179 
180   //----------------------------------
181   //
182   // filter init
183   //
184   //----------------------------------
185 
186   if(ptr->tag & TC_FILTER_INIT) {
187 
188     if((vob = tc_get_vob())==NULL) return(-1);
189 
190     // filter init ok.
191 
192     if(verbose) tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP);
193 
194     if(verbose) tc_log_info(MOD_NAME, "options=%s", options);
195 
196     if (options) {
197 	if (is_optstr(options)) {
198 	    optstr_get(options, "mode", "%d", &mode);
199 	} else
200 	    sscanf(options, "%d", &mode);
201     }
202 
203     if(mode <0) { tc_log_error(MOD_NAME, "Invalid mode"); return(-1); }
204 
205     return(0);
206   }
207 
208   //----------------------------------
209   //
210   // filter close
211   //
212   //----------------------------------
213 
214   if(ptr->tag & TC_FILTER_CLOSE) {
215     return(0);
216   }
217 
218   //----------------------------------
219   //
220   // filter frame routine
221   //
222   //----------------------------------
223 
224   // tag variable indicates, if we are called before
225   // transcodes internal video/audo frame processing routines
226   // or after and determines video/audio context
227 
228   if(ptr->tag & TC_PRE_M_PROCESS && ptr->tag & TC_VIDEO && !(ptr->attributes & TC_FRAME_IS_SKIPPED)) {
229 
230     if(vob->im_v_codec==CODEC_RGB) {
231       generate_rgb_frame(ptr->video_buf, ptr->v_width, ptr->v_height);
232     } else {
233       generate_yuv_frame(ptr->video_buf, ptr->v_width, ptr->v_height);
234     }
235   }
236   return(0);
237 }
238