]> Creatis software - gdcm.git/blob - src/gdcmmpeg2/src/mpeg2dec/mpeg2dec.c
COMP: Fix warning about pos being used only with a ifdef. Thanks to bcc for report
[gdcm.git] / src / gdcmmpeg2 / src / mpeg2dec / mpeg2dec.c
1
2 /* mpeg2dec.c, main(), initialization, option processing                    */
3
4 /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
5
6 /*
7  * Disclaimer of Warranty
8  *
9  * These software programs are available to the user without any license fee or
10  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
11  * any and all warranties, whether express, implied, or statuary, including any
12  * implied warranties or merchantability or of fitness for a particular
13  * purpose.  In no event shall the copyright-holder be liable for any
14  * incidental, punitive, or consequential damages of any kind whatsoever
15  * arising from the use of these programs.
16  *
17  * This disclaimer of warranty extends to the user of these programs and user's
18  * customers, employees, agents, transferees, successors, and assigns.
19  *
20  * The MPEG Software Simulation Group does not represent or warrant that the
21  * programs furnished hereunder are free of infringement of any third-party
22  * patents.
23  *
24  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
25  * are subject to royalty fees to patent holders.  Many of these patents are
26  * general enough such that they are unavoidable regardless of implementation
27  * design.
28  *
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include <fcntl.h>
35
36 #define GLOBAL
37 #include "config.h"
38 #include "global.h"
39
40 /* private prototypes */
41 static int  video_sequence _ANSI_ARGS_((int *framenum));
42 static int Decode_Bitstream _ANSI_ARGS_((void));
43 static int  Headers _ANSI_ARGS_((void));
44 static void Initialize_Sequence _ANSI_ARGS_((void));
45 static void Initialize_Decoder _ANSI_ARGS_((void));
46 static void Deinitialize_Sequence _ANSI_ARGS_((void));
47 static void Process_Options _ANSI_ARGS_((int argc, char *argv[]));
48
49
50 #if OLD
51 static int  Get_Val _ANSI_ARGS_((char *argv[]));
52 #endif
53
54 /* #define DEBUG */
55
56 static void Clear_Options();
57 #ifdef DEBUG
58 static void Print_Options();
59 #endif
60
61 int main(argc,argv)
62 int argc;
63 char *argv[];
64 {
65   int ret, code;
66
67   Clear_Options();
68
69   /* decode command line arguments */
70   Process_Options(argc,argv);
71
72 #ifdef DEBUG
73   Print_Options();
74 #endif
75
76   ld = &base; /* select base layer context */
77
78   /* open MPEG base layer bitstream file(s) */
79   /* NOTE: this is either a base layer stream or a spatial enhancement stream */
80   if ((base.Infile=open(Main_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
81   {
82     fprintf(stderr,"Base layer input file %s not found\n", Main_Bitstream_Filename);
83     exit(1);
84   }
85
86
87   if(base.Infile != 0)
88   {
89     Initialize_Buffer(); 
90   
91     if(Show_Bits(8)==0x47)
92     {
93       sprintf(Error_Text,"Decoder currently does not parse transport streams\n");
94       Error(Error_Text);
95     }
96
97     next_start_code();
98     code = Show_Bits(32);
99
100     switch(code)
101     {
102     case SEQUENCE_HEADER_CODE:
103       break;
104     case PACK_START_CODE:
105       System_Stream_Flag = 1;
106     case VIDEO_ELEMENTARY_STREAM:
107       System_Stream_Flag = 1;
108       break;
109     default:
110       sprintf(Error_Text,"Unable to recognize stream type\n");
111       Error(Error_Text);
112       break;
113     }
114
115     lseek(base.Infile, 0l, 0);
116     Initialize_Buffer(); 
117   }
118
119   if(base.Infile!=0)
120   {
121     lseek(base.Infile, 0l, 0);
122   }
123
124   Initialize_Buffer(); 
125
126   if(Two_Streams)
127   {
128     ld = &enhan; /* select enhancement layer context */
129
130     if ((enhan.Infile = open(Enhancement_Layer_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
131     {
132       sprintf(Error_Text,"enhancment layer bitstream file %s not found\n",
133         Enhancement_Layer_Bitstream_Filename);
134
135       Error(Error_Text);
136     }
137
138     Initialize_Buffer();
139     ld = &base;
140   }
141
142   Initialize_Decoder();
143
144   ret = Decode_Bitstream();
145
146   close(base.Infile);
147
148   if (Two_Streams)
149     close(enhan.Infile);
150
151   return ret;
152 }
153
154 /* IMPLEMENTAION specific rouintes */
155 static void Initialize_Decoder()
156 {
157   int i;
158
159   /* Clip table */
160   if (!(Clip=(unsigned char *)malloc(1024)))
161     Error("Clip[] malloc failed\n");
162
163   Clip += 384;
164
165   for (i=-384; i<640; i++)
166     Clip[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
167
168   /* IDCT */
169   if (Reference_IDCT_Flag)
170     Initialize_Reference_IDCT();
171   else
172     Initialize_Fast_IDCT();
173
174 }
175
176 /* mostly IMPLEMENTAION specific rouintes */
177 static void Initialize_Sequence()
178 {
179   int cc, size;
180   static int Table_6_20[3] = {6,8,12};
181
182   /* check scalability mode of enhancement layer */
183   if (Two_Streams && (enhan.scalable_mode!=SC_SNR) && (base.scalable_mode!=SC_DP))
184     Error("unsupported scalability mode\n");
185
186   /* force MPEG-1 parameters for proper decoder behavior */
187   /* see ISO/IEC 13818-2 section D.9.14 */
188   if (!base.MPEG2_Flag)
189   {
190     progressive_sequence = 1;
191     progressive_frame = 1;
192     picture_structure = FRAME_PICTURE;
193     frame_pred_frame_dct = 1;
194     chroma_format = CHROMA420;
195     matrix_coefficients = 5;
196   }
197
198   /* round to nearest multiple of coded macroblocks */
199   /* ISO/IEC 13818-2 section 6.3.3 sequence_header() */
200   mb_width = (horizontal_size+15)/16;
201   mb_height = (base.MPEG2_Flag && !progressive_sequence) ? 2*((vertical_size+31)/32)
202                                         : (vertical_size+15)/16;
203
204   Coded_Picture_Width = 16*mb_width;
205   Coded_Picture_Height = 16*mb_height;
206
207   /* ISO/IEC 13818-2 sections 6.1.1.8, 6.1.1.9, and 6.1.1.10 */
208   Chroma_Width = (chroma_format==CHROMA444) ? Coded_Picture_Width
209                                            : Coded_Picture_Width>>1;
210   Chroma_Height = (chroma_format!=CHROMA420) ? Coded_Picture_Height
211                                             : Coded_Picture_Height>>1;
212   
213   /* derived based on Table 6-20 in ISO/IEC 13818-2 section 6.3.17 */
214   block_count = Table_6_20[chroma_format-1];
215
216   for (cc=0; cc<3; cc++)
217   {
218     if (cc==0)
219       size = Coded_Picture_Width*Coded_Picture_Height;
220     else
221       size = Chroma_Width*Chroma_Height;
222
223     if (!(backward_reference_frame[cc] = (unsigned char *)malloc(size)))
224       Error("backward_reference_frame[] malloc failed\n");
225
226     if (!(forward_reference_frame[cc] = (unsigned char *)malloc(size)))
227       Error("forward_reference_frame[] malloc failed\n");
228
229     if (!(auxframe[cc] = (unsigned char *)malloc(size)))
230       Error("auxframe[] malloc failed\n");
231
232     if(Ersatz_Flag)
233       if (!(substitute_frame[cc] = (unsigned char *)malloc(size)))
234         Error("substitute_frame[] malloc failed\n");
235
236
237     if (base.scalable_mode==SC_SPAT)
238     {
239       /* this assumes lower layer is 4:2:0 */
240       if (!(llframe0[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
241         Error("llframe0 malloc failed\n");
242       if (!(llframe1[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
243         Error("llframe1 malloc failed\n");
244     }
245   }
246
247   /* SCALABILITY: Spatial */
248   if (base.scalable_mode==SC_SPAT)
249   {
250     if (!(lltmp = (short *)malloc(lower_layer_prediction_horizontal_size*((lower_layer_prediction_vertical_size*vertical_subsampling_factor_n)/vertical_subsampling_factor_m)*sizeof(short))))
251       Error("lltmp malloc failed\n");
252   }
253
254 #ifdef DISPLAY
255   if (Output_Type==T_X11)
256   {
257     Initialize_Display_Process("");
258     Initialize_Dither_Matrix();
259   }
260 #endif /* DISPLAY */
261
262 }
263
264 void Error(text)
265 char *text;
266 {
267   fprintf(stderr,text);
268   exit(1);
269 }
270
271 /* Trace_Flag output */
272 void Print_Bits(code,bits,len)
273 int code,bits,len;
274 {
275   int i;
276   for (i=0; i<len; i++)
277     printf("%d",(code>>(bits-1-i))&1);
278 }
279
280
281
282 /* option processing */
283 static void Process_Options(argc,argv)
284 int argc;                  /* argument count  */
285 char *argv[];              /* argument vector */
286 {
287   int i, LastArg, NextArg;
288
289   /* at least one argument should be present */
290   if (argc<2)
291   {
292     printf("\n%s, %s\n",Version,Author);
293     printf("Usage:  mpeg2decode {options}\n"
294 "Options: -b  file  main bitstream (base or spatial enhancement layer)\n"
295 "         -cn file  conformance report (n: level)\n"
296 "         -e  file  enhancement layer bitstream (SNR or Data Partitioning)\n"
297 "         -f        store/display interlaced video in frame format\n"
298 "         -g        concatenated file format for substitution method (-x)\n"
299 "         -in file  information & statistics report  (n: level)\n"
300 "         -l  file  file name pattern for lower layer sequence\n"
301 "                   (for spatial scalability)\n"
302 "         -on file  output format (0:YUV 1:SIF 2:TGA 3:PPM 4:X11 5:X11HiQ)\n"
303 "         -q        disable warnings to stderr\n"
304 "         -r        use double precision reference IDCT\n"
305 "         -t        enable low level tracing to stdout\n"
306 "         -u  file  print user_data to stdio or file\n"
307 "         -vn       verbose output (n: level)\n"
308 "         -x  file  filename pattern of picture substitution sequence\n\n"
309 "File patterns:  for sequential filenames, \"printf\" style, e.g. rec%%d\n"
310 "                 or rec%%d%%c for fieldwise storage\n"
311 "Levels:        0:none 1:sequence 2:picture 3:slice 4:macroblock 5:block\n\n"
312 "Example:       mpeg2decode -b bitstream.mpg -f -r -o0 rec%%d\n"
313 "         \n");
314     exit(0);
315   }
316
317
318   Output_Type = -1;
319   i = 1;
320
321   /* command-line options are proceeded by '-' */
322
323   while(i < argc)
324   {
325     /* check if this is the last argument */
326     LastArg = ((argc-i)==1);
327
328     /* parse ahead to see if another flag immediately follows current
329        argument (this is used to tell if a filename is missing) */
330     if(!LastArg)
331       NextArg = (argv[i+1][0]=='-');
332     else
333       NextArg = 0;
334
335     /* second character, [1], after '-' is the switch */
336     if(argv[i][0]=='-')
337     {
338       switch(toupper(argv[i][1]))
339       {
340         /* third character. [2], is the value */
341       case 'B':
342         Main_Bitstream_Flag = 1;
343
344         if(NextArg || LastArg)
345         {
346           printf("ERROR: -b must be followed the main bitstream filename\n");
347         }
348         else
349           Main_Bitstream_Filename = argv[++i]; 
350
351         break;
352
353
354       case 'C':
355
356 #ifdef VERIFY
357         Verify_Flag = atoi(&argv[i][2]); 
358
359         if((Verify_Flag < NO_LAYER) || (Verify_Flag > ALL_LAYERS))
360         {
361           printf("ERROR: -c level (%d) out of range [%d,%d]\n",
362             Verify_Flag, NO_LAYER, ALL_LAYERS);
363           exit(ERROR);
364         }
365 #else  /* VERIFY */
366         printf("This program not compiled for Verify_Flag option\n");
367 #endif /* VERIFY */
368         break;
369
370       case 'E':
371         Two_Streams = 1; /* either Data Partitioning (DP) or SNR Scalability enhancment */
372                    
373         if(NextArg || LastArg)
374         {
375           printf("ERROR: -e must be followed by filename\n");
376           exit(ERROR);
377         }
378         else
379           Enhancement_Layer_Bitstream_Filename = argv[++i]; 
380
381         break;
382
383
384       case 'F':
385         Frame_Store_Flag = 1;
386         break;
387
388       case 'G':
389         Big_Picture_Flag = 1;
390         break;
391
392
393       case 'I':
394 #ifdef VERIFY
395         Stats_Flag = atoi(&argv[i][2]); 
396 #else /* VERIFY */
397         printf("WARNING: This program not compiled for -i option\n");
398 #endif /* VERIFY */     
399         break;
400     
401       case 'L':  /* spatial scalability flag */
402         Spatial_Flag = 1;
403
404        if(NextArg || LastArg)
405        {
406          printf("ERROR: -l must be followed by filename\n");
407          exit(ERROR);
408        }
409        else
410          Lower_Layer_Picture_Filename = argv[++i]; 
411
412         break;
413
414       case 'O':
415   
416         Output_Type = atoi(&argv[i][2]); 
417   
418         if((Output_Type==4) || (Output_Type==5))
419           Output_Picture_Filename = "";  /* no need of filename */
420         else if(NextArg || LastArg)  
421         {
422           printf("ERROR: -o must be followed by filename\n");
423           exit(ERROR);
424         }
425         else
426         /* filename is separated by space, so it becomes the next argument */
427           Output_Picture_Filename = argv[++i]; 
428
429 #ifdef DISPLAY
430         if (Output_Type==T_X11HIQ)
431         {
432           hiQdither = 1;
433           Output_Type=T_X11;
434         }
435 #endif /* DISPLAY */
436         break;
437
438       case 'Q':
439         Quiet_Flag = 1;
440         break;
441
442       case 'R':
443         Reference_IDCT_Flag = 1;
444         break;
445     
446       case 'T':
447 #ifdef TRACE
448         Trace_Flag = 1;
449 #else /* TRACE */
450         printf("WARNING: This program not compiled for -t option\n");
451 #endif /* TRACE */
452         break;
453
454       case 'U':
455         User_Data_Flag = 1;
456
457       case 'V':
458 #ifdef VERBOSE
459         Verbose_Flag = atoi(&argv[i][2]); 
460 #else /* VERBOSE */
461         printf("This program not compiled for -v option\n");
462 #endif /* VERBOSE */
463         break;
464
465
466       case 'X':
467         Ersatz_Flag = 1;
468
469        if(NextArg || LastArg)
470        {
471          printf("ERROR: -x must be followed by filename\n"); 
472          exit(ERROR);
473        }
474        else
475         Substitute_Picture_Filename = argv[++i]; 
476
477         break;
478
479
480
481       default:
482         fprintf(stderr,"undefined option -%c ignored. Exiting program\n", 
483           argv[i][1]);
484
485         exit(ERROR);
486     
487       } /* switch() */
488     } /* if argv[i][0] == '-' */
489     
490     i++;
491
492     /* check for bitstream filename argument (there must always be one, at the very end
493      of the command line arguments */
494
495   } /* while() */
496
497
498   /* options sense checking */
499
500   if(Main_Bitstream_Flag!=1)
501   {
502     printf("There must be a main bitstream specified (-b filename)\n");
503   }
504
505   /* force display process to show frame pictures */
506   if((Output_Type==4 || Output_Type==5) && Frame_Store_Flag)
507     Display_Progressive_Flag = 1;
508   else
509     Display_Progressive_Flag = 0;
510
511 #ifdef VERIFY
512   /* parse the bitstream, do not actually decode it completely */
513   
514
515 #if 0
516   if(Output_Type==-1)
517   {
518     Decode_Layer = Verify_Flag;
519     printf("FYI: Decoding bitstream elements up to: %s\n", 
520       Layer_Table[Decode_Layer]);
521   }
522   else
523 #endif
524     Decode_Layer = ALL_LAYERS;
525
526 #endif /* VERIFY */
527
528   /* no output type specified */
529   if(Output_Type==-1)
530   {
531     Output_Type = 9; 
532     Output_Picture_Filename = "";
533   }
534
535
536 #ifdef DISPLAY
537   if (Output_Type==T_X11)
538   {
539     if(Frame_Store_Flag)
540       Display_Progressive_Flag = 1;
541     else
542       Display_Progressive_Flag = 0;
543
544     Frame_Store_Flag = 1; /* to avoid calling dither() twice */
545   }
546 #endif
547
548
549 }
550
551
552 #ifdef OLD
553 /* 
554    this is an old routine used to convert command line arguments
555    into integers 
556 */
557 static int Get_Val(argv)
558 char *argv[];
559 {
560   int val;
561
562   if (sscanf(argv[1]+2,"%d",&val)!=1)
563     return 0;
564
565   while (isdigit(argv[1][2]))
566     argv[1]++;
567
568   return val;
569 }
570 #endif
571
572
573
574 static int Headers()
575 {
576   int ret;
577
578   ld = &base;
579   
580
581   /* return when end of sequence (0) or picture
582      header has been parsed (1) */
583
584   ret = Get_Hdr();
585
586
587   if (Two_Streams)
588   {
589     ld = &enhan;
590     if (Get_Hdr()!=ret && !Quiet_Flag)
591       fprintf(stderr,"streams out of sync\n");
592     ld = &base;
593   }
594
595   return ret;
596 }
597
598
599
600 static int Decode_Bitstream()
601 {
602   int ret;
603   int Bitstream_Framenum;
604
605   Bitstream_Framenum = 0;
606
607   for(;;)
608   {
609
610 #ifdef VERIFY
611     Clear_Verify_Headers();
612 #endif /* VERIFY */
613
614     ret = Headers();
615     
616     if(ret==1)
617     {
618       ret = video_sequence(&Bitstream_Framenum);
619     }
620     else
621       return(ret);
622   }
623
624 }
625
626
627 static void Deinitialize_Sequence()
628 {
629   int i;
630
631   /* clear flags */
632   base.MPEG2_Flag=0;
633
634   for(i=0;i<3;i++)
635   {
636     free(backward_reference_frame[i]);
637     free(forward_reference_frame[i]);
638     free(auxframe[i]);
639
640     if (base.scalable_mode==SC_SPAT)
641     {
642      free(llframe0[i]);
643      free(llframe1[i]);
644     }
645   }
646
647   if (base.scalable_mode==SC_SPAT)
648     free(lltmp);
649
650 #ifdef DISPLAY
651   if (Output_Type==T_X11) 
652     Terminate_Display_Process();
653 #endif
654 }
655
656
657 static int video_sequence(Bitstream_Framenumber)
658 int *Bitstream_Framenumber;
659 {
660   int Bitstream_Framenum;
661   int Sequence_Framenum;
662   int Return_Value;
663
664   Bitstream_Framenum = *Bitstream_Framenumber;
665   Sequence_Framenum=0;
666
667   Initialize_Sequence();
668
669   /* decode picture whose header has already been parsed in 
670      Decode_Bitstream() */
671
672
673   Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
674
675   /* update picture numbers */
676   if (!Second_Field)
677   {
678     Bitstream_Framenum++;
679     Sequence_Framenum++;
680   }
681
682   /* loop through the rest of the pictures in the sequence */
683   while ((Return_Value=Headers()))
684   {
685     Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
686
687     if (!Second_Field)
688     {
689       Bitstream_Framenum++;
690       Sequence_Framenum++;
691     }
692   }
693
694   /* put last frame */
695   if (Sequence_Framenum!=0)
696   {
697     Output_Last_Frame_of_Sequence(Bitstream_Framenum);
698   }
699
700   Deinitialize_Sequence();
701
702 #ifdef VERIFY
703     Clear_Verify_Headers();
704 #endif /* VERIFY */
705
706   *Bitstream_Framenumber = Bitstream_Framenum;
707   return(Return_Value);
708 }
709
710
711
712 static void Clear_Options()
713 {
714   Verbose_Flag = 0;
715   Output_Type = 0;
716   Output_Picture_Filename = " ";
717   hiQdither  = 0;
718   Output_Type = 0;
719   Frame_Store_Flag = 0;
720   Spatial_Flag = 0;
721   Lower_Layer_Picture_Filename = " ";
722   Reference_IDCT_Flag = 0;
723   Trace_Flag = 0;
724   Quiet_Flag = 0;
725   Ersatz_Flag = 0;
726   Substitute_Picture_Filename  = " ";
727   Two_Streams = 0;
728   Enhancement_Layer_Bitstream_Filename = " ";
729   Big_Picture_Flag = 0;
730   Main_Bitstream_Flag = 0;
731   Main_Bitstream_Filename = " ";
732   Verify_Flag = 0;
733   Stats_Flag  = 0;
734   User_Data_Flag = 0; 
735 }
736
737
738 #ifdef DEBUG
739 static void Print_Options()
740 {
741   
742   printf("Verbose_Flag                         = %d\n", Verbose_Flag);
743   printf("Output_Type                          = %d\n", Output_Type);
744   printf("Output_Picture_Filename              = %s\n", Output_Picture_Filename);
745   printf("hiQdither                            = %d\n", hiQdither);
746   printf("Output_Type                          = %d\n", Output_Type);
747   printf("Frame_Store_Flag                     = %d\n", Frame_Store_Flag);
748   printf("Spatial_Flag                         = %d\n", Spatial_Flag);
749   printf("Lower_Layer_Picture_Filename         = %s\n", Lower_Layer_Picture_Filename);
750   printf("Reference_IDCT_Flag                  = %d\n", Reference_IDCT_Flag);
751   printf("Trace_Flag                           = %d\n", Trace_Flag);
752   printf("Quiet_Flag                           = %d\n", Quiet_Flag);
753   printf("Ersatz_Flag                          = %d\n", Ersatz_Flag);
754   printf("Substitute_Picture_Filename          = %s\n", Substitute_Picture_Filename);
755   printf("Two_Streams                          = %d\n", Two_Streams);
756   printf("Enhancement_Layer_Bitstream_Filename = %s\n", Enhancement_Layer_Bitstream_Filename);
757   printf("Big_Picture_Flag                     = %d\n", Big_Picture_Flag);
758   printf("Main_Bitstream_Flag                  = %d\n", Main_Bitstream_Flag);
759   printf("Main_Bitstream_Filename              = %s\n", Main_Bitstream_Filename);
760   printf("Verify_Flag                          = %d\n", Verify_Flag);
761   printf("Stats_Flag                           = %d\n", Stats_Flag);
762   printf("User_Data_Flag                       = %d\n", User_Data_Flag);
763
764 }
765 #endif