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