]> Creatis software - gdcm.git/blob - src/gdcmMpeg.cxx
COMP: Fix warning
[gdcm.git] / src / gdcmMpeg.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmMpeg.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/11/04 15:46:52 $
7   Version:   $Revision: 1.9 $
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
22
23 typedef struct
24 {
25   std::ifstream *InFd;
26 } istream;
27 extern "C" {
28 #define GLOBAL
29 #include "config.h"
30 #include "global.h"
31 }
32
33
34 off_t my_seek(istream *infile, off_t offset, int whence)
35 {
36   //return fseek(infile->InFd,offset, whence);
37   switch(whence)
38     {
39     case SEEK_SET:
40       infile->InFd->seekg(offset, std::ios::beg);
41       break;
42     case SEEK_END:
43       infile->InFd->seekg(offset, std::ios::end);
44       break;
45     case SEEK_CUR:
46       infile->InFd->seekg(offset, std::ios::cur);
47       break;
48     }
49   return infile->InFd->tellg();
50 }
51 ssize_t my_read(istream *infile, void *buf, size_t count)
52 {
53   //return fread(buf,1,count, infile->InFd);
54   infile->InFd->read((char*)buf, count);
55   return infile->InFd->gcount();
56 }
57
58 int my_close(istream *infile)
59 {
60   //return fclose(infile->InFd);
61   infile->InFd->close();
62   return 0;
63 }
64
65 namespace gdcm 
66 {
67 /**
68  * \brief   routine for MPEG decompression 
69  * @param fp pointer to an already open file descriptor 
70  *                      8 significant bits per pixel
71  * @param image_buffer to receive uncompressed pixels
72  * @param length length
73  * @return 1 on success, 0 on error
74  */
75 static int Headers();
76 static void DeInitialize_Decoder()
77 {
78   free(Clip-384); /* I love magic number */
79 }
80 static void Deinitialize_Sequence()
81 {
82   int i;
83
84   /* First cleanup the static buffer in store.c */
85   FreeStaticBuffer();
86
87   /* clear flags */
88   base.MPEG2_Flag=0;
89
90   for(i=0;i<3;i++)
91   {
92     free(backward_reference_frame[i]);
93     free(forward_reference_frame[i]);
94     free(auxframe[i]);
95
96     if (base.scalable_mode==SC_SPAT)
97     {
98      free(llframe0[i]);
99      free(llframe1[i]);
100     }
101   }
102
103   if (base.scalable_mode==SC_SPAT)
104     free(lltmp);
105
106 #ifdef DISPLAY
107   if (Output_Type==T_X11) 
108     Terminate_Display_Process();
109 #endif
110 }
111
112 /* mostly IMPLEMENTAION specific routines */
113 static void Initialize_Sequence()
114 {
115   int cc, size;
116   static int Table_6_20[3] = {6,8,12};
117
118   /* check scalability mode of enhancement layer */
119   if (Two_Streams && (enhan.scalable_mode!=SC_SNR) && (base.scalable_mode!=SC_DP))
120     Error("unsupported scalability mode\n");
121
122   /* force MPEG-1 parameters for proper decoder behavior */
123   /* see ISO/IEC 13818-2 section D.9.14 */
124   if (!base.MPEG2_Flag)
125   {
126     progressive_sequence = 1;
127     progressive_frame = 1;
128     picture_structure = FRAME_PICTURE;
129     frame_pred_frame_dct = 1;
130     chroma_format = CHROMA420;
131     matrix_coefficients = 5;
132   }
133
134   /* round to nearest multiple of coded macroblocks */
135   /* ISO/IEC 13818-2 section 6.3.3 sequence_header() */
136   mb_width = (horizontal_size+15)/16;
137   mb_height = (base.MPEG2_Flag && !progressive_sequence) ? 2*((vertical_size+31)/32)
138                                         : (vertical_size+15)/16;
139
140   Coded_Picture_Width = 16*mb_width;
141   Coded_Picture_Height = 16*mb_height;
142
143   /* ISO/IEC 13818-2 sections 6.1.1.8, 6.1.1.9, and 6.1.1.10 */
144   Chroma_Width = (chroma_format==CHROMA444) ? Coded_Picture_Width
145                                            : Coded_Picture_Width>>1;
146   Chroma_Height = (chroma_format!=CHROMA420) ? Coded_Picture_Height
147                                             : Coded_Picture_Height>>1;
148   
149   /* derived based on Table 6-20 in ISO/IEC 13818-2 section 6.3.17 */
150   block_count = Table_6_20[chroma_format-1];
151
152   for (cc=0; cc<3; cc++)
153   {
154     if (cc==0)
155       size = Coded_Picture_Width*Coded_Picture_Height;
156     else
157       size = Chroma_Width*Chroma_Height;
158
159     if (!(backward_reference_frame[cc] = (unsigned char *)malloc(size)))
160       Error("backward_reference_frame[] malloc failed\n");
161
162     if (!(forward_reference_frame[cc] = (unsigned char *)malloc(size)))
163       Error("forward_reference_frame[] malloc failed\n");
164
165     if (!(auxframe[cc] = (unsigned char *)malloc(size)))
166       Error("auxframe[] malloc failed\n");
167
168     if(Ersatz_Flag)
169       if (!(substitute_frame[cc] = (unsigned char *)malloc(size)))
170         Error("substitute_frame[] malloc failed\n");
171
172
173     if (base.scalable_mode==SC_SPAT)
174     {
175       /* this assumes lower layer is 4:2:0 */
176       if (!(llframe0[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
177         Error("llframe0 malloc failed\n");
178       if (!(llframe1[cc] = (unsigned char *)malloc((lower_layer_prediction_horizontal_size*lower_layer_prediction_vertical_size)/(cc?4:1))))
179         Error("llframe1 malloc failed\n");
180     }
181   }
182
183   /* SCALABILITY: Spatial */
184   if (base.scalable_mode==SC_SPAT)
185   {
186     if (!(lltmp = (short *)malloc(lower_layer_prediction_horizontal_size*((lower_layer_prediction_vertical_size*vertical_subsampling_factor_n)/vertical_subsampling_factor_m)*sizeof(short))))
187       Error("lltmp malloc failed\n");
188   }
189
190 #ifdef DISPLAY
191   if (Output_Type==T_X11)
192   {
193     Initialize_Display_Process("");
194     Initialize_Dither_Matrix();
195   }
196 #endif /* DISPLAY */
197
198 }
199 static int video_sequence(int *Bitstream_Framenumber)
200 //int *Bitstream_Framenumber;
201 {
202   int Bitstream_Framenum;
203   int Sequence_Framenum;
204   int Return_Value;
205
206   Bitstream_Framenum = *Bitstream_Framenumber;
207   Sequence_Framenum=0;
208
209   Initialize_Sequence();
210
211   /* decode picture whose header has already been parsed in 
212      Decode_Bitstream() */
213
214
215   Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
216
217   /* update picture numbers */
218   if (!Second_Field)
219   {
220     Bitstream_Framenum++;
221     Sequence_Framenum++;
222   }
223
224   /* loop through the rest of the pictures in the sequence */
225   while ((Return_Value=Headers()))
226   {
227     Decode_Picture(Bitstream_Framenum, Sequence_Framenum);
228
229     if (!Second_Field)
230     {
231       Bitstream_Framenum++;
232       Sequence_Framenum++;
233     }
234   }
235
236   /* put last frame */
237   if (Sequence_Framenum!=0)
238   {
239     Output_Last_Frame_of_Sequence(Bitstream_Framenum);
240   }
241
242   Deinitialize_Sequence();
243
244 #ifdef VERIFY
245     Clear_Verify_Headers();
246 #endif /* VERIFY */
247
248   *Bitstream_Framenumber = Bitstream_Framenum;
249   return(Return_Value);
250 }
251
252 static int Headers()
253 {
254   int ret;
255
256   ld = &base;
257   
258
259   /* return when end of sequence (0) or picture
260      header has been parsed (1) */
261
262   ret = Get_Hdr();
263
264
265   if (Two_Streams)
266   {
267     ld = &enhan;
268     if (Get_Hdr()!=ret && !Quiet_Flag)
269       fprintf(stderr,"streams out of sync\n");
270     ld = &base;
271   }
272
273   return ret;
274 }
275 static int Decode_Bitstream()
276 {
277   int ret;
278   int Bitstream_Framenum;
279
280   Bitstream_Framenum = 0;
281
282   for(;;)
283   {
284
285 #ifdef VERIFY
286     Clear_Verify_Headers();
287 #endif /* VERIFY */
288
289     ret = Headers();
290     
291     if(ret==1)
292     {
293       ret = video_sequence(&Bitstream_Framenum);
294     }
295     else
296       return(ret);
297   }
298
299 }
300
301
302 /* IMPLEMENTATION specific routines */
303 static void Initialize_Decoder()
304 {
305   int i;
306
307   /* Clip table */
308   if (!(Clip=(unsigned char *)malloc(1024)))
309     Error("Clip[] malloc failed\n");
310
311   Clip += 384;
312
313   for (i=-384; i<640; i++)
314     Clip[i] = (i<0) ? 0 : ((i>255) ? 255 : i);
315
316   /* IDCT */
317   if (Reference_IDCT_Flag)
318     Initialize_Reference_IDCT();
319   else
320     Initialize_Fast_IDCT();
321
322 }
323
324 bool ReadMPEGFile (std::ifstream *fp, char *image_buffer, size_t length)
325 {
326   std::streampos mpeg_start = fp->tellg(); // the MPEG stream in our case does not start at 0
327 #if 0
328   fp->read((char*)image_buffer, length);
329   std::ofstream out("/tmp/etiam.mpeg");
330   out.write((char*)image_buffer, length);
331   out.close();
332 #else
333   (void)length;
334 #endif
335
336   int ret, code;
337   istream bos,eos;
338   /*base.open_stream = my_open;*/
339   base.seek_stream = my_seek;
340   base.read_stream = my_read;
341   base.close_stream = my_close;
342
343   Verbose_Flag                         = 0;
344   Output_Type                          = T_MEM; //store in mem
345   Output_Picture_Filename              = "/tmp/rec%d";
346   hiQdither                            = 0;
347   Frame_Store_Flag                     = 1;
348   Spatial_Flag                         = 0;
349   Lower_Layer_Picture_Filename         = "";
350   Reference_IDCT_Flag                  = 1;
351   Trace_Flag                           = 0;
352   Quiet_Flag                           = 0;
353   Ersatz_Flag                          = 0;
354   Substitute_Picture_Filename          = "";
355   Two_Streams                          = 0;
356   Enhancement_Layer_Bitstream_Filename = "";
357   Big_Picture_Flag                     = 0;
358   Main_Bitstream_Flag                  = 1;
359   Main_Bitstream_Filename              = "/tmp/etiam.mpeg";
360   Main_Bitstream_Filename              = "/tmp/ts.mpg";
361   Verify_Flag                          = 0;
362   Stats_Flag                           = 0;
363   User_Data_Flag                       = 0;
364   OUTMEM                               = (char*)image_buffer;
365
366
367   ld = &base; /* select base layer context */
368
369   /* open MPEG base layer bitstream file(s) */
370   /* NOTE: this is either a base layer stream or a spatial enhancement stream */
371 /*  if ((base.Infile=open(Main_Bitstream_Filename,O_RDONLY|O_BINARY))<0) */
372   /*base.Infile = ld->open_stream(Main_Bitstream_Filename);*/
373   base.Infile = &bos;
374 #ifdef FILESTAR
375   //base.Infile->InFd = fopen(Main_Bitstream_Filename, "rb");
376   //base.Infile->InFd.open(Main_Bitstream_Filename, std::ios::binary | std::ios::in);
377   base.Infile->InFd = fp;
378 #else
379   base.Infile->InFd = open(Main_Bitstream_Filename,O_RDONLY|O_BINARY );
380 #endif
381   if( !base.Infile->InFd)
382   {
383     fprintf(stderr,"Base layer input file %s not found\n", Main_Bitstream_Filename);
384     exit(1);
385   }
386
387
388   if(base.Infile != 0)
389   {
390     Initialize_Buffer();
391
392     if(Show_Bits(8)==0x47)
393     {
394       sprintf(Error_Text,"Decoder currently does not parse transport streams\n");
395       Error(Error_Text);
396     }
397
398     next_start_code();
399     code = Show_Bits(32);
400
401     switch(code)
402     {
403     case SEQUENCE_HEADER_CODE:
404       break;
405     case PACK_START_CODE:
406       System_Stream_Flag = 1;
407     case VIDEO_ELEMENTARY_STREAM:
408       System_Stream_Flag = 1;
409       break;
410     default:
411       sprintf(Error_Text,"Unable to recognize stream type\n");
412       Error(Error_Text);
413       break;
414     }
415
416     /*lseek(base.Infile, 0l, SEEK_SET);*/
417     ld->seek_stream(base.Infile,mpeg_start,SEEK_SET);
418     Initialize_Buffer(); 
419   }
420
421   if(base.Infile!=0)
422   {
423     /*lseek(base.Infile, 0l, SEEK_SET);*/
424     ld->seek_stream(base.Infile,mpeg_start,SEEK_SET);
425   }
426
427   Initialize_Buffer(); 
428
429   if(Two_Streams)
430   {
431     ld = &enhan; /* select enhancement layer context */
432
433     /*if ((enhan.Infile = open(Enhancement_Layer_Bitstream_Filename,O_RDONLY|O_BINARY))<0)*/
434     /*enhan.Infile = ld->open_stream(Enhancement_Layer_Bitstream_Filename);*/
435     enhan.Infile = &eos;
436 #ifdef FILESTAR
437     //enhan.Infile->InFd = fopen(Main_Bitstream_Filename, "rb");
438     enhan.Infile->InFd->open(Main_Bitstream_Filename, std::ios::binary|std::ios::in);
439     abort();
440 #else
441     enhan.Infile->InFd = open(Enhancement_Layer_Bitstream_Filename,O_RDONLY|O_BINARY);
442 #endif
443     if (enhan.Infile->InFd)
444     {
445       sprintf(Error_Text,"enhancment layer bitstream file %s not found\n",
446         Enhancement_Layer_Bitstream_Filename);
447
448       Error(Error_Text);
449     }
450
451     Initialize_Buffer();
452     ld = &base;
453   }
454
455   Initialize_Decoder();
456
457   ret = Decode_Bitstream();
458
459   /*close(base.Infile);*/
460   ld->close_stream(base.Infile);
461
462   if (Two_Streams)
463     /*close(enhan.Infile);*/
464     ld->close_stream(enhan.Infile);
465
466   DeInitialize_Decoder();
467
468 #if 0
469   std::ofstream out2("/tmp/etiam.raw");
470   out2.write((char*)image_buffer, 352*240*3*10);
471   out2.close();
472 #endif
473
474   return ret;
475 }
476
477 } // end namespace gdcm