Subversion Repositories shark

Rev

Rev 1085 | Details | Compare with Previous | Last modification | View Log | RSS feed

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