]> Creatis software - gdcm.git/blob - src/gdcmmpeg2/src/mpeg2enc/mpeg2enc.c
*** empty log message ***
[gdcm.git] / src / gdcmmpeg2 / src / mpeg2enc / mpeg2enc.c
1 /* mpeg2enc.c, main() and parameter file reading                            */
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
33 #define GLOBAL /* used by global.h */
34 #include "config.h"
35 #include "global.h"
36
37 /* private prototypes */
38 static void init _ANSI_ARGS_((void));
39 static void readparmfile _ANSI_ARGS_((char *fname));
40 static void readquantmat _ANSI_ARGS_((void));
41
42
43 int main(argc,argv)
44 int argc;
45 char *argv[];
46 {
47   if (argc!=3)
48   {
49     printf("\n%s, %s\n",version,author);
50     printf("Usage: mpeg2encode in.par out.m2v\n");
51     exit(0);
52   }
53
54   /* read parameter file */
55   readparmfile(argv[1]);
56
57   /* read quantization matrices */
58   readquantmat();
59
60   /* open output file */
61   if (!(outfile=fopen(argv[2],"wb")))
62   {
63     sprintf(errortext,"Couldn't create output file %s",argv[2]);
64     error(errortext);
65   }
66
67   init();
68   putseq();
69
70   fclose(outfile);
71   fclose(statfile);
72
73   return 0;
74 }
75
76 static void init()
77 {
78   int i, size;
79   static int block_count_tab[3] = {6,8,12};
80
81   initbits();
82   init_fdct();
83   init_idct();
84
85   /* round picture dimensions to nearest multiple of 16 or 32 */
86   mb_width = (horizontal_size+15)/16;
87   mb_height = prog_seq ? (vertical_size+15)/16 : 2*((vertical_size+31)/32);
88   mb_height2 = fieldpic ? mb_height>>1 : mb_height; /* for field pictures */
89   width = 16*mb_width;
90   height = 16*mb_height;
91
92   chrom_width = (chroma_format==CHROMA444) ? width : width>>1;
93   chrom_height = (chroma_format!=CHROMA420) ? height : height>>1;
94
95   height2 = fieldpic ? height>>1 : height;
96   width2 = fieldpic ? width<<1 : width;
97   chrom_width2 = fieldpic ? chrom_width<<1 : chrom_width;
98   
99   block_count = block_count_tab[chroma_format-1];
100
101   /* clip table */
102   if (!(clp = (unsigned char *)malloc(1024)))
103     error("malloc failed\n");
104   clp+= 384;
105   for (i=-384; i<640; i++)
106     clp[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
107
108   for (i=0; i<3; i++)
109   {
110     size = (i==0) ? width*height : chrom_width*chrom_height;
111
112     if (!(newrefframe[i] = (unsigned char *)malloc(size)))
113       error("malloc failed\n");
114     if (!(oldrefframe[i] = (unsigned char *)malloc(size)))
115       error("malloc failed\n");
116     if (!(auxframe[i] = (unsigned char *)malloc(size)))
117       error("malloc failed\n");
118     if (!(neworgframe[i] = (unsigned char *)malloc(size)))
119       error("malloc failed\n");
120     if (!(oldorgframe[i] = (unsigned char *)malloc(size)))
121       error("malloc failed\n");
122     if (!(auxorgframe[i] = (unsigned char *)malloc(size)))
123       error("malloc failed\n");
124     if (!(predframe[i] = (unsigned char *)malloc(size)))
125       error("malloc failed\n");
126   }
127
128   mbinfo = (struct mbinfo *)malloc(mb_width*mb_height2*sizeof(struct mbinfo));
129
130   if (!mbinfo)
131     error("malloc failed\n");
132
133   blocks =
134     (short (*)[64])malloc(mb_width*mb_height2*block_count*sizeof(short [64]));
135
136   if (!blocks)
137     error("malloc failed\n");
138
139   /* open statistics output file */
140   if (statname[0]=='-')
141     statfile = stdout;
142   else if (!(statfile = fopen(statname,"w")))
143   {
144     sprintf(errortext,"Couldn't create statistics output file %s",statname);
145     error(errortext);
146   }
147 }
148
149 void error(text)
150 char *text;
151 {
152   fprintf(stderr,text);
153   putc('\n',stderr);
154   exit(1);
155 }
156
157 static void readparmfile(fname)
158 char *fname;
159 {
160   int i;
161   int h,m,s,f;
162   FILE *fd;
163   char line[256];
164   static double ratetab[8]=
165     {24000.0/1001.0,24.0,25.0,30000.0/1001.0,30.0,50.0,60000.0/1001.0,60.0};
166   extern int r,Xi,Xb,Xp,d0i,d0p,d0b; /* rate control */
167   extern double avg_act; /* rate control */
168
169   if (!(fd = fopen(fname,"r")))
170   {
171     sprintf(errortext,"Couldn't open parameter file %s",fname);
172     error(errortext);
173   }
174
175   fgets(id_string,254,fd);
176   fgets(line,254,fd); sscanf(line,"%s",tplorg);
177   fgets(line,254,fd); sscanf(line,"%s",tplref);
178   fgets(line,254,fd); sscanf(line,"%s",iqname);
179   fgets(line,254,fd); sscanf(line,"%s",niqname);
180   fgets(line,254,fd); sscanf(line,"%s",statname);
181   fgets(line,254,fd); sscanf(line,"%d",&inputtype);
182   fgets(line,254,fd); sscanf(line,"%d",&nframes);
183   fgets(line,254,fd); sscanf(line,"%d",&frame0);
184   fgets(line,254,fd); sscanf(line,"%d:%d:%d:%d",&h,&m,&s,&f);
185   fgets(line,254,fd); sscanf(line,"%d",&N);
186   fgets(line,254,fd); sscanf(line,"%d",&M);
187   fgets(line,254,fd); sscanf(line,"%d",&mpeg1);
188   fgets(line,254,fd); sscanf(line,"%d",&fieldpic);
189   fgets(line,254,fd); sscanf(line,"%d",&horizontal_size);
190   fgets(line,254,fd); sscanf(line,"%d",&vertical_size);
191   fgets(line,254,fd); sscanf(line,"%d",&aspectratio);
192   fgets(line,254,fd); sscanf(line,"%d",&frame_rate_code);
193   fgets(line,254,fd); sscanf(line,"%lf",&bit_rate);
194   fgets(line,254,fd); sscanf(line,"%d",&vbv_buffer_size);   
195   fgets(line,254,fd); sscanf(line,"%d",&low_delay);     
196   fgets(line,254,fd); sscanf(line,"%d",&constrparms);
197   fgets(line,254,fd); sscanf(line,"%d",&profile);
198   fgets(line,254,fd); sscanf(line,"%d",&level);
199   fgets(line,254,fd); sscanf(line,"%d",&prog_seq);
200   fgets(line,254,fd); sscanf(line,"%d",&chroma_format);
201   fgets(line,254,fd); sscanf(line,"%d",&video_format);
202   fgets(line,254,fd); sscanf(line,"%d",&color_primaries);
203   fgets(line,254,fd); sscanf(line,"%d",&transfer_characteristics);
204   fgets(line,254,fd); sscanf(line,"%d",&matrix_coefficients);
205   fgets(line,254,fd); sscanf(line,"%d",&display_horizontal_size);
206   fgets(line,254,fd); sscanf(line,"%d",&display_vertical_size);
207   fgets(line,254,fd); sscanf(line,"%d",&dc_prec);
208   fgets(line,254,fd); sscanf(line,"%d",&topfirst);
209   fgets(line,254,fd); sscanf(line,"%d %d %d",
210     frame_pred_dct_tab,frame_pred_dct_tab+1,frame_pred_dct_tab+2);
211   
212   fgets(line,254,fd); sscanf(line,"%d %d %d",
213     conceal_tab,conceal_tab+1,conceal_tab+2);
214   
215   fgets(line,254,fd); sscanf(line,"%d %d %d",
216     qscale_tab,qscale_tab+1,qscale_tab+2);
217
218   fgets(line,254,fd); sscanf(line,"%d %d %d",
219     intravlc_tab,intravlc_tab+1,intravlc_tab+2);
220   fgets(line,254,fd); sscanf(line,"%d %d %d",
221     altscan_tab,altscan_tab+1,altscan_tab+2);
222   fgets(line,254,fd); sscanf(line,"%d",&repeatfirst);
223   fgets(line,254,fd); sscanf(line,"%d",&prog_frame);
224 /* intra slice interval refresh period */  
225   fgets(line,254,fd); sscanf(line,"%d",&P);
226   fgets(line,254,fd); sscanf(line,"%d",&r);
227   fgets(line,254,fd); sscanf(line,"%lf",&avg_act);
228   fgets(line,254,fd); sscanf(line,"%d",&Xi);
229   fgets(line,254,fd); sscanf(line,"%d",&Xp);
230   fgets(line,254,fd); sscanf(line,"%d",&Xb);
231   fgets(line,254,fd); sscanf(line,"%d",&d0i);
232   fgets(line,254,fd); sscanf(line,"%d",&d0p);
233   fgets(line,254,fd); sscanf(line,"%d",&d0b);
234
235   if (N<1)
236     error("N must be positive");
237   if (M<1)
238     error("M must be positive");
239   if (N%M != 0)
240     error("N must be an integer multiple of M");
241
242   motion_data = (struct motion_data *)malloc(M*sizeof(struct motion_data));
243   if (!motion_data)
244     error("malloc failed\n");
245
246   for (i=0; i<M; i++)
247   {
248     fgets(line,254,fd);
249     sscanf(line,"%d %d %d %d",
250       &motion_data[i].forw_hor_f_code, &motion_data[i].forw_vert_f_code,
251       &motion_data[i].sxf, &motion_data[i].syf);
252
253     if (i!=0)
254     {
255       fgets(line,254,fd);
256       sscanf(line,"%d %d %d %d",
257         &motion_data[i].back_hor_f_code, &motion_data[i].back_vert_f_code,
258         &motion_data[i].sxb, &motion_data[i].syb);
259     }
260   }
261
262   fclose(fd);
263
264   /* make flags boolean (x!=0 -> x=1) */
265   mpeg1 = !!mpeg1;
266   fieldpic = !!fieldpic;
267   low_delay = !!low_delay;
268   constrparms = !!constrparms;
269   prog_seq = !!prog_seq;
270   topfirst = !!topfirst;
271
272   for (i=0; i<3; i++)
273   {
274     frame_pred_dct_tab[i] = !!frame_pred_dct_tab[i];
275     conceal_tab[i] = !!conceal_tab[i];
276     qscale_tab[i] = !!qscale_tab[i];
277     intravlc_tab[i] = !!intravlc_tab[i];
278     altscan_tab[i] = !!altscan_tab[i];
279   }
280   repeatfirst = !!repeatfirst;
281   prog_frame = !!prog_frame;
282
283   /* make sure MPEG specific parameters are valid */
284   range_checks();
285
286   frame_rate = ratetab[frame_rate_code-1];
287
288   /* timecode -> frame number */
289   tc0 = h;
290   tc0 = 60*tc0 + m;
291   tc0 = 60*tc0 + s;
292   tc0 = (int)(frame_rate+0.5)*tc0 + f;
293
294   if (!mpeg1)
295   {
296     profile_and_level_checks();
297   }
298   else
299   {
300     /* MPEG-1 */
301     if (constrparms)
302     {
303       if (horizontal_size>768
304           || vertical_size>576
305           || ((horizontal_size+15)/16)*((vertical_size+15)/16)>396
306           || ((horizontal_size+15)/16)*((vertical_size+15)/16)*frame_rate>396*25.0
307           || frame_rate>30.0)
308       {
309         if (!quiet)
310           fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
311         constrparms = 0;
312       }
313     }
314
315     if (constrparms)
316     {
317       for (i=0; i<M; i++)
318       {
319         if (motion_data[i].forw_hor_f_code>4)
320         {
321           if (!quiet)
322             fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
323           constrparms = 0;
324           break;
325         }
326
327         if (motion_data[i].forw_vert_f_code>4)
328         {
329           if (!quiet)
330             fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
331           constrparms = 0;
332           break;
333         }
334
335         if (i!=0)
336         {
337           if (motion_data[i].back_hor_f_code>4)
338           {
339             if (!quiet)
340               fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
341             constrparms = 0;
342             break;
343           }
344
345           if (motion_data[i].back_vert_f_code>4)
346           {
347             if (!quiet)
348               fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
349             constrparms = 0;
350             break;
351           }
352         }
353       }
354     }
355   }
356
357   /* relational checks */
358
359   if (mpeg1)
360   {
361     if (!prog_seq)
362     {
363       if (!quiet)
364         fprintf(stderr,"Warning: setting progressive_sequence = 1\n");
365       prog_seq = 1;
366     }
367
368     if (chroma_format!=CHROMA420)
369     {
370       if (!quiet)
371         fprintf(stderr,"Warning: setting chroma_format = 1 (4:2:0)\n");
372       chroma_format = CHROMA420;
373     }
374
375     if (dc_prec!=0)
376     {
377       if (!quiet)
378         fprintf(stderr,"Warning: setting intra_dc_precision = 0\n");
379       dc_prec = 0;
380     }
381
382     for (i=0; i<3; i++)
383       if (qscale_tab[i])
384       {
385         if (!quiet)
386           fprintf(stderr,"Warning: setting qscale_tab[%d] = 0\n",i);
387         qscale_tab[i] = 0;
388       }
389
390     for (i=0; i<3; i++)
391       if (intravlc_tab[i])
392       {
393         if (!quiet)
394           fprintf(stderr,"Warning: setting intravlc_tab[%d] = 0\n",i);
395         intravlc_tab[i] = 0;
396       }
397
398     for (i=0; i<3; i++)
399       if (altscan_tab[i])
400       {
401         if (!quiet)
402           fprintf(stderr,"Warning: setting altscan_tab[%d] = 0\n",i);
403         altscan_tab[i] = 0;
404       }
405   }
406
407   if (!mpeg1 && constrparms)
408   {
409     if (!quiet)
410       fprintf(stderr,"Warning: setting constrained_parameters_flag = 0\n");
411     constrparms = 0;
412   }
413
414   if (prog_seq && !prog_frame)
415   {
416     if (!quiet)
417       fprintf(stderr,"Warning: setting progressive_frame = 1\n");
418     prog_frame = 1;
419   }
420
421   if (prog_frame && fieldpic)
422   {
423     if (!quiet)
424       fprintf(stderr,"Warning: setting field_pictures = 0\n");
425     fieldpic = 0;
426   }
427
428   if (!prog_frame && repeatfirst)
429   {
430     if (!quiet)
431       fprintf(stderr,"Warning: setting repeat_first_field = 0\n");
432     repeatfirst = 0;
433   }
434
435   if (prog_frame)
436   {
437     for (i=0; i<3; i++)
438       if (!frame_pred_dct_tab[i])
439       {
440         if (!quiet)
441           fprintf(stderr,"Warning: setting frame_pred_frame_dct[%d] = 1\n",i);
442         frame_pred_dct_tab[i] = 1;
443       }
444   }
445
446   if (prog_seq && !repeatfirst && topfirst)
447   {
448     if (!quiet)
449       fprintf(stderr,"Warning: setting top_field_first = 0\n");
450     topfirst = 0;
451   }
452
453   /* search windows */
454   for (i=0; i<M; i++)
455   {
456     if (motion_data[i].sxf > (4<<motion_data[i].forw_hor_f_code)-1)
457     {
458       if (!quiet)
459         fprintf(stderr,
460           "Warning: reducing forward horizontal search width to %d\n",
461           (4<<motion_data[i].forw_hor_f_code)-1);
462       motion_data[i].sxf = (4<<motion_data[i].forw_hor_f_code)-1;
463     }
464
465     if (motion_data[i].syf > (4<<motion_data[i].forw_vert_f_code)-1)
466     {
467       if (!quiet)
468         fprintf(stderr,
469           "Warning: reducing forward vertical search width to %d\n",
470           (4<<motion_data[i].forw_vert_f_code)-1);
471       motion_data[i].syf = (4<<motion_data[i].forw_vert_f_code)-1;
472     }
473
474     if (i!=0)
475     {
476       if (motion_data[i].sxb > (4<<motion_data[i].back_hor_f_code)-1)
477       {
478         if (!quiet)
479           fprintf(stderr,
480             "Warning: reducing backward horizontal search width to %d\n",
481             (4<<motion_data[i].back_hor_f_code)-1);
482         motion_data[i].sxb = (4<<motion_data[i].back_hor_f_code)-1;
483       }
484
485       if (motion_data[i].syb > (4<<motion_data[i].back_vert_f_code)-1)
486       {
487         if (!quiet)
488           fprintf(stderr,
489             "Warning: reducing backward vertical search width to %d\n",
490             (4<<motion_data[i].back_vert_f_code)-1);
491         motion_data[i].syb = (4<<motion_data[i].back_vert_f_code)-1;
492       }
493     }
494   }
495
496 }
497
498 static void readquantmat()
499 {
500   int i,v;
501   FILE *fd;
502
503   if (iqname[0]=='-')
504   {
505     /* use default intra matrix */
506     load_iquant = 0;
507     for (i=0; i<64; i++)
508       intra_q[i] = default_intra_quantizer_matrix[i];
509   }
510   else
511   {
512     /* read customized intra matrix */
513     load_iquant = 1;
514     if (!(fd = fopen(iqname,"r")))
515     {
516       sprintf(errortext,"Couldn't open quant matrix file %s",iqname);
517       error(errortext);
518     }
519
520     for (i=0; i<64; i++)
521     {
522       fscanf(fd,"%d",&v);
523       if (v<1 || v>255)
524         error("invalid value in quant matrix");
525       intra_q[i] = v;
526     }
527
528     fclose(fd);
529   }
530
531   if (niqname[0]=='-')
532   {
533     /* use default non-intra matrix */
534     load_niquant = 0;
535     for (i=0; i<64; i++)
536       inter_q[i] = 16;
537   }
538   else
539   {
540     /* read customized non-intra matrix */
541     load_niquant = 1;
542     if (!(fd = fopen(niqname,"r")))
543     {
544       sprintf(errortext,"Couldn't open quant matrix file %s",niqname);
545       error(errortext);
546     }
547
548     for (i=0; i<64; i++)
549     {
550       fscanf(fd,"%d",&v);
551       if (v<1 || v>255)
552         error("invalid value in quant matrix");
553       inter_q[i] = v;
554     }
555
556     fclose(fd);
557   }
558 }