]> Creatis software - gdcm.git/blob - src/gdcmMpeg.cxx
Enhance gdcm::File::IsReable() heuristics to be able to process some Loic
[gdcm.git] / src / gdcmMpeg.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmMpeg.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/06/24 10:55:59 $
7   Version:   $Revision: 1.5 $
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
248 static int video_sequence(int *Bitstream_Framenumber)
249 {
250   int Bitstream_Framenum;
251   int Sequence_Framenum;
252   int Return_Value;
253
254   Bitstream_Framenum = *Bitstream_Framenumber;
255   Sequence_Framenum=0;
256
257   Initialize_Sequence();
258
259   /* decode picture whose header has already been parsed in 
260      Decode_Bitstream() */
261
262
263   Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
264
265   /* update picture numbers */
266   if ( !Second_Field )
267   {
268     Bitstream_Framenum++;
269     Sequence_Framenum++;
270   }
271
272   /* loop through the rest of the pictures in the sequence */
273   while ((Return_Value=Headers()))
274   {
275     Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
276
277     if ( !Second_Field )
278     {
279       Bitstream_Framenum++;
280       Sequence_Framenum++;
281     }
282   }
283
284   /* put last frame */
285   if (Sequence_Framenum!=0)
286   {
287     Output_Last_Frame_of_Sequence(Bitstream_Framenum);
288   }
289
290   Deinitialize_Sequence();
291
292 #ifdef VERIFY
293     Clear_Verify_Headers();
294 #endif /* VERIFY */
295
296   *Bitstream_Framenumber = Bitstream_Framenum;
297   return(Return_Value);
298 }
299 } // End "C" extern
300
301 namespace gdcm 
302 {
303 /**
304  * \brief   routine for MPEG decompression 
305  * @param fp pointer to an already open file descriptor 
306  *                      8 significant bits per pixel
307  * @param image_buffer to receive uncompressed pixels
308  * @param length length
309  * @return 1 on success, 0 on error
310  */
311
312 bool ReadMPEGFile (std::ifstream *fp, void *image_buffer, size_t length)
313 {
314   int ret, code;
315
316 #if 0
317   fp->read((char*)image_buffer, length);
318
319   ofstream out("/tmp/etiam.mpeg");
320   out.write((char*)image_buffer, length);
321   out.close();
322 #endif
323
324 //  Clear_Options();
325
326   /* decode command line arguments */
327 //  Process_Options(argc,argv);
328
329 #ifdef DEBUG
330   Print_Options();
331 #endif
332
333   ld = &base; /* select base layer context */
334
335   /* open MPEG base layer bitstream file(s) */
336   /* NOTE: this is either a base layer stream or a spatial enhancement stream */
337 #if 0
338   if ((base.Infile=open(Main_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
339   {
340     fprintf(stderr,"Base layer input file %s not found\n", Main_Bitstream_Filename);
341     exit(1);
342   }
343 #else
344   base.Infile = -1; //DEBUG
345 #endif
346
347
348   if ( base.Infile != 0 )
349   {
350     Initialize_Buffer(); 
351   
352     if ( Show_Bits(8)==0x47 )
353     {
354       sprintf(Error_Text,"Decoder currently does not parse transport streams\n");
355       Error(Error_Text);
356     }
357
358     next_start_code();
359     code = Show_Bits(32);
360
361     switch(code)
362     {
363     case SEQUENCE_HEADER_CODE:
364       break;
365     case PACK_START_CODE:
366       System_Stream_Flag = 1;
367     case VIDEO_ELEMENTARY_STREAM:
368       System_Stream_Flag = 1;
369       break;
370     default:
371       sprintf(Error_Text,"Unable to recognize stream type\n");
372       Error(Error_Text);
373       break;
374     }
375
376     //lseek(base.Infile, 0l, SEEK_SET);
377     //fp->seekg(mpeg_start, ios_base::beg);
378     Initialize_Buffer(); 
379   }
380
381   if ( base.Infile!=0 )
382   {
383     //lseek(base.Infile, 0l, SEEK_SET);
384     //fp->seekg(mpeg_start, ios_base::beg);
385   }
386
387   Initialize_Buffer(); 
388
389   if ( Two_Streams )
390   {
391   abort();
392     ld = &enhan; /* select enhancement layer context */
393
394     if ( (enhan.Infile = open(Enhancement_Layer_Bitstream_Filename,O_RDONLY|O_BINARY))<0)
395     {
396       sprintf(Error_Text,"enhancment layer bitstream file %s not found\n",
397         Enhancement_Layer_Bitstream_Filename);
398
399       Error(Error_Text);
400     }
401
402     Initialize_Buffer();
403     ld = &base;
404   }
405
406   Initialize_Decoder();
407
408   ret = Decode_Bitstream();
409
410   //close(base.Infile);
411
412   if ( Two_Streams )
413     {
414     abort();
415     close(enhan.Infile);
416     }
417
418   return ret;
419 }
420
421 } // end namespace gdcm