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