]> Creatis software - gdcm.git/blob - src/gdcmmpeg2/src/mpeg2dec/store.c
61366c097915e3dc605ac4ba9180fde1e591b3ec
[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
164   if (!Quiet_Flag)
165     my_fprintf("saving %s\n",name);
166
167   //if ((outfile = open(name,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
168   ostream file;
169   outfile = &file;
170   if(!my_fopen(name, "wb", outfile))
171   {
172     my_sprintf(Error_Text,"Couldn't create %s\n",name);
173     Error(Error_Text);
174   }
175
176   optr=obfr;
177
178   for (i=0; i<height; i++)
179   {
180     p = src + offset + incr*i;
181     for (j=0; j<width; j++)
182       putbyte(*p++);
183   }
184
185   if (optr!=obfr)
186     my_fwrite(obfr,optr-obfr,1,outfile);
187
188   my_fclose(outfile);
189 }
190
191 /*
192  * store as headerless file in U,Y,V,Y format
193  */
194 static void store_sif (outname,src,offset,incr,height)
195 char *outname;
196 unsigned char *src[];
197 int offset, incr, height;
198 {
199   int i,j;
200   unsigned char *py, *pu, *pv;
201   static unsigned char *u422, *v422;
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   //if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
235   ostream file;
236   outfile = &file;
237   if(!my_fopen(outname, "wb", outfile))
238   {
239     my_sprintf(Error_Text,"Couldn't create %s\n",outname);
240     Error(Error_Text);
241   }
242
243   optr = obfr;
244
245   for (i=0; i<height; i++)
246   {
247     py = src[0] + offset + incr*i;
248     pu = u422 + (offset>>1) + (incr>>1)*i;
249     pv = v422 + (offset>>1) + (incr>>1)*i;
250
251     for (j=0; j<horizontal_size; j+=2)
252     {
253       putbyte(*pu++);
254       putbyte(*py++);
255       putbyte(*pv++);
256       putbyte(*py++);
257     }
258   }
259
260   if (optr!=obfr)
261     my_fwrite(obfr,optr-obfr,1,outfile);
262
263   my_fclose(outfile);
264 }
265
266 /*
267  * store as PPM (PBMPLUS) or uncompressed Truevision TGA ('Targa') file
268  */
269 static void store_ppm_tga(outname,src,offset,incr,height,tgaflag)
270 char *outname;
271 unsigned char *src[];
272 int offset, incr, height;
273 int tgaflag;
274 {
275   int i, j;
276   int y, u, v, r, g, b;
277   int crv, cbu, cgu, cgv;
278   unsigned char *py, *pu, *pv;
279   static unsigned char tga24[14] = {0,0,2,0,0,0,0, 0,0,0,0,0,24,32};
280   char header[FILENAME_LENGTH];
281   static unsigned char *u422, *v422, *u444, *v444;
282
283   if (chroma_format==CHROMA444)
284   {
285     u444 = src[1];
286     v444 = src[2];
287   }
288   else
289   {
290     if (!u444)
291     {
292       if (chroma_format==CHROMA420)
293       {
294         if (!(u422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
295                                              *Coded_Picture_Height)))
296           Error("malloc failed");
297         static_malloc[2] = u422;
298         if (!(v422 = (unsigned char *)malloc((Coded_Picture_Width>>1)
299                                              *Coded_Picture_Height)))
300           Error("malloc failed");
301         static_malloc[3] = v422;
302       }
303
304       if (!(u444 = (unsigned char *)malloc(Coded_Picture_Width
305                                            *Coded_Picture_Height)))
306         Error("malloc failed");
307       static_malloc[4] = u444;
308
309       if (!(v444 = (unsigned char *)malloc(Coded_Picture_Width
310                                            *Coded_Picture_Height)))
311         Error("malloc failed");
312       static_malloc[5] = v444;
313     }
314
315     if (chroma_format==CHROMA420)
316     {
317       conv420to422(src[1],u422);
318       conv420to422(src[2],v422);
319       conv422to444(u422,u444);
320       conv422to444(v422,v444);
321     }
322     else
323     {
324       conv422to444(src[1],u444);
325       conv422to444(src[2],v444);
326     }
327   }
328
329   strcat(outname,tgaflag ? ".tga" : ".ppm");
330
331   if (!Quiet_Flag)
332     my_fprintf("saving %s\n",outname);
333
334   //if ((outfile = open(outname,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666))==-1)
335   ostream file;
336   outfile = &file;
337   if(! my_fopen(outname, "wb", outfile))
338   {
339     my_sprintf(Error_Text,"Couldn't create %s\n",outname);
340     Error(Error_Text);
341   }
342
343   optr = obfr;
344
345   if (tgaflag)
346   {
347     /* TGA header */
348     for (i=0; i<12; i++)
349       putbyte(tga24[i]);
350
351     putword(horizontal_size); putword(height);
352     putbyte(tga24[12]); putbyte(tga24[13]);
353   }
354   else
355   {
356     /* PPM header */
357     my_sprintf(header,"P6\n%d %d\n255\n",horizontal_size,height);
358
359     for (i=0; header[i]!=0; i++)
360       putbyte(header[i]);
361   }
362
363   /* matrix coefficients */
364   crv = Inverse_Table_6_9[matrix_coefficients][0];
365   cbu = Inverse_Table_6_9[matrix_coefficients][1];
366   cgu = Inverse_Table_6_9[matrix_coefficients][2];
367   cgv = Inverse_Table_6_9[matrix_coefficients][3];
368   
369   for (i=0; i<height; i++)
370   {
371     py = src[0] + offset + incr*i;
372     pu = u444 + offset + incr*i;
373     pv = v444 + offset + incr*i;
374
375     for (j=0; j<horizontal_size; j++)
376     {
377       u = *pu++ - 128;
378       v = *pv++ - 128;
379       y = 76309 * (*py++ - 16); /* (255/219)*65536 */
380       r = Clip[(y + crv*v + 32768)>>16];
381       g = Clip[(y - cgu*u - cgv*v + 32768)>>16];
382       b = Clip[(y + cbu*u + 32786)>>16];
383
384       if (tgaflag)
385       {
386         putbyte(b); putbyte(g); putbyte(r);
387       }
388       else
389       {
390         putbyte(r); putbyte(g); putbyte(b);
391       }
392     }
393   }
394
395   if (optr!=obfr)
396     my_fwrite(obfr,optr-obfr,1,outfile);
397
398   my_fclose(outfile);
399 }
400
401 static void putbyte(c)
402 int c;
403 {
404   *optr++ = c;
405
406   if (optr == obfr+OBFRSIZE)
407   {
408     my_fwrite(obfr,OBFRSIZE,1,outfile);
409     optr = obfr;
410   }
411 }
412
413 static void putword(w)
414 int w;
415 {
416   putbyte(w); putbyte(w>>8);
417 }
418
419 /* horizontal 1:2 interpolation filter */
420 static void conv422to444(src,dst)
421 unsigned char *src,*dst;
422 {
423   int i, i2, w, j, im3, im2, im1, ip1, ip2, ip3;
424
425   w = Coded_Picture_Width>>1;
426
427   if (base.MPEG2_Flag)
428   {
429     for (j=0; j<Coded_Picture_Height; j++)
430     {
431       for (i=0; i<w; i++)
432       {
433         i2 = i<<1;
434         im2 = (i<2) ? 0 : i-2;
435         im1 = (i<1) ? 0 : i-1;
436         ip1 = (i<w-1) ? i+1 : w-1;
437         ip2 = (i<w-2) ? i+2 : w-1;
438         ip3 = (i<w-3) ? i+3 : w-1;
439
440         /* FIR filter coefficients (*256): 21 0 -52 0 159 256 159 0 -52 0 21 */
441         /* even samples (0 0 256 0 0) */
442         dst[i2] = src[i];
443
444         /* odd samples (21 -52 159 159 -52 21) */
445         dst[i2+1] = Clip[(int)(21*(src[im2]+src[ip3])
446                         -52*(src[im1]+src[ip2]) 
447                        +159*(src[i]+src[ip1])+128)>>8];
448       }
449       src+= w;
450       dst+= Coded_Picture_Width;
451     }
452   }
453   else
454   {
455     for (j=0; j<Coded_Picture_Height; j++)
456     {
457       for (i=0; i<w; i++)
458       {
459
460         i2 = i<<1;
461         im3 = (i<3) ? 0 : i-3;
462         im2 = (i<2) ? 0 : i-2;
463         im1 = (i<1) ? 0 : i-1;
464         ip1 = (i<w-1) ? i+1 : w-1;
465         ip2 = (i<w-2) ? i+2 : w-1;
466         ip3 = (i<w-3) ? i+3 : w-1;
467
468         /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
469         dst[i2] =   Clip[(int)(  5*src[im3]
470                          -21*src[im2]
471                          +70*src[im1]
472                         +228*src[i]
473                          -37*src[ip1]
474                          +11*src[ip2]+128)>>8];
475
476        dst[i2+1] = Clip[(int)(  5*src[ip3]
477                          -21*src[ip2]
478                          +70*src[ip1]
479                         +228*src[i]
480                          -37*src[im1]
481                          +11*src[im2]+128)>>8];
482       }
483       src+= w;
484       dst+= Coded_Picture_Width;
485     }
486   }
487 }
488
489 /* vertical 1:2 interpolation filter */
490 static void conv420to422(src,dst)
491 unsigned char *src,*dst;
492 {
493   int w, h, i, j, j2;
494   int jm6, jm5, jm4, jm3, jm2, jm1, jp1, jp2, jp3, jp4, jp5, jp6, jp7;
495
496   w = Coded_Picture_Width>>1;
497   h = Coded_Picture_Height>>1;
498
499   if (progressive_frame)
500   {
501     /* intra frame */
502     for (i=0; i<w; i++)
503     {
504       for (j=0; j<h; j++)
505       {
506         j2 = j<<1;
507         jm3 = (j<3) ? 0 : j-3;
508         jm2 = (j<2) ? 0 : j-2;
509         jm1 = (j<1) ? 0 : j-1;
510         jp1 = (j<h-1) ? j+1 : h-1;
511         jp2 = (j<h-2) ? j+2 : h-1;
512         jp3 = (j<h-3) ? j+3 : h-1;
513
514         /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */
515         /* New FIR filter coefficients (*256): 3 -16 67 227 -32 7 */
516         dst[w*j2] =     Clip[(int)(  3*src[w*jm3]
517                              -16*src[w*jm2]
518                              +67*src[w*jm1]
519                             +227*src[w*j]
520                              -32*src[w*jp1]
521                              +7*src[w*jp2]+128)>>8];
522
523         dst[w*(j2+1)] = Clip[(int)(  3*src[w*jp3]
524                              -16*src[w*jp2]
525                              +67*src[w*jp1]
526                             +227*src[w*j]
527                              -32*src[w*jm1]
528                              +7*src[w*jm2]+128)>>8];
529       }
530       src++;
531       dst++;
532     }
533   }
534   else
535   {
536     /* intra field */
537     for (i=0; i<w; i++)
538     {
539       for (j=0; j<h; j+=2)
540       {
541         j2 = j<<1;
542
543         /* top field */
544         jm6 = (j<6) ? 0 : j-6;
545         jm4 = (j<4) ? 0 : j-4;
546         jm2 = (j<2) ? 0 : j-2;
547         jp2 = (j<h-2) ? j+2 : h-2;
548         jp4 = (j<h-4) ? j+4 : h-2;
549         jp6 = (j<h-6) ? j+6 : h-2;
550
551         /* Polyphase FIR filter coefficients (*256): 2 -10 35 242 -18 5 */
552         /* New polyphase FIR filter coefficients (*256): 1 -7 30 248 -21 5 */
553         dst[w*j2] = Clip[(int)(  1*src[w*jm6]
554                          -7*src[w*jm4]
555                          +30*src[w*jm2]
556                         +248*src[w*j]
557                          -21*src[w*jp2]
558                           +5*src[w*jp4]+128)>>8];
559
560         /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */
561         /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */
562         dst[w*(j2+2)] = Clip[(int)( 7*src[w*jm4]
563                              -35*src[w*jm2]
564                             +194*src[w*j]
565                             +110*src[w*jp2]
566                              -24*src[w*jp4]
567                               +4*src[w*jp6]+128)>>8];
568
569         /* bottom field */
570         jm5 = (j<5) ? 1 : j-5;
571         jm3 = (j<3) ? 1 : j-3;
572         jm1 = (j<1) ? 1 : j-1;
573         jp1 = (j<h-1) ? j+1 : h-1;
574         jp3 = (j<h-3) ? j+3 : h-1;
575         jp5 = (j<h-5) ? j+5 : h-1;
576         jp7 = (j<h-7) ? j+7 : h-1;
577
578         /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */
579         /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */
580         dst[w*(j2+1)] = Clip[(int)( 7*src[w*jp5]
581                              -35*src[w*jp3]
582                             +194*src[w*jp1]
583                             +110*src[w*jm1]
584                              -24*src[w*jm3]
585                               +4*src[w*jm5]+128)>>8];
586
587         dst[w*(j2+3)] = Clip[(int)(  1*src[w*jp7]
588                              -7*src[w*jp5]
589                              +30*src[w*jp3]
590                             +248*src[w*jp1]
591                              -21*src[w*jm1]
592                               +5*src[w*jm3]+128)>>8];
593       }
594       src++;
595       dst++;
596     }
597   }
598 }