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