]> Creatis software - gdcm.git/blob - src/gdcmmpeg2/src/mpeg2dec/subspic.c
COMP: Fix compilation on Win32 system without unistd.h but instead io.h
[gdcm.git] / src / gdcmmpeg2 / src / mpeg2dec / subspic.c
1 /* #define DEBUG */
2 /* subspic.c, Frame buffer substitution routines */
3
4 /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
5
6 /*
7  * Disclaimer of Warranty
8  *
9  * These software programs are available to the user without any license fee or
10  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
11  * any and all warranties, whether express, implied, or statuary, including any
12  * implied warranties or merchantability or of fitness for a particular
13  * purpose.  In no event shall the copyright-holder be liable for any
14  * incidental, punitive, or consequential damages of any kind whatsoever
15  * arising from the use of these programs.
16  *
17  * This disclaimer of warranty extends to the user of these programs and user's
18  * customers, employees, agents, transferees, successors, and assigns.
19  *
20  * The MPEG Software Simulation Group does not represent or warrant that the
21  * programs furnished hereunder are free of infringement of any third-party
22  * patents.
23  *
24  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
25  * are subject to royalty fees to patent holders.  Many of these patents are
26  * general enough such that they are unavoidable regardless of implementation
27  * design.
28  *
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <fcntl.h>
34
35 #include "config.h"
36 #include "global.h"
37
38 /* private prototypes*/
39 static void Read_Frame _ANSI_ARGS_((char *filename, 
40   unsigned char *frame_buffer[], int framenum));
41 static void Copy_Frame _ANSI_ARGS_((unsigned char *src, unsigned char *dst, 
42   int width, int height, int parity, int incr));
43 static int Read_Components _ANSI_ARGS_ ((char *filename, 
44   unsigned char *frame[3], int framenum));
45 static int Read_Component _ANSI_ARGS_ ((char *fname, unsigned char *frame, 
46   int width, int height));
47 static int Extract_Components _ANSI_ARGS_ ((char *filename,
48   unsigned char *frame[3], int framenum));
49
50
51 /* substitute frame buffer routine */
52 void Substitute_Frame_Buffer (bitstream_framenum, sequence_framenum)
53 int bitstream_framenum;
54 int sequence_framenum;
55 {
56   /* static tracking variables */
57   static int previous_temporal_reference;
58   static int previous_bitstream_framenum;
59   static int previous_anchor_temporal_reference;
60   static int previous_anchor_bitstream_framenum;
61   static int previous_picture_coding_type;
62   static int bgate;
63   
64   /* local temporary variables */
65   int substitute_display_framenum;
66
67
68 #ifdef DEBUG
69   printf("SUB: seq fn(%d) bitfn(%d) tempref(%d) picstr(%d) type(%d)\n", 
70     sequence_framenum, bitstream_framenum, temporal_reference, 
71     picture_structure, picture_coding_type);
72 #endif
73
74   /* we don't substitute at the first picture of a sequence */
75   if((sequence_framenum!=0)||(Second_Field))
76   {
77     /* only at the start of the frame */
78     if ((picture_structure==FRAME_PICTURE)||(!Second_Field))
79     {
80       if(picture_coding_type==P_TYPE)
81       {
82         /* the most recently decoded reference frame needs substituting */
83         substitute_display_framenum = bitstream_framenum - 1;
84         
85         Read_Frame(Substitute_Picture_Filename, forward_reference_frame, 
86           substitute_display_framenum);
87       }
88       /* only the first B frame in a consequitve set of B pictures
89          loads a substitute backward_reference_frame since all subsequent
90          B frames predict from the same reference pictures */
91       else if((picture_coding_type==B_TYPE)&&(bgate!=1))
92       {
93         substitute_display_framenum = 
94           (previous_temporal_reference - temporal_reference) 
95             + bitstream_framenum - 1;
96
97         Read_Frame(Substitute_Picture_Filename, backward_reference_frame, 
98           substitute_display_framenum);
99       }
100     } /* P fields can predict from the two most recently decoded fields, even
101          from the first field of the same frame being decoded */
102     else if(Second_Field && (picture_coding_type==P_TYPE))
103     {
104       /* our favourite case: the IP field picture pair */
105       if((previous_picture_coding_type==I_TYPE)&&(picture_coding_type==P_TYPE))
106       {
107         substitute_display_framenum = bitstream_framenum;
108       }
109       else /* our more generic P field picture pair */
110       {
111         substitute_display_framenum = 
112           (temporal_reference - previous_anchor_temporal_reference) 
113             + bitstream_framenum - 1;
114       }
115
116       Read_Frame(Substitute_Picture_Filename, current_frame, substitute_display_framenum);
117     }
118 #ifdef DEBUG
119     else if((picture_coding_type!=B_TYPE)||(picture_coding_type!=D_TYPE))
120     {
121       printf("NO SUBS FOR THIS PICTURE\n");
122     }
123 #endif
124   }
125
126
127   /* set b gate so we don't redundantly load next time around */
128   if(picture_coding_type==B_TYPE)
129     bgate = 1;
130   else
131     bgate = 0;
132
133   /* update general tracking variables */
134   if((picture_structure==FRAME_PICTURE)||(!Second_Field))
135   {
136     previous_temporal_reference  = temporal_reference;
137     previous_bitstream_framenum  = bitstream_framenum;
138   }
139   
140   /* update reference frame tracking variables */
141   if((picture_coding_type!=B_TYPE) && 
142     ((picture_structure==FRAME_PICTURE)||Second_Field))
143   {
144     previous_anchor_temporal_reference  = temporal_reference;
145     previous_anchor_bitstream_framenum  = bitstream_framenum;
146   }
147
148   previous_picture_coding_type = picture_coding_type;
149
150 }
151
152
153 /* Note: fields are only read to serve as the same-frame reference for 
154    a second field */
155 static void Read_Frame(fname,frame,framenum)
156 char *fname;
157 unsigned char *frame[];
158 int framenum;
159 {
160   int parity;
161   int rerr = 0;
162   int field_mode;
163
164   if(framenum<0)
165     printf("ERROR: framenum (%d) is less than zero\n", framenum);
166
167
168   if(Big_Picture_Flag)
169     rerr = Extract_Components(fname, substitute_frame, framenum);
170   else
171     rerr = Read_Components(fname, substitute_frame, framenum);
172
173   if(rerr!=0)
174   {
175     printf("was unable to substitute frame\n");
176   }
177
178   /* now copy to the appropriate buffer */
179   /* first field (which we are attempting to substitute) must be
180      of opposite field parity to the current one */
181   if((Second_Field)&&(picture_coding_type==P_TYPE))
182   {
183     parity      = (picture_structure==TOP_FIELD ? 1:0);      
184     field_mode  = (picture_structure==FRAME_PICTURE ? 0:1);
185   }
186   else
187   {
188     /* Like frame structued pictures, B pictures only substitute an entire frame 
189        since both fields always predict from the same frame (with respect 
190        to forward/backwards directions) */
191     parity = 0;
192     field_mode = 0;
193   }
194
195
196   Copy_Frame(substitute_frame[0], frame[0], Coded_Picture_Width, 
197     Coded_Picture_Height, parity, field_mode);
198   
199   Copy_Frame(substitute_frame[1], frame[1], Chroma_Width, Chroma_Height, 
200     parity, field_mode);
201   
202   Copy_Frame(substitute_frame[2], frame[2], Chroma_Width, Chroma_Height,
203     parity, field_mode);
204
205 #ifdef VERBOSE
206   if(Verbose_Flag > NO_LAYER)
207     printf("substituted %s %d\n",
208       (field_mode ? (parity?"bottom field":"bottom field"):"frame"), framenum);
209 #endif
210 }
211
212
213
214
215 static int Read_Components(filename, frame, framenum) 
216 char *filename;
217 unsigned char *frame[3];
218 int framenum;
219 {
220   int err = 0;
221   char outname[FILENAME_LENGTH];
222   char name[FILENAME_LENGTH];
223
224   sprintf(outname,filename,framenum);
225
226
227   sprintf(name,"%s.Y",outname);
228   err += Read_Component(name, frame[0], Coded_Picture_Width, 
229     Coded_Picture_Height);
230
231   sprintf(name,"%s.U",outname);
232   err += Read_Component(name, frame[1], Chroma_Width, Chroma_Height);
233
234   sprintf(name,"%s.V",outname);
235   err += Read_Component(name, frame[2], Chroma_Width, Chroma_Height);
236
237   return(err);
238 }
239
240
241 static int Read_Component(Filename, Frame, Width, Height)
242 char *Filename;
243 unsigned char *Frame;
244 int Width;
245 int Height;
246 {
247   int Size;
248   int Bytes_Read;
249   int Infile;
250
251   Size = Width*Height;
252
253 #ifdef DEBUG
254   printf("SUBS: reading %s\n", filename);
255 #endif
256
257   if(!(Infile=open(Filename,O_RDONLY|O_BINARY))<0)
258   {
259     printf("ERROR: unable to open reference filename (%s)\n", Filename);
260     return(-1);
261   }
262
263   Bytes_Read = read(Infile, Frame, Size);
264   
265   if(Bytes_Read!=Size)
266   {
267     printf("was able to read only %d bytes of %d of file %s\n",
268       Bytes_Read, Size, Filename);
269   }
270  
271   close(Infile); 
272   return(0);
273 }
274
275
276 /* optimization: do not open the big file each time. Open once at start
277    of decoder, and close at the very last frame */
278
279 /* Note: "big" files were used in E-mail exchanges almost exclusively by the 
280    MPEG Committee's syntax validation and conformance ad-hoc groups from 
281    the year 1993 until 1995 */
282 static int Extract_Components(filename, frame, framenum) 
283 char *filename;
284 unsigned char *frame[3];
285 int framenum;
286 {
287 /*  int err = 0; */
288   FILE *fd;
289   int line;
290   int size, offset;
291
292
293   if (!(fd = fopen(filename,"rb")))
294   {
295     sprintf(Error_Text,"Couldn't open %s\n",filename);
296     return(-1);
297   }
298
299   /* compute size of each frame (in bytes) */
300   size = (Coded_Picture_Width*Coded_Picture_Height);
301
302   if(chroma_format==CHROMA444)
303     size = (size * 3);
304   else if(chroma_format==CHROMA422)
305     size = (size * 2);
306   else if(chroma_format==CHROMA420)
307     size = ((size*3)>>1);
308   else
309     printf("ERROR: chroma_format (%d) not recognized\n", chroma_format);
310
311
312   /* compute distance into "big" file */
313   offset = size*framenum;
314
315 #ifdef DEBUG
316   printf("EXTRACTING: frame(%d) offset(%d), size (%d) from %s\n", 
317     framenum, offset, size, filename);
318 #endif
319
320   /* seek to location in big file where desired frame begins */
321   /* note: this offset cannot exceed a few billion bytes due to the */
322   /*       obvious limitations of 32-bit integers */
323   fseek(fd, offset, 0);
324
325   /* Y  */
326   for (line=0; line<Coded_Picture_Height; line++)
327   {
328     fread(frame[0]+(line*Coded_Picture_Width),1,Coded_Picture_Width,fd);
329   }
330
331   /* Cb */
332   for (line=0; line<Chroma_Height; line++)
333   {
334     fread(frame[1]+(line*Chroma_Width),1,Chroma_Width,fd);
335   }
336
337   /* Cr */
338   for (line=0; line<Chroma_Height; line++)
339   {
340     fread(frame[2]+(line*Chroma_Width),1,Chroma_Width,fd);
341   }
342
343
344   fclose(fd);
345   return(0);
346 }
347
348
349 static void Copy_Frame(src, dst, width, height, parity, field_mode)
350 unsigned char *src;
351 unsigned char *dst;
352 int width;
353 int height;
354 int parity;        /* field parity (top or bottom) to overwrite */
355 int field_mode;    /* 0 = frame, 1 = field                      */
356 {
357   int row, col;
358   int s, d;
359   int incr;
360
361   s = d = 0;
362
363 #ifdef DEBUG
364   printf("COPYING (w=%d, h=%d, parity=%d, field_mode=%d)\n",
365     width,height,parity,field_mode);
366 #endif /* DEBUG */
367
368   if(field_mode)
369   {
370     incr = 2;
371
372     if(parity==0)
373       s += width;
374   }
375   else
376   {
377     incr = 1;
378   }
379
380   for(row=0; row<height; row+=incr) 
381   {
382     for(col=0; col<width; col++)
383     {
384       dst[d+col] = src[s+col];
385     }
386     
387     d += (width*incr);
388     s += (width*incr);
389   }
390
391 }
392