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, &copy_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