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