]> Creatis software - gdcm.git/blob - src/gdcmMpeg.cxx
ENH: Cleanup got the thing mostly working
[gdcm.git] / src / gdcmMpeg.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmMpeg.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/10/27 19:57:21 $
7   Version:   $Revision: 1.7 $
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 #if 1
327   fp->read((char*)image_buffer, length);
328   std::ofstream out("/tmp/etiam.mpeg");
329   out.write((char*)image_buffer, length);
330   out.close();
331 #endif
332
333   int ret, code;
334   istream bos,eos;
335   /*base.open_stream = my_open;*/
336   base.seek_stream = my_seek;
337   base.read_stream = my_read;
338   base.close_stream = my_close;
339
340   Verbose_Flag                         = 0;
341   Output_Type                          = T_MEM; //store in mem
342   Output_Picture_Filename              = "/tmp/rec%d";
343   hiQdither                            = 0;
344   Frame_Store_Flag                     = 1;
345   Spatial_Flag                         = 0;
346   Lower_Layer_Picture_Filename         = "";
347   Reference_IDCT_Flag                  = 1;
348   Trace_Flag                           = 0;
349   Quiet_Flag                           = 0;
350   Ersatz_Flag                          = 0;
351   Substitute_Picture_Filename          = "";
352   Two_Streams                          = 0;
353   Enhancement_Layer_Bitstream_Filename = "";
354   Big_Picture_Flag                     = 0;
355   Main_Bitstream_Flag                  = 1;
356   Main_Bitstream_Filename              = "/tmp/etiam.mpeg";
357   Main_Bitstream_Filename              = "/tmp/ts.mpg";
358   Verify_Flag                          = 0;
359   Stats_Flag                           = 0;
360   User_Data_Flag                       = 0;
361   OUTMEM                               = (char*)image_buffer;
362
363
364   ld = &base; /* select base layer context */
365
366   /* open MPEG base layer bitstream file(s) */
367   /* NOTE: this is either a base layer stream or a spatial enhancement stream */
368 /*  if ((base.Infile=open(Main_Bitstream_Filename,O_RDONLY|O_BINARY))<0) */
369   /*base.Infile = ld->open_stream(Main_Bitstream_Filename);*/
370   base.Infile = &bos;
371 #ifdef FILESTAR
372   //base.Infile->InFd = fopen(Main_Bitstream_Filename, "rb");
373   base.Infile->InFd.open(Main_Bitstream_Filename, std::ios::binary | std::ios::in);
374 #else
375   base.Infile->InFd = open(Main_Bitstream_Filename,O_RDONLY|O_BINARY );
376 #endif
377   if( !base.Infile->InFd)
378   {
379     fprintf(stderr,"Base layer input file %s not found\n", Main_Bitstream_Filename);
380     exit(1);
381   }
382
383
384   if(base.Infile != 0)
385   {
386     Initialize_Buffer();
387
388     if(Show_Bits(8)==0x47)
389     {
390       sprintf(Error_Text,"Decoder currently does not parse transport streams\n");
391       Error(Error_Text);
392     }
393
394     next_start_code();
395     code = Show_Bits(32);
396
397     switch(code)
398     {
399     case SEQUENCE_HEADER_CODE:
400       break;
401     case PACK_START_CODE:
402       System_Stream_Flag = 1;
403     case VIDEO_ELEMENTARY_STREAM:
404       System_Stream_Flag = 1;
405       break;
406     default:
407       sprintf(Error_Text,"Unable to recognize stream type\n");
408       Error(Error_Text);
409       break;
410     }
411
412     /*lseek(base.Infile, 0l, SEEK_SET);*/
413     ld->seek_stream(base.Infile,0l,SEEK_SET);
414     Initialize_Buffer(); 
415   }
416
417   if(base.Infile!=0)
418   {
419     /*lseek(base.Infile, 0l, SEEK_SET);*/
420     ld->seek_stream(base.Infile,0l,SEEK_SET);
421   }
422
423   Initialize_Buffer(); 
424
425   if(Two_Streams)
426   {
427     ld = &enhan; /* select enhancement layer context */
428
429     /*if ((enhan.Infile = open(Enhancement_Layer_Bitstream_Filename,O_RDONLY|O_BINARY))<0)*/
430     /*enhan.Infile = ld->open_stream(Enhancement_Layer_Bitstream_Filename);*/
431     enhan.Infile = &eos;
432 #ifdef FILESTAR
433     //enhan.Infile->InFd = fopen(Main_Bitstream_Filename, "rb");
434     enhan.Infile->InFd.open(Main_Bitstream_Filename, std::ios::binary|std::ios::in);
435 #else
436     enhan.Infile->InFd = open(Enhancement_Layer_Bitstream_Filename,O_RDONLY|O_BINARY);
437 #endif
438     if (enhan.Infile->InFd)
439     {
440       sprintf(Error_Text,"enhancment layer bitstream file %s not found\n",
441         Enhancement_Layer_Bitstream_Filename);
442
443       Error(Error_Text);
444     }
445
446     Initialize_Buffer();
447     ld = &base;
448   }
449
450   Initialize_Decoder();
451
452   ret = Decode_Bitstream();
453
454   /*close(base.Infile);*/
455   ld->close_stream(base.Infile);
456
457   if (Two_Streams)
458     /*close(enhan.Infile);*/
459     ld->close_stream(enhan.Infile);
460
461   DeInitialize_Decoder();
462
463 #if 0
464   std::ofstream out2("/tmp/etiam.raw");
465   out2.write((char*)image_buffer, 352*240*3*10);
466   out2.close();
467 #endif
468
469   return ret;
470 }
471
472 } // end namespace gdcm