]> Creatis software - gdcm.git/blob - src/gdcmmpeg2/src/mpeg2dec/store.c
Replace C++ style comments by C style comments, to avoid gcc warnings
[gdcm.git] / src / gdcmmpeg2 / src / mpeg2dec / store.c
1 /* store.c, picture output routines                                         */
2
3 /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
4
5 /*
6  * Disclaimer of Warranty
7  *
8  * These software programs are available to the user without any license fee or
9  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
10  * any and all warranties, whether express, implied, or statuary, including any
11  * implied warranties or merchantability or of fitness for a particular
12  * purpose.  In no event shall the copyright-holder be liable for any
13  * incidental, punitive, or consequential damages of any kind whatsoever
14  * arising from the use of these programs.
15  *
16  * This disclaimer of warranty extends to the user of these programs and user's
17  * customers, employees, agents, transferees, successors, and assigns.
18  *
19  * The MPEG Software Simulation Group does not represent or warrant that the
20  * programs furnished hereunder are free of infringement of any third-party
21  * patents.
22  *
23  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
24  * are subject to royalty fees to patent holders.  Many of these patents are
25  * general enough such that they are unavoidable regardless of implementation
26  * design.
27  *
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <fcntl.h>
33 #include <string.h> /* for strcat */
34
35 #include "config.h"
36 #include "global.h"
37
38 /* private prototypes */
39 static void store_one _ANSI_ARGS_((char *outname, unsigned char *src[],
40   int offset, int incr, int height));
41 static void store_yuv _ANSI_ARGS_((char *outname, unsigned char *src[],
42   int offset, int incr, int height));
43 static void store_sif _ANSI_ARGS_((char *outname, unsigned char *src[],
44   int offset, int incr, int height));
45 static void store_ppm_tga _ANSI_ARGS_((char *outname, unsigned char *src[],
46   int offset, int incr, int height, int tgaflag));
47 static void store_yuv1 _ANSI_ARGS_((char *name, unsigned char *src,
48   int offset, int incr, int width, int height));
49 static void putbyte _ANSI_ARGS_((int c));
50 static void putword _ANSI_ARGS_((int w));
51 static void conv422to444 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
52 static void conv420to422 _ANSI_ARGS_((unsigned char *src, unsigned char *dst));
53
54 #define OBFRSIZE 4096
55 static unsigned char obfr[OBFRSIZE];
56 static unsigned char *optr;
57 static int outfile;
58
59 /*
60  * store a picture as either one frame or two fields
61  */
62 void Write_Frame(src,frame)
63 unsigned char *src[];
64 int frame;
65 {
66   char outname[FILENAME_LENGTH];
67
68   if (progressive_sequence || progressive_frame || Frame_Store_Flag)
69   {
70     /* progressive */
71     sprintf(outname,Output_Picture_Filename,frame,'f');
72     store_one(outname,src,0,Coded_Picture_Width,vertical_size);
73   }
74   else
75   {
76     /* interlaced */
77     sprintf(outname,Output_Picture_Filename,frame,'a');
78     store_one(outname,src,0,Coded_Picture_Width<<1,vertical_size>>1);
79
80     sprintf(outname,Output_Picture_Filename,frame,'b');
81     store_one(outname,src,
82       Coded_Picture_Width,Coded_Picture_Width<<1,vertical_size>>1);
83   }
84 }
85
86 /*
87  * store one frame or one field
88  */
89 static void store_one(outname,src,offset,incr,height)
90 char *outname;
91 unsigned char *src[];
92 int offset, incr, height;
93 {
94   switch (Output_Type)
95   {
96   case T_YUV:
97     store_yuv(outname,src,offset,incr,height);
98     break;
99   case T_SIF:
100     store_sif(outname,src,offset,incr,height);
101     break;
102   case T_TGA:
103     store_ppm_tga(outname,src,offset,incr,height,1);
104     break;
105   case T_PPM:
106     store_ppm_tga(outname,src,offset,incr,height,0);
107     break;
108 #ifdef DISPLAY
109   case T_X11:
110     dither(src);
111     break;
112 #endif
113   default:
114     break;
115   }
116 }
117
118 /* separate headerless files for y, u and v */
119 static void store_yuv(outname,src,offset,incr,height)
120 char *outname;
121 unsigned char *src[];
122 int offset,incr,height;
123 {
124   int hsize;
125   char tmpname[FILENAME_LENGTH];
126
127   hsize = horizontal_size;
128
129   sprintf(tmpname,"%s.Y",outname);
130   store_yuv1(tmpname,src[0],offset,incr,hsize,height);
131
132   if (chroma_format!=CHROMA444)
133   {
134     offset>>=1; incr>>=1; hsize>>=1;
135   }
136
137   if (chroma_format==CHROMA420)
138   {
139     height>>=1;
140   }
141
142   sprintf(tmpname,"%s.U",outname);
143   store_yuv1(tmpname,src[1],offset,incr,hsize,height);
144
145   sprintf(tmpname,"%s.V",outname);
146   store_yuv1(tmpname,src[2],offset,incr,hsize,height);
147 }
148
149 /* auxiliary routine */
150 static void store_yuv1(name,src,offset,incr,width,height)
151 char *name;
152 unsigned char *src;
153 int offset,incr,width,height;
154 {
155   int i, j;
156   unsigned char *p;
157
158   if (!Quiet_Flag)
159     fprintf(stderr,"saving %s\n",name);
160
161   if ((outfile = open(name,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
162   {
163     sprintf(Error_Text,"Couldn't create %s\n",name);
164     Error(Error_Text);
165   }
166
167   optr=obfr;
168
169   for (i=0; i<height; i++)
170   {
171     p = src + offset + incr*i;
172     for (j=0; j<width; j++)
173       putbyte(*p++);
174   }
175
176   if (optr!=obfr)
177     write(outfile,obfr,optr-obfr);
178
179   close(outfile);
180 }
181
182 /*
183  * store as headerless file in U,Y,V,Y format
184  */
185 static void store_sif (outname,src,offset,incr,height)
186 char *outname;
187 unsigned char *src[];
188 int offset, incr, height;
189 {
190   int i,j;
191   unsigned char *py, *pu, *pv;
192   static unsigned char *u422, *v422;
193
194   if (chroma_format==CHROMA444)
195     Error("4:4:4 not supported for SIF format");
196
197   if (chroma_format==CHROMA422)
198   {
199     u422 = src[1];
200     v422 = src[2];
201   }
202   else
203   {
204     if (!u422)
205     {
206       if (!(u422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
207                                            *Coded_Picture_Height)))
208         Error("malloc failed");
209       if (!(v422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
210                                            *Coded_Picture_Height)))
211         Error("malloc failed");
212     }
213   
214     conv420to422(src[1],u422);
215     conv420to422(src[2],v422);
216   }
217
218   strcat(outname,".SIF");
219
220   if (!Quiet_Flag)
221     fprintf(stderr,"saving %s\n",outname);
222
223   if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
224   {
225     sprintf(Error_Text,"Couldn't create %s\n",outname);
226     Error(Error_Text);
227   }
228
229   optr = obfr;
230
231   for (i=0; i<height; i++)
232   {
233     py = src[0] + offset + incr*i;
234     pu = u422 + (offset>>1) + (incr>>1)*i;
235     pv = v422 + (offset>>1) + (incr>>1)*i;
236
237     for (j=0; j<horizontal_size; j+=2)
238     {
239       putbyte(*pu++);
240       putbyte(*py++);
241       putbyte(*pv++);
242       putbyte(*py++);
243     }
244   }
245
246   if (optr!=obfr)
247     write(outfile,obfr,optr-obfr);
248
249   close(outfile);
250 }
251
252 /*
253  * store as PPM (PBMPLUS) or uncompressed Truevision TGA ('Targa') file
254  */
255 static void store_ppm_tga(outname,src,offset,incr,height,tgaflag)
256 char *outname;
257 unsigned char *src[];
258 int offset, incr, height;
259 int tgaflag;
260 {
261   int i, j;
262   int y, u, v, r, g, b;
263   int crv, cbu, cgu, cgv;
264   unsigned char *py, *pu, *pv;
265   static unsigned char tga24[14] = {0,0,2,0,0,0,0, 0,0,0,0,0,24,32};
266   char header[FILENAME_LENGTH];
267   static unsigned char *u422, *v422, *u444, *v444;
268
269   if (chroma_format==CHROMA444)
270   {
271     u444 = src[1];
272     v444 = src[2];
273   }
274   else
275   {
276     if (!u444)
277     {
278       if (chroma_format==CHROMA420)
279       {
280         if (!(u422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
281                                              *Coded_Picture_Height)))
282           Error("malloc failed");
283         if (!(v422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
284                                              *Coded_Picture_Height)))
285           Error("malloc failed");
286       }
287
288       if (!(u444 = (unsigned char *)malloc(Coded_Picture_Width
289                                            *Coded_Picture_Height)))
290         Error("malloc failed");
291
292       if (!(v444 = (unsigned char *)malloc(Coded_Picture_Width
293                                            *Coded_Picture_Height)))
294         Error("malloc failed");
295     }
296
297     if (chroma_format==CHROMA420)
298     {
299       conv420to422(src[1],u422);
300       conv420to422(src[2],v422);
301       conv422to444(u422,u444);
302       conv422to444(v422,v444);
303     }
304     else
305     {
306       conv422to444(src[1],u444);
307       conv422to444(src[2],v444);
308     }
309   }
310
311   strcat(outname,tgaflag ? ".tga" : ".ppm");
312
313   if (!Quiet_Flag)
314     fprintf(stderr,"saving %s\n",outname);
315
316   if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
317   {
318     sprintf(Error_Text,"Couldn't create %s\n",outname);
319     Error(Error_Text);
320   }
321
322   optr = obfr;
323
324   if (tgaflag)
325   {
326     /* TGA header */
327     for (i=0; i<12; i++)
328       putbyte(tga24[i]);
329
330     putword(horizontal_size); putword(height);
331     putbyte(tga24[12]); putbyte(tga24[13]);
332   }
333   else
334   {
335     /* PPM header */
336     sprintf(header,"P6\n%d %d\n255\n",horizontal_size,height);
337
338     for (i=0; header[i]!=0; i++)
339       putbyte(header[i]);
340   }
341
342   /* matrix coefficients */
343   crv = Inverse_Table_6_9[matrix_coefficients][0];
344   cbu = Inverse_Table_6_9[matrix_coefficients][1];
345   cgu = Inverse_Table_6_9[matrix_coefficients][2];
346   cgv = Inverse_Table_6_9[matrix_coefficients][3];
347   
348   for (i=0; i<height; i++)
349   {
350     py = src[0] + offset + incr*i;
351     pu = u444 + offset + incr*i;
352     pv = v444 + offset + incr*i;
353
354     for (j=0; j<horizontal_size; j++)
355     {
356       u = *pu++ - 128;
357       v = *pv++ - 128;
358       y = 76309 * (*py++ - 16); /* (255/219)*65536 */
359       r = Clip[(y + crv*v + 32768)>>16];
360       g = Clip[(y - cgu*u - cgv*v + 32768)>>16];
361       b = Clip[(y + cbu*u + 32786)>>16];
362
363       if (tgaflag)
364       {
365         putbyte(b); putbyte(g); putbyte(r);
366       }
367       else
368       {
369         putbyte(r); putbyte(g); putbyte(b);
370       }
371     }
372   }
373
374   if (optr!=obfr)
375     write(outfile,obfr,optr-obfr);
376
377   close(outfile);
378 }
379
380 static void putbyte(c)
381 int c;
382 {
383   *optr++ = c;
384
385   if (optr == obfr+OBFRSIZE)
386   {
387     write(outfile,obfr,OBFRSIZE);
388     optr = obfr;
389   }
390 }
391
392 static void putword(w)
393 int w;
394 {
395   putbyte(w); putbyte(w>>8);
396 }
397
398 /* horizontal 1:2 interpolation filter */
399 static void conv422to444(src,dst)
400 unsigned char *src,*dst;
401 {
402   int i, i2, w, j, im3, im2, im1, ip1, ip2, ip3;
403
404   w = Coded_Picture_Width>>1;
405
406   if (base.MPEG2_Flag)
407   {
408     for (j=0; j<Coded_Picture_Height; j++)
409     {
410       for (i=0; i<w; i++)
411       {
412         i2 = i<<1;
413         im2 = (i<2) ? 0 : i-2;
414         im1 = (i<1) ? 0 : i-1;
415         ip1 = (i<w-1) ? i+1 : w-1;
416         ip2 = (i<w-2) ? i+2 : w-1;
417         ip3 = (i<w-3) ? i+3 : w-1;
418
419         /* FIR filter coefficients (*256): 21 0 -52 0 159 256 159 0 -52 0 21 */
420         /* even samples (0 0 256 0 0) */
421         dst[i2] = src[i];
422
423         /* odd samples (21 -52 159 159 -52 21) */
424         dst[i2+1] = Clip[(int)(21*(src[im2]+src[ip3])
425                         -52*(src[im1]+src[ip2]) 
426                        +159*(src[i]+src[ip1])+128)>>8];
427       }
428       src+= w;
429       dst+= Coded_Picture_Width;
430     }
431   }
432   else
433   {
434     for (j=0; j<Coded_Picture_Height; j++)
435     {
436       for (i=0; i<w; i++)
437       {
438
439         i2 = i<<1;
440         im3 = (i<3) ? 0 : i-3;
441         im2 = (i<2) ? 0 : i-2;
442         im1 = (i<1) ? 0 : i-1;
443         ip1 = (i<w-1) ? i+1 : w-1;
444         ip2 = (i<w-2) ? i+2 : w-1;
445         ip3 = (i<w-3) ? i+3 : w-1;
446
447         /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
448         dst[i2] =   Clip[(int)(  5*src[im3]
449                          -21*src[im2]
450                          +70*src[im1]
451                         +228*src[i]
452                          -37*src[ip1]
453                          +11*src[ip2]+128)>>8];
454
455        dst[i2+1] = Clip[(int)(  5*src[ip3]
456                          -21*src[ip2]
457                          +70*src[ip1]
458                         +228*src[i]
459                          -37*src[im1]
460                          +11*src[im2]+128)>>8];
461       }
462       src+= w;
463       dst+= Coded_Picture_Width;
464     }
465   }
466 }
467
468 /* vertical 1:2 interpolation filter */
469 static void conv420to422(src,dst)
470 unsigned char *src,*dst;
471 {
472   int w, h, i, j, j2;
473   int jm6, jm5, jm4, jm3, jm2, jm1, jp1, jp2, jp3, jp4, jp5, jp6, jp7;
474
475   w = Coded_Picture_Width>>1;
476   h = Coded_Picture_Height>>1;
477
478   if (progressive_frame)
479   {
480     /* intra frame */
481     for (i=0; i<w; i++)
482     {
483       for (j=0; j<h; j++)
484       {
485         j2 = j<<1;
486         jm3 = (j<3) ? 0 : j-3;
487         jm2 = (j<2) ? 0 : j-2;
488         jm1 = (j<1) ? 0 : j-1;
489         jp1 = (j<h-1) ? j+1 : h-1;
490         jp2 = (j<h-2) ? j+2 : h-1;
491         jp3 = (j<h-3) ? j+3 : h-1;
492
493         /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
494         /* New FIR filter coefficients (*256): 3 -16 67 227 -32 7 */
495         dst[w*j2] =     Clip[(int)(  3*src[w*jm3]
496                              -16*src[w*jm2]
497                              +67*src[w*jm1]
498                             +227*src[w*j]
499                              -32*src[w*jp1]
500                              +7*src[w*jp2]+128)>>8];
501
502         dst[w*(j2+1)] = Clip[(int)(  3*src[w*jp3]
503                              -16*src[w*jp2]
504                              +67*src[w*jp1]
505                             +227*src[w*j]
506                              -32*src[w*jm1]
507                              +7*src[w*jm2]+128)>>8];
508       }
509       src++;
510       dst++;
511     }
512   }
513   else
514   {
515     /* intra field */
516     for (i=0; i<w; i++)
517     {
518       for (j=0; j<h; j+=2)
519       {
520         j2 = j<<1;
521
522         /* top field */
523         jm6 = (j<6) ? 0 : j-6;
524         jm4 = (j<4) ? 0 : j-4;
525         jm2 = (j<2) ? 0 : j-2;
526         jp2 = (j<h-2) ? j+2 : h-2;
527         jp4 = (j<h-4) ? j+4 : h-2;
528         jp6 = (j<h-6) ? j+6 : h-2;
529
530         /* Polyphase FIR filter coefficients (*256): 2 -10 35 242 -18 5 */
531         /* New polyphase FIR filter coefficients (*256): 1 -7 30 248 -21 5 */
532         dst[w*j2] = Clip[(int)(  1*src[w*jm6]
533                          -7*src[w*jm4]
534                          +30*src[w*jm2]
535                         +248*src[w*j]
536                          -21*src[w*jp2]
537                           +5*src[w*jp4]+128)>>8];
538
539         /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */
540         /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */
541         dst[w*(j2+2)] = Clip[(int)( 7*src[w*jm4]
542                              -35*src[w*jm2]
543                             +194*src[w*j]
544                             +110*src[w*jp2]
545                              -24*src[w*jp4]
546                               +4*src[w*jp6]+128)>>8];
547
548         /* bottom field */
549         jm5 = (j<5) ? 1 : j-5;
550         jm3 = (j<3) ? 1 : j-3;
551         jm1 = (j<1) ? 1 : j-1;
552         jp1 = (j<h-1) ? j+1 : h-1;
553         jp3 = (j<h-3) ? j+3 : h-1;
554         jp5 = (j<h-5) ? j+5 : h-1;
555         jp7 = (j<h-7) ? j+7 : h-1;
556
557         /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */
558         /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */
559         dst[w*(j2+1)] = Clip[(int)( 7*src[w*jp5]
560                              -35*src[w*jp3]
561                             +194*src[w*jp1]
562                             +110*src[w*jm1]
563                              -24*src[w*jm3]
564                               +4*src[w*jm5]+128)>>8];
565
566         dst[w*(j2+3)] = Clip[(int)(  1*src[w*jp7]
567                              -7*src[w*jp5]
568                              +30*src[w*jp3]
569                             +248*src[w*jp1]
570                              -21*src[w*jm1]
571                               +5*src[w*jm3]+128)>>8];
572       }
573       src++;
574       dst++;
575     }
576   }
577 }