]> Creatis software - gdcm.git/blob - src/gdcmMpeg.cxx
ENH: Initial checkin of gdcmMpeg, the code is still messy but it compiles finally
[gdcm.git] / src / gdcmMpeg.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmMpeg.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/05/21 18:43:52 $
7   Version:   $Revision: 1.1 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 #include "gdcmDebug.h"
19
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include <fcntl.h>
25 extern "C" {
26 #define GLOBAL
27 #include "config.h"
28 #include "global.h"
29
30 /* private prototypes */
31 static int  video_sequence _ANSI_ARGS_((int *framenum));
32 static int Decode_Bitstream _ANSI_ARGS_((void));
33 static int  Headers _ANSI_ARGS_((void));
34 static void Initialize_Sequence _ANSI_ARGS_((void));
35 static void Initialize_Decoder _ANSI_ARGS_((void));
36 static void Deinitialize_Sequence _ANSI_ARGS_((void));
37 //static void Process_Options _ANSI_ARGS_((int argc, char *argv[]));
38
39 /* IMPLEMENTAION specific rouintes */
40 static void Initialize_Decoder()
41 {
42   int i;
43
44   /* Clip table */
45   if (!(Clip=(unsigned char *)malloc(1024)))
46     Error("Clip[] malloc failed\n");
47
48   Clip += 384;
49
50   for (i=-384; i<640; i++)
51     Clip[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
52
53   /* IDCT */
54   if (Reference_IDCT_Flag)
55     Initialize_Reference_IDCT();
56   else
57     Initialize_Fast_IDCT();
58
59 }
60
61 /* mostly IMPLEMENTAION specific rouintes */
62 static void Initialize_Sequence()
63 {
64   int cc, size;
65   static int Table_6_20[3] = {6,8,12};
66
67   /* check scalability mode of enhancement layer */
68   if (Two_Streams && (enhan.scalable_mode!=SC_SNR) && (base.scalable_mode!=SC_DP))
69     Error("unsupported scalability mode\n");
70
71   /* force MPEG-1 parameters for proper decoder behavior */
72   /* see ISO/IEC 13818-2 section D.9.14 */
73   if (!base.MPEG2_Flag)
74   {
75     progressive_sequence = 1;
76     progressive_frame = 1;
77     picture_structure = FRAME_PICTURE;
78     frame_pred_frame_dct = 1;
79     chroma_format = CHROMA420;
80     matrix_coefficients = 5;
81   }
82
83   /* round to nearest multiple of coded macroblocks */
84   /* ISO/IEC 13818-2 section 6.3.3 sequence_header() */
85   mb_width = (horizontal_size+15)/16;
86   mb_height = (base.MPEG2_Flag && !progressive_sequence) ? 2*((vertical_size+31)/32)
87                                         : (vertical_size+15)/16;
88
89   Coded_Picture_Width = 16*mb_width;
90   Coded_Picture_Height = 16*mb_height;
91
92   /* ISO/IEC 13818-2 sections 6.1.1.8, 6.1.1.9, and 6.1.1.10 */
93   Chroma_Width = (chroma_format==CHROMA444) ? Coded_Picture_Width
94                                            : Coded_Picture_Width>>1;
95   Chroma_Height = (chroma_format!=CHROMA420) ? Coded_Picture_Height
96                                             : Coded_Picture_Height>>1;
97   
98   /* derived based on Table 6-20 in ISO/IEC 13818-2 section 6.3.17 */
99   block_count = Table_6_20[chroma_format-1];
100
101   for (cc=0; cc<3; cc++)
102   {
103     if (cc==0)
104       size = Coded_Picture_Width*Coded_Picture_Height;
105     else
106       size = Chroma_Width*Chroma_Height;
107
108     if (!(backward_reference_frame[cc] = (unsigned char *)malloc(size)))
109       Error("backward_reference_frame[] malloc failed\n");
110
111     if (!(forward_reference_frame[cc] = (unsigned char *)malloc(size)))
112       Error("forward_reference_frame[] malloc failed\n");
113
114     if (!(auxframe[cc] = (unsigned char *)malloc(size)))
115       Error("auxframe[] malloc failed\n");
116
117     if(Ersatz_Flag)
118       if (!(substitute_frame[cc] = (unsigned char *)malloc(size)))
119         Error("substitute_frame[] malloc failed\n");
120
121
122     if (base.scalable_mode==SC_SPAT)
123     {
124       /* this assumes lower layer is 4:2:0 */
125       if (!(llframe0[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
126         Error("llframe0 malloc failed\n");
127       if (!(llframe1[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
128         Error("llframe1 malloc failed\n");
129     }
130   }
131
132   /* SCALABILITY: Spatial */
133   if (base.scalable_mode==SC_SPAT)
134   {
135     if (!(lltmp = (short *)malloc(lower_layer_prediction_horizontal_size*((lower_layer_prediction_vertical_size*vertical_subsampling_factor_n)/vertical_subsampling_factor_m)*sizeof(short))))
136       Error("lltmp malloc failed\n");
137   }
138
139 #ifdef DISPLAY
140   if (Output_Type==T_X11)
141   {
142     Initialize_Display_Process("");
143     Initialize_Dither_Matrix();
144   }
145 #endif /* DISPLAY */
146
147 }
148
149 extern void Error(char *text)
150 {
151   fprintf(stderr,text);
152   exit(1);
153 }
154
155 /* Trace_Flag output */
156 void Print_Bits(int code, int bits, int len)
157 {
158   int i;
159   for (i=0; i<len; i++)
160     printf("%d",(code>>(bits-1-i))&1);
161 }
162
163 static int Headers()
164 {
165   int ret;
166
167   ld = &base;
168   
169
170   /* return when end of sequence (0) or picture
171      header has been parsed (1) */
172
173   ret = Get_Hdr();
174
175
176   if (Two_Streams)
177   {
178     ld = &enhan;
179     if (Get_Hdr()!=ret && !Quiet_Flag)
180       fprintf(stderr,"streams out of sync\n");
181     ld = &base;
182   }
183
184   return ret;
185 }
186
187
188
189 static int Decode_Bitstream()
190 {
191   int ret;
192   int Bitstream_Framenum;
193
194   Bitstream_Framenum = 0;
195
196   for(;;)
197   {
198
199 #ifdef VERIFY
200     Clear_Verify_Headers();
201 #endif /* VERIFY */
202
203     ret = Headers();
204     
205     if(ret==1)
206     {
207       ret = video_sequence(&Bitstream_Framenum);
208     }
209     else
210       return(ret);
211   }
212
213 }
214
215
216 static void Deinitialize_Sequence()
217 {
218   int i;
219
220   /* clear flags */
221   base.MPEG2_Flag=0;
222
223   for(i=0;i<3;i++)
224   {
225     free(backward_reference_frame[i]);
226     free(forward_reference_frame[i]);
227     free(auxframe[i]);
228
229     if (base.scalable_mode==SC_SPAT)
230     {
231      free(llframe0[i]);
232      free(llframe1[i]);
233     }
234   }
235
236   if (base.scalable_mode==SC_SPAT)
237     free(lltmp);
238
239 #ifdef DISPLAY
240   if (Output_Type==T_X11) 
241     Terminate_Display_Process();
242 #endif
243 }
244
245
246 static int video_sequence(int *Bitstream_Framenumber)
247 {
248   int Bitstream_Framenum;
249   int Sequence_Framenum;
250   int Return_Value;
251
252   Bitstream_Framenum = *Bitstream_Framenumber;
253   Sequence_Framenum=0;
254
255   Initialize_Sequence();
256
257   /* decode picture whose header has already been parsed in 
258      Decode_Bitstream() */
259
260
261   Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
262
263   /* update picture numbers */
264   if (!Second_Field)
265   {
266     Bitstream_Framenum++;
267     Sequence_Framenum++;
268   }
269
270   /* loop through the rest of the pictures in the sequence */
271   while ((Return_Value=Headers()))
272   {
273     Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
274
275     if (!Second_Field)
276     {
277       Bitstream_Framenum++;
278       Sequence_Framenum++;
279     }
280   }
281
282   /* put last frame */
283   if (Sequence_Framenum!=0)
284   {
285     Output_Last_Frame_of_Sequence(Bitstream_Framenum);
286   }
287
288   Deinitialize_Sequence();
289
290 #ifdef VERIFY
291     Clear_Verify_Headers();
292 #endif /* VERIFY */
293
294   *Bitstream_Framenumber = Bitstream_Framenum;
295   return(Return_Value);
296 }
297 } // End "C" extern
298
299 namespace gdcm 
300 {
301 /**
302  * \brief   routine for MPEG decompression 
303  * @param fp pointer to an already open file descriptor 
304  *                      8 significant bits per pixel
305  * @param image_buffer to receive uncompressed pixels
306  * @param statesuspension Suspension State basically it should be 3 otherwise more complex to handle
307  * @return 1 on success, 0 on error
308  */
309 bool ReadMPEGFile (std::ifstream *fp, void *image_buffer)
310 {
311   int ret, code;
312
313 //  Clear_Options();
314
315   /* decode command line arguments */
316 //  Process_Options(argc,argv);
317
318 #ifdef DEBUG
319   Print_Options();
320 #endif
321
322   ld = &base; /* select base layer context */
323
324   /* open MPEG base layer bitstream file(s) */
325   /* NOTE: this is either a base layer stream or a spatial enhancement stream */
326 #if 0
327   if ((base.Infile=open(Main_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
328   {
329     fprintf(stderr,"Base layer input file %s not found\n", Main_Bitstream_Filename);
330     exit(1);
331   }
332 #else
333   base.Infile = -1; //DEBUG
334 #endif
335
336
337   if(base.Infile != 0)
338   {
339     Initialize_Buffer(); 
340   
341     if(Show_Bits(8)==0x47)
342     {
343       sprintf(Error_Text,"Decoder currently does not parse transport streams\n");
344       Error(Error_Text);
345     }
346
347     next_start_code();
348     code = Show_Bits(32);
349
350     switch(code)
351     {
352     case SEQUENCE_HEADER_CODE:
353       break;
354     case PACK_START_CODE:
355       System_Stream_Flag = 1;
356     case VIDEO_ELEMENTARY_STREAM:
357       System_Stream_Flag = 1;
358       break;
359     default:
360       sprintf(Error_Text,"Unable to recognize stream type\n");
361       Error(Error_Text);
362       break;
363     }
364
365     //lseek(base.Infile, 0l, SEEK_SET);
366     //fp->seekg(mpeg_start, ios_base::beg);
367     Initialize_Buffer(); 
368   }
369
370   if(base.Infile!=0)
371   {
372     //lseek(base.Infile, 0l, SEEK_SET);
373     //fp->seekg(mpeg_start, ios_base::beg);
374   }
375
376   Initialize_Buffer(); 
377
378   if(Two_Streams)
379   {
380   abort();
381     ld = &enhan; /* select enhancement layer context */
382
383     if ((enhan.Infile = open(Enhancement_Layer_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
384     {
385       sprintf(Error_Text,"enhancment layer bitstream file %s not found\n",
386         Enhancement_Layer_Bitstream_Filename);
387
388       Error(Error_Text);
389     }
390
391     Initialize_Buffer();
392     ld = &base;
393   }
394
395   Initialize_Decoder();
396
397   ret = Decode_Bitstream();
398
399   //close(base.Infile);
400
401   if (Two_Streams)
402     {
403     abort();
404     close(enhan.Infile);
405     }
406
407   return ret;
408 }
409
410 } // end namespace gdcm