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