]> Creatis software - gdcm.git/blob - src/gdcmMpeg.cxx
re indent
[gdcm.git] / src / gdcmMpeg.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmMpeg.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/09/17 12:20:01 $
7   Version:   $Revision: 1.14 $
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 /* IMPLEMENTATION specific routines */
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 IMPLEMENTATION specific routines */
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) 
69       &&
70        (base.scalable_mode!=SC_DP) )
71   {
72      Error("unsupported scalability mode\n");
73   }
74   /* force MPEG-1 parameters for proper decoder behavior */
75   /* see ISO/IEC 13818-2 section D.9.14 */
76   if ( !base.MPEG2_Flag )
77   {
78     progressive_sequence = 1;
79     progressive_frame = 1;
80     picture_structure = FRAME_PICTURE;
81     frame_pred_frame_dct = 1;
82     chroma_format = CHROMA420;
83     matrix_coefficients = 5;
84   }
85
86   /* round to nearest multiple of coded macroblocks */
87   /* ISO/IEC 13818-2 section 6.3.3 sequence_header() */
88   mb_width = (horizontal_size+15)/16;
89   mb_height = (base.MPEG2_Flag && !progressive_sequence) ? 2*((vertical_size+31)/32)
90                                         : (vertical_size+15)/16;
91
92   Coded_Picture_Width = 16*mb_width;
93   Coded_Picture_Height = 16*mb_height;
94
95   /* ISO/IEC 13818-2 sections 6.1.1.8, 6.1.1.9, and 6.1.1.10 */
96   Chroma_Width = (chroma_format==CHROMA444) ? Coded_Picture_Width
97                                            : Coded_Picture_Width>>1;
98   Chroma_Height = (chroma_format!=CHROMA420) ? Coded_Picture_Height
99                                             : Coded_Picture_Height>>1;
100   
101   /* derived based on Table 6-20 in ISO/IEC 13818-2 section 6.3.17 */
102   block_count = Table_6_20[chroma_format-1];
103
104   for (cc=0; cc<3; cc++)
105   {
106     if ( cc==0 )
107       size = Coded_Picture_Width*Coded_Picture_Height;
108     else
109       size = Chroma_Width*Chroma_Height;
110
111     if ( !(backward_reference_frame[cc] = (unsigned char *)malloc(size)) )
112       Error("backward_reference_frame[] malloc failed\n");
113
114     if ( !(forward_reference_frame[cc] = (unsigned char *)malloc(size)) )
115       Error("forward_reference_frame[] malloc failed\n");
116
117     if ( !(auxframe[cc] = (unsigned char *)malloc(size)) )
118       Error("auxframe[] malloc failed\n");
119
120     if ( Ersatz_Flag )
121       if ( !(substitute_frame[cc] = (unsigned char *)malloc(size)) )
122         Error("substitute_frame[] malloc failed\n");
123
124
125     if ( base.scalable_mode==SC_SPAT )
126     {
127       /* this assumes lower layer is 4:2:0 */
128       if ( !(llframe0[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
129         Error("llframe0 malloc failed\n");
130       if ( !(llframe1[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
131         Error("llframe1 malloc failed\n");
132     }
133   }
134
135   /* SCALABILITY: Spatial */
136   if ( base.scalable_mode==SC_SPAT )
137   {
138     if ( !(lltmp = (short *)malloc(lower_layer_prediction_horizontal_size*((lower_layer_prediction_vertical_size*vertical_subsampling_factor_n)/vertical_subsampling_factor_m)*sizeof(short))))
139       Error("lltmp malloc failed\n");
140   }
141
142 #ifdef DISPLAY
143   if (Output_Type==T_X11)
144   {
145     Initialize_Display_Process("");
146     Initialize_Dither_Matrix();
147   }
148 #endif /* DISPLAY */
149
150 }
151
152 extern void Error(char *text)
153 {
154   fprintf(stderr,text);
155   exit(1);
156 }
157
158 /* Trace_Flag output */
159 void Print_Bits(int code, int bits, int len)
160 {
161   int i;
162   for (i=0; i<len; i++)
163     printf("%d",(code>>(bits-1-i))&1);
164 }
165
166 static int Headers()
167 {
168   int ret;
169
170   ld = &base;
171  
172   /* return when end of sequence (0) or picture
173      header has been parsed (1) */
174
175   ret = Get_Hdr();
176
177
178   if (Two_Streams)
179   {
180     ld = &enhan;
181     if (Get_Hdr()!=ret && !Quiet_Flag)
182       fprintf(stderr,"streams out of sync\n");
183     ld = &base;
184   }
185
186   return ret;
187 }
188
189
190
191 static int Decode_Bitstream()
192 {
193   int ret;
194   int Bitstream_Framenum;
195
196   Bitstream_Framenum = 0;
197
198   for(;;)
199   {
200
201 #ifdef VERIFY
202     Clear_Verify_Headers();
203 #endif /* VERIFY */
204
205     ret = Headers();
206     
207     if ( ret==1 )
208     {
209       ret = video_sequence(&Bitstream_Framenum);
210     }
211     else
212       return(ret);
213   }
214
215 }
216
217
218 static void Deinitialize_Sequence()
219 {
220   int i;
221
222   /* clear flags */
223   base.MPEG2_Flag=0;
224
225   for(i=0;i<3;i++)
226   {
227     free(backward_reference_frame[i]);
228     free(forward_reference_frame[i]);
229     free(auxframe[i]);
230
231     if ( base.scalable_mode==SC_SPAT )
232     {
233      free(llframe0[i]);
234      free(llframe1[i]);
235     }
236   }
237
238   if ( base.scalable_mode==SC_SPAT )
239     free(lltmp);
240
241 #ifdef DISPLAY
242   if ( Output_Type==T_X11 ) 
243     Terminate_Display_Process();
244 #endif
245 }
246
247 static int video_sequence(int *Bitstream_Framenumber)
248 {
249   int Bitstream_Framenum;
250   int Sequence_Framenum;
251   int Return_Value;
252
253   Bitstream_Framenum = *Bitstream_Framenumber;
254   Sequence_Framenum=0;
255
256   Initialize_Sequence();
257
258   /* decode picture whose header has already been parsed in 
259      Decode_Bitstream() */
260
261
262   Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
263
264   /* update picture numbers */
265   if ( !Second_Field )
266   {
267     Bitstream_Framenum++;
268     Sequence_Framenum++;
269   }
270
271   /* loop through the rest of the pictures in the sequence */
272   while ((Return_Value=Headers()))
273   {
274     Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
275
276     if ( !Second_Field )
277     {
278       Bitstream_Framenum++;
279       Sequence_Framenum++;
280     }
281   }
282
283   /* put last frame */
284   if (Sequence_Framenum!=0)
285   {
286     Output_Last_Frame_of_Sequence(Bitstream_Framenum);
287   }
288
289   Deinitialize_Sequence();
290
291 #ifdef VERIFY
292     Clear_Verify_Headers();
293 #endif /* VERIFY */
294
295   *Bitstream_Framenumber = Bitstream_Framenum;
296   return(Return_Value);
297 }
298 } // End "C" extern
299
300 namespace GDCM_NAME_SPACE 
301 {
302 /**
303  * \brief   routine for MPEG decompression 
304  * @param fp pointer to an already open file descriptor 
305  *                      8 significant bits per pixel
306  * @param image_buffer to receive uncompressed pixels
307  * @param length length
308  * @return 1 on success, 0 on error
309  */
310 bool ReadMPEGFile (std::ifstream *fp, void *image_buffer, size_t length)
311 {
312   int ret, code;
313
314 #if 0
315   fp->read((char*)image_buffer, length);
316   ofstream out("/tmp/etiam.mpeg");
317   out.write((char*)image_buffer, length);
318   out.close();
319 #endif
320
321 //  Clear_Options();
322
323   /* decode command line arguments */
324 //  Process_Options(argc,argv);
325
326 #ifdef DEBUG
327   Print_Options();
328 #endif
329
330   ld = &base; /* select base layer context */
331
332   /* open MPEG base layer bitstream file(s) */
333   /* NOTE: this is either a base layer stream or a spatial enhancement stream */
334 #if 0
335   if ((base.Infile=open(Main_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
336   {
337     fprintf(stderr,"Base layer input file %s not found\n", Main_Bitstream_Filename);
338     exit(1);
339   }
340 #else
341   base.Infile = -1; //DEBUG
342 #endif
343
344
345   if ( base.Infile != 0 )
346   {
347     Initialize_Buffer(); 
348   
349     if ( Show_Bits(8)==0x47 )
350     {
351       sprintf(Error_Text,"Decoder currently does not parse transport streams\n");
352       Error(Error_Text);
353     }
354
355     next_start_code();
356     code = Show_Bits(32);
357
358     switch(code)
359     {
360     case SEQUENCE_HEADER_CODE:
361       break;
362     case PACK_START_CODE:
363       System_Stream_Flag = 1;
364     case VIDEO_ELEMENTARY_STREAM:
365       System_Stream_Flag = 1;
366       break;
367     default:
368       sprintf(Error_Text,"Unable to recognize stream type\n");
369       Error(Error_Text);
370       break;
371     }
372
373     //lseek(base.Infile, 0l, SEEK_SET);
374     //fp->seekg(mpeg_start, ios_base::beg);
375     Initialize_Buffer(); 
376   }
377
378   if ( base.Infile!=0 )
379   {
380     //lseek(base.Infile, 0l, SEEK_SET);
381     //fp->seekg(mpeg_start, ios_base::beg);
382   }
383
384   Initialize_Buffer(); 
385
386   if ( Two_Streams )
387   {
388   abort();
389     ld = &enhan; /* select enhancement layer context */
390
391     if ( (enhan.Infile = open(Enhancement_Layer_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
392     {
393       sprintf(Error_Text,"enhancment layer bitstream file %s not found\n",
394         Enhancement_Layer_Bitstream_Filename);
395
396       Error(Error_Text);
397     }
398
399     Initialize_Buffer();
400     ld = &base;
401   }
402
403   Initialize_Decoder();
404
405   ret = Decode_Bitstream();
406
407   //close(base.Infile);
408
409   if ( Two_Streams )
410     {
411     abort();
412     close(enhan.Infile);
413     }
414
415   return ret;
416 }
417
418 } // end namespace gdcm