1 /****************************************************************************
2 * yuvinactive.c
3 * Copyright (C) 2003 Bernhard Praschinger
4 *
5 * Sets a area in the yuv frame to black
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 *****************************************************************************/
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <signal.h>
32 #include <string.h>
33 #include "yuv4mpeg.h"
34
35 #define LUMA 16
36 #define CHROMA 128
37
38 /* some defintions */
39 struct area_s {
40 int width; /**< width of the area */
41 int height; /**< height of the area */
42 int voffset; /**< vertical offset from the top left boarder */
43 int hoffset; /**< horizontal offest from the top left boarder */
44 };
45
46 struct color_yuv {
47 int luma; /**< the luma to use */
48 int chroma_b; /**< the chroma Cb to use */
49 int chroma_r; /**< the chroma Cr to use */
50 };
51
52 int verbose = 1;
53
54 /* protoypes */
55 static void print_usage(char *progname);
56 void copy_area(struct area_s , int , int , uint8_t *frame[], int );
57 void process_commandline(int argc, char *argv[], struct area_s *inarea,
58 int *darker, int *copy_pixel, struct color_yuv *coloryuv, int *average_pixel);
59 void fillarea(char area[20], struct area_s *inarea);
60 void set_darker(struct area_s inarea, int horz, int vert, uint8_t *frame[], int darker);
61 void set_inactive(struct area_s inarea, int horz, int vert, uint8_t *frame[], struct color_yuv *coloryuv);
62 void set_yuvcolor(char area[20], struct color_yuv *coloryuv);
63 void average_area(struct area_s inarea, int horz, int vert, uint8_t *frame[], int average_pixel);
64 void average_block(int go_h, int go_w, int horz, int plane, int *orig_offset, uint8_t *frame[]);
65
66 /* Here we start the programm */
67
68 /** The typical help output */
print_usage(char * progname)69 static void print_usage(char *progname)
70 {
71 fprintf(stderr, "%s usage: -i XxY+XOFF+YOFF\n\n",progname);
72 fprintf(stderr, " -h -H - print out this help\n");
73 fprintf(stderr, " -i X+Y+XOFF+YOFF - the area which will be set inactive, from top left\n");
74 fprintf(stderr, " - X=Width, Y=Height, XOFF=VerticalOffset, YOFF=HorizonalOffset\n");
75 fprintf(stderr, " -s luma,Cb,Cr - set the filling color in yuv format\n");
76 fprintf(stderr, " -d num [1-100] - set how much darker the area will be, in percent\n");
77 fprintf(stderr, " -c num - copy num sourrounding lines into the area\n");
78 fprintf(stderr, " -a num - use num pixles for on square to average the area\n");
79 fprintf(stderr, "\n");
80 exit(1);
81 }
82
83 /** Here we process the command line options */
process_commandline(int argc,char * argv[],struct area_s * inarea,int * darker,int * copy_pixel,struct color_yuv * coloryuv,int * average_pixel)84 void process_commandline(int argc, char *argv[], struct area_s *inarea,
85 int *darker, int *copy_pixel, struct color_yuv *coloryuv, int *average_pixel)
86 {
87 int c;
88 char area [20];
89
90 while ((c = getopt(argc, argv, "Hhv:i:s:d:c:a:")) != -1)
91 {
92 switch (c)
93 {
94 case 'v':
95 verbose = atoi(optarg);
96 if ( verbose < 0 || verbose > 2)
97 print_usage(argv[0]);
98 if (verbose == 2)
99 mjpeg_info("Set Verbose = %i", verbose);
100 break;
101 case 'i':
102 strncpy(area, optarg, 20); /* This part shows how to process */
103 fillarea(area, inarea); /* command line options */
104 break;
105 case 's':
106 strncpy(area, optarg, 20);
107 set_yuvcolor(area, coloryuv);
108 break;
109 case 'd':
110 *darker = atoi(optarg);
111 break;
112 case 'c':
113 *copy_pixel = atoi(optarg);
114 break;
115 case 'a':
116 *average_pixel = atoi(optarg);
117 break;
118 case 'H':
119 case 'h':
120 print_usage(argv[0]);
121 }
122 }
123
124 /* Checking if we have used the -i option */
125 if ( ((*inarea).height == 0) && ((*inarea).width == 0) )
126 mjpeg_error_exit1("You have to use the -i option");
127
128 /* Checking the range of the darker -d option */
129 if ( (*darker < 0) || (*darker > 100) )
130 mjpeg_error_exit1("You can only make the area 1-100 percent darker");
131 else
132 mjpeg_info("Setting the area %i percent darker", *darker);
133
134 /* Checking the copy pixel option */
135 if (*copy_pixel != 0)
136 {
137 if ( ((*inarea).height/2) < *copy_pixel)
138 {
139 mjpeg_error("You can only copy half of the height into the area");
140 mjpeg_error_exit1("lower the copy pixel value below: %i ",
141 ((*inarea).height/2));
142 }
143
144 if ( (*copy_pixel % 2) != 0)
145 mjpeg_error_exit1("you have to use a even number of lines to copy into the field");
146
147 if ( ((*inarea).height % *copy_pixel) != 0)
148 mjpeg_error_exit1("the height has to be a multiply of the copy pixel value");
149
150 mjpeg_info("Number of rows using for coping into the area %i", *copy_pixel);
151 }
152
153 /* Checking the average pixel option */
154 if (*average_pixel != 0)
155 {
156 if ( (*average_pixel > (*inarea).height) ||
157 (*average_pixel > (*inarea).width) )
158 mjpeg_error_exit1("The pixles used for the average must be less the the inactive area");
159
160 if ( (*average_pixel % 2) != 0)
161 mjpeg_error_exit1("you have to use a even number for the average pixels");
162
163 mjpeg_info("Number of pixels used for averaging %i", *average_pixel);
164 }
165 }
166
167 /** Here we set the color to use for filling the area */
set_yuvcolor(char area[20],struct color_yuv * coloryuv)168 void set_yuvcolor(char area[20], struct color_yuv *coloryuv)
169 {
170 int i;
171 unsigned int u1, u2, u3;
172
173 i = sscanf (area, "%i,%i,%i", &u1, &u2, &u3);
174
175 if ( 3 == i )
176 {
177 (*coloryuv).luma = u1;
178 (*coloryuv).chroma_b = u2;
179 (*coloryuv).chroma_r = u3;
180 if ( ((*coloryuv).luma > 235) || ((*coloryuv).luma < 16) )
181 mjpeg_error_exit1("out of range value for luma given: %i, \n"
182 " allowed values 16-235", (*coloryuv).luma);
183 if ( ((*coloryuv).chroma_b > 240) || ((*coloryuv).chroma_b < 16) )
184 mjpeg_error_exit1("out of range value for Cb given: %i, \n"
185 " allowed values 16-240", (*coloryuv).chroma_b);
186 if ( ((*coloryuv).chroma_r > 240) || ((*coloryuv).chroma_r < 16) )
187 mjpeg_error_exit1("out of range value for Cr given: %i, \n"
188 " allowed values 16-240", (*coloryuv).chroma_r);
189
190 mjpeg_info("got luma %i, Cb %i, Cr %i ",
191 (*coloryuv).luma, (*coloryuv).chroma_b, (*coloryuv).chroma_r );
192 }
193 else
194 mjpeg_error_exit1("Wrong number of colors given, %s", area);
195 }
196
197 /** Here we cut out the number of the area string */
fillarea(char area[20],struct area_s * inarea)198 void fillarea(char area[20], struct area_s *inarea)
199 {
200 int i;
201 unsigned int u1, u2, u3, u4;
202
203 /* Cuting out the numbers of the stream */
204 i = sscanf (area, "%ix%i+%i+%i", &u1, &u2, &u3, &u4);
205
206 if ( 4 == i) /* Checking if we have got 4 numbers */
207 {
208 (*inarea).width = u1;
209 (*inarea).height = u2;
210 (*inarea).hoffset = u3;
211 (*inarea).voffset = u4;
212
213 if ( (((*inarea).width % 2) != 0) || (((*inarea).height % 2) != 0) ||
214 (((*inarea).hoffset% 2)!= 0) || (((*inarea).voffset% 2) != 0) )
215 mjpeg_error_exit1("At least one argument no even number");
216
217 if (verbose >= 1)
218 mjpeg_info("got the area : W %i, H %i, Xoff %i, Yoff %i",
219 (*inarea).width,(*inarea).height,(*inarea).hoffset,(*inarea).voffset);
220 }
221 else
222 mjpeg_error_exit1("Wrong inactive sting given: %s", area);
223
224 }
225
226 /** Here we copy the surrounding information into the area */
copy_area(struct area_s inarea,int horz,int vert,uint8_t * frame[],int copy_pixel)227 void copy_area(struct area_s inarea, int horz, int vert, uint8_t *frame[],
228 int copy_pixel)
229 {
230 uint8_t *plane_l, *plane_cb, *plane_cr;
231 unsigned char *temp_pix_l, *temp_pix_cb, *temp_pix_cr;
232 int i,j, offset_pix, copy_offset_pix, chroma_lines;
233
234 temp_pix_l = (unsigned char *)malloc(inarea.width);
235 temp_pix_cb = (unsigned char *)malloc(inarea.width/2);
236 temp_pix_cr = (unsigned char *)malloc(inarea.width/2);
237
238 plane_l = frame[0];
239 plane_cb = frame[1];
240 plane_cr = frame[2];
241
242 /* In the first step we copy the luma data*/
243 offset_pix = (horz * inarea.voffset) + inarea.hoffset;
244 i=0;
245 while (i < (inarea.height/2)) /* copying lines from the top down */
246 {
247 copy_offset_pix = (horz * (inarea.voffset - copy_pixel) + inarea.hoffset);
248
249 for (j = 0; j < copy_pixel; j++)
250 {
251 memcpy(temp_pix_l, (plane_l+(copy_offset_pix+(j*horz))), inarea.width);
252 memcpy((plane_l+offset_pix), temp_pix_l, inarea.width);
253 offset_pix += horz;
254 //mjpeg_info("copy_offset %i, offset %i von j %i, von i %i", copy_offset_pix, offset_pix, j ,i);
255 }
256 i += copy_pixel; /* we copy more lines in one step */
257 }
258
259 while (i < inarea.height) /* copying lines from the bottom up */
260 {
261 copy_offset_pix = (horz * (inarea.voffset + inarea.height) + inarea.hoffset);
262
263 for (j = 0; j < copy_pixel; j++)
264 {
265 memcpy(temp_pix_l, (plane_l+copy_offset_pix+(j*horz)), inarea.width);
266 memcpy((plane_l+offset_pix), temp_pix_l, inarea.width);
267 offset_pix += horz;
268 // mjpeg_info("wert von offset_pix %i, von j %i, von i %i", copy_offset_pix, j ,i);
269 }
270 i += copy_pixel; /* we copy more lines in one step */
271 }
272
273 /* In the 2nd step we copy the chroma data */
274 offset_pix = (horz * inarea.voffset)/4 + (inarea.hoffset/2);
275
276 if ((inarea.height%4) != 0)
277 chroma_lines = ((inarea.height/2 -1) /2);
278 else
279 chroma_lines = inarea.height /4;
280
281 i=0;
282 while ( i < chroma_lines)
283 {
284 copy_offset_pix = ((horz/2) * (inarea.voffset/2 + inarea.height/2)
285 + inarea.hoffset/2);
286
287 for (j = 0; j < (copy_pixel/2); j++)
288 {
289 memcpy(temp_pix_cb,(plane_cb+copy_offset_pix+(j*horz)),(inarea.width/2));
290 memcpy((plane_cb+offset_pix), temp_pix_cb, (inarea.width/2));
291 memcpy(temp_pix_cr,(plane_cr+copy_offset_pix+(j*horz)),(inarea.width/2));
292 memcpy((plane_cr+offset_pix), temp_pix_cr, (inarea.width/2));
293 offset_pix += (horz/2);
294 }
295 i += (copy_pixel/2); /* we copy more lines in one step */
296 }
297 while ( i < (inarea.height/2))
298 {
299 copy_offset_pix = ((horz/2) * (inarea.voffset/2 + inarea.height/2)
300 + inarea.hoffset/2);
301
302 for (j = 0; j < (copy_pixel/2); j++)
303 {
304 memcpy(temp_pix_cb,(plane_cb+copy_offset_pix+(j*horz)),(inarea.width/2)); memcpy((plane_cb+offset_pix), temp_pix_cb, (inarea.width/2));
305 memcpy(temp_pix_cr,(plane_cr+copy_offset_pix+(j*horz)),(inarea.width/2)); memcpy((plane_cr+offset_pix), temp_pix_cr, (inarea.width/2));
306 offset_pix += (horz/2);
307 }
308 i += (copy_pixel/2); /* we copy more lines in one step */
309 }
310
311 free(temp_pix_l);
312 temp_pix_l = NULL;
313 free(temp_pix_cb);
314 temp_pix_cb = NULL;
315 free(temp_pix_cr);
316 temp_pix_cr = NULL;
317 }
318
319 /** Here we set a n x n area to a average color */
average_block(int go_h,int go_w,int horz,int plane,int * orig_offset,uint8_t * frame[])320 void average_block(int go_h, int go_w, int horz, int plane, int *orig_offset, uint8_t *frame[])
321 {
322 unsigned char *temp_pix;
323 int i, j, summe, offset_pix;
324
325 temp_pix = (unsigned char*)malloc(1);
326 *temp_pix=0;
327 offset_pix = *orig_offset;
328 summe = 0;
329
330 for ( i=0; i < go_h; i++)
331 {
332 for (j=0; j < go_w; j++)
333 {
334 memcpy(temp_pix,(frame[plane]+offset_pix),1);
335 summe += (int)*temp_pix;
336 offset_pix++;
337 }
338 offset_pix += horz - j;
339 }
340
341 *temp_pix = (unsigned char)(summe / (go_h * go_w));
342 offset_pix = *orig_offset;
343
344 for (i = 0; i < go_h; i++)
345 {
346 for (j = 0; j < go_w; j++)
347 memcpy((frame[plane]+offset_pix+j), temp_pix, 1);
348
349 offset_pix += horz;
350 }
351
352 free(temp_pix);
353 temp_pix=NULL;
354 }
355
356 /** Here we average the area */
average_area(struct area_s inarea,int horz,int vert,uint8_t * frame[],int average_pixel)357 void average_area(struct area_s inarea, int horz, int vert, uint8_t *frame[],
358 int average_pixel)
359 {
360 int orig_offset, sub_offset, plane;
361 int go_w, go_h, togo_w, togo_h;
362
363 orig_offset = (horz* inarea.voffset) + inarea.hoffset;
364 sub_offset = ((horz/2) * (inarea.voffset/2)) + (inarea.hoffset/2);
365
366 go_w = average_pixel;
367 go_h = average_pixel;
368 togo_w = inarea.width - go_w ; /* we decrease here one block, else we */
369 togo_h = inarea.height - go_h; /* that solves a problem in the while */
370 plane = 0; /* here we set that we wnat to use the first plane of the frame */
371
372 while ( go_h != 0 )
373 {
374 while ( go_w != 0)
375 {
376 average_block(go_h, go_w, horz, plane, &orig_offset, frame);
377 average_block(go_h/2, go_w/2, horz/2, plane+1, &sub_offset, frame);
378 average_block(go_h/2, go_w/2, horz/2, plane+2, &sub_offset, frame);
379
380 orig_offset += go_w;
381 sub_offset += go_w/2;
382
383 if ( (togo_w - go_w) >= 0 )
384 togo_w -= go_w; /* normal decrease of the square horicontal*/
385 else if (togo_w != 0)
386 {
387 go_w = togo_w; /* the last few pixels */
388 togo_w = 0;
389 }
390 else
391 go_w = 0; /* this row finished averaging the pixels */
392 }
393
394 /* Here we go to the next row we have to average,first line+ (width-1line) */
395 orig_offset = orig_offset+ (horz -inarea.width) + (horz *(average_pixel -1));
396 sub_offset = sub_offset+ ((horz/2) - (inarea.width/2) +
397 ((horz/2) *(average_pixel/2) -1));
398 /* we also have to reset the go_w variable, that cost me hours .... */
399 go_w = average_pixel;
400 togo_w = inarea.width - average_pixel ;
401
402 if ( (togo_h - go_h) >= 0 )
403 togo_h -= go_h; /* normal decrease of the square vertical */
404 else if (togo_h != 0)
405 {
406 go_h = togo_h; /* the last few pixels */
407 togo_h = 0;
408 }
409 else
410 go_h = 0; /* this field finished averaging the pixels */
411
412 }
413
414 }
415
416 /** Here we set the area darker, only touching luma */
set_darker(struct area_s inarea,int horz,int vert,uint8_t * frame[],int darker)417 void set_darker(struct area_s inarea, int horz, int vert, uint8_t *frame[],
418 int darker)
419 {
420 int i, n, hoffset_pix;
421 uint8_t *plane_l;
422 unsigned char *temp_pix;
423 unsigned char *pix;
424 float dark;
425
426 dark = 1 - (darker* 0.01);
427
428 temp_pix = (unsigned char *)malloc(1);
429 pix = (unsigned char *)malloc(1);
430 *temp_pix=0;
431 *pix=0;
432
433 /* First we do the luma */
434 plane_l = frame[0];
435 hoffset_pix = (horz * inarea.voffset) + inarea.hoffset;
436
437 for (i = 0; i < inarea.height; i++)
438 {
439 for (n = 0; n < inarea.width; n++)
440 {
441 memcpy( temp_pix, (plane_l+hoffset_pix), 1);
442 *pix = 16 + (int)((*temp_pix - 16) * dark);
443
444 if (*pix < 16 ) /* We take care that we don't produce values */
445 *pix = 16; /* which should not be used */
446
447 memset( (plane_l + hoffset_pix), *pix, 1);
448
449 hoffset_pix++;
450 }
451 hoffset_pix += (horz - inarea.width) ;
452 }
453
454
455 /* And then the Cr and Cb */
456 plane_l = frame[1];
457 hoffset_pix = ((horz/2) * (inarea.voffset/2)) + (inarea.hoffset/2);
458
459 for (i = 0; i < (inarea.height/2); i++)
460 {
461 for (n = 0; n < (inarea.width/2); n++)
462 {
463 memcpy( temp_pix, (plane_l+hoffset_pix), 1);
464 *pix = 128 + (int)((*temp_pix - 128) * dark);
465 memset( (plane_l + hoffset_pix), *pix, 1);
466 hoffset_pix++;
467 }
468 hoffset_pix += ((horz - inarea.width) /2) ;
469 }
470
471 plane_l = frame[2];
472 hoffset_pix = ((horz/2) * (inarea.voffset/2)) + (inarea.hoffset/2);
473
474 for (i = 0; i < (inarea.height/2); i++)
475 {
476 for (n = 0; n < (inarea.width/2); n++)
477 {
478 memcpy( temp_pix, (plane_l+hoffset_pix), 1);
479 *pix = 128 + (int)((*temp_pix - 128) * dark);
480 memset( (plane_l + hoffset_pix), *pix, 1);
481 hoffset_pix++;
482 }
483 hoffset_pix += ((horz - inarea.width) /2) ;
484 }
485
486 free(temp_pix);
487 temp_pix=NULL;
488 free(pix);
489 pix=NULL;
490 }
491
492 /** Here is the first stage of setting the stream to black */
set_inactive(struct area_s inarea,int horz,int vert,uint8_t * frame[],struct color_yuv * coloryuv)493 void set_inactive(struct area_s inarea, int horz, int vert, uint8_t *frame[],
494 struct color_yuv *coloryuv)
495 {
496 int i, hoffset_pix;
497 uint8_t *plane_l, *plane_cb, *plane_cr;
498
499 plane_l = frame[0];
500 plane_cb= frame[1];
501 plane_cr= frame[2];
502
503 /* Number of pixels for the luma */
504 hoffset_pix = (horz * inarea.voffset) + inarea.hoffset;
505
506 for (i = 0; i < inarea.height; i++) /* Setting the Luma */
507 {
508 memset( (plane_l + hoffset_pix), (*coloryuv).luma , (inarea.width) );
509 hoffset_pix += horz;
510 }
511
512 /* Number of pixels chroma */
513 hoffset_pix = ((horz / 2) * (inarea.voffset/2) ) + (inarea.hoffset / 2 );
514
515 for (i = 0; i < (inarea.height/2); i++) /*Setting the chroma */
516 {
517 memset( (plane_cb + hoffset_pix), (*coloryuv).chroma_b, (inarea.width/2) );
518 memset( (plane_cr + hoffset_pix), (*coloryuv).chroma_r, (inarea.width/2) );
519 hoffset_pix += (horz/2);
520 }
521
522 }
523
524 /** MAIN */
main(int argc,char ** argv)525 int main( int argc, char **argv)
526 {
527 int i, frame_count;
528 int horz, vert; /* width and height of the frame */
529 uint8_t *frame[3]; /*pointer to the 3 color planes of the input frame */
530 struct area_s inarea;
531 struct color_yuv coloryuv;
532 int input_fd = 0; /* std in */
533 int output_fd = 1; /* std out */
534 int darker = 0; /* how much darker should the image be */
535 int copy_pixel = 0; /* how much pixels we should use for filling up the area */
536 int average_pixel = 0; /* how much pixel to use for average */
537 y4m_stream_info_t istream, ostream;
538 y4m_frame_info_t iframe;
539
540 inarea.width=0; inarea.height=0; inarea.voffset=0; inarea.hoffset=0;
541
542 coloryuv.luma = LUMA; /*Setting the luma to black */
543 coloryuv.chroma_b = CHROMA; /*Setting the chroma to center, means white */
544 coloryuv.chroma_r = CHROMA; /*Setting the chroma to center, means white */
545
546 (void)mjpeg_default_handler_verbosity(verbose);
547
548 /* processing commandline */
549 process_commandline(argc, argv, &inarea, &darker, ©_pixel, &coloryuv,
550 &average_pixel);
551
552 y4m_init_stream_info(&istream);
553 y4m_init_stream_info(&ostream);
554 y4m_init_frame_info(&iframe);
555
556 /* First read the header of the y4m stream */
557 i = y4m_read_stream_header(input_fd, &istream);
558
559 if ( i != Y4M_OK) /* a basic check if we really have y4m stream */
560 mjpeg_error_exit1("Input stream error: %s", y4m_strerr(i));
561 else
562 {
563 /* Here we copy the input stream info to the output stream info header */
564 y4m_copy_stream_info(&ostream, &istream);
565
566 /* Here we write the new output header to the output fd */
567 y4m_write_stream_header(output_fd, &ostream);
568
569 horz = y4m_si_get_width(&istream); /* get the width of the frame */
570 vert = y4m_si_get_height(&istream); /* get the height of the frame */
571
572 if ( (inarea.width + inarea.hoffset) > horz)
573 mjpeg_error_exit1("Input width and offset larger than framewidth,exit");
574
575 if ( (inarea.height + inarea.voffset) > vert)
576 mjpeg_error_exit1("Input height and offset larger than frameheight,exit");
577
578 /* Here we allocate the memory for on frame */
579 frame[0] = malloc( horz * vert );
580 frame[1] = malloc( (horz/2) * (vert/2) );
581 frame[2] = malloc( (horz/2) * (vert/2) );
582
583 /* Here we set the initial number of of frames */
584 /* We do not need it. Just for showing that is does something */
585 frame_count = 0 ;
586
587 /* This is the main loop here can filters effects, scaling and so
588 on be done with the video frames. Just up to your mind */
589 /* We read now a single frame with the header and check if it does not
590 have any problems or we have alreaddy processed the last without data */
591 while(y4m_read_frame(input_fd, &istream, &iframe, frame) == Y4M_OK)
592 {
593 frame_count++;
594
595 /* You can do something usefull here */
596 if (darker != 0)
597 set_darker(inarea, horz, vert, frame, darker);
598 else if (copy_pixel != 0)
599 copy_area(inarea, horz, vert, frame, copy_pixel);
600 else if (average_pixel != 0)
601 average_area(inarea, horz, vert, frame, average_pixel);
602 else
603 set_inactive(inarea, horz, vert, frame, &coloryuv);
604
605 /* Now we put out the read frame */
606 y4m_write_frame(output_fd, &ostream, &iframe, frame);
607 }
608
609 /* Cleaning up the data structures */
610 y4m_fini_stream_info(&istream);
611 y4m_fini_stream_info(&ostream);
612 y4m_fini_frame_info(&iframe);
613
614 }
615
616 /* giving back the memory to the system */
617 free(frame[0]);
618 frame[0] = 0;
619 free(frame[1]);
620 frame[1] = 0;
621 free(frame[2]);
622 frame[2] = 0;
623
624 exit(0); /* exiting */
625 }
626