1 /* predict.cc, motion compensated prediction                                 */
2 
3 /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
4 
5 /*
6  * Disclaimer of Warranty
7  *
8  * These software programs are available to the user without any license fee or
9  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
10  * any and all warranties, whether express, implied, or statuary, including any
11  * implied warranties or merchantability or of fitness for a particular
12  * purpose.  In no event shall the copyright-holder be liable for any
13  * incidental, punitive, or consequential damages of any kind whatsoever
14  * arising from the use of these programs.
15  *
16  * This disclaimer of warranty extends to the user of these programs and user's
17  * customers, employees, agents, transferees, successors, and assigns.
18  *
19  * The MPEG Software Simulation Group does not represent or warrant that the
20  * programs furnished hereunder are free of infringement of any third-party
21  * patents.
22  *
23  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
24  * are subject to royalty fees to patent holders.  Many of these patents are
25  * general enough such that they are unavoidable regardless of implementation
26  * design.
27  *
28  */
29 /* Modifications and enhancements (C) 2000/2001 Andrew Stevens */
30 
31 /* These modifications are free software; you can redistribute it
32  *  and/or modify it under the terms of the GNU General Public License
33  *  as published by the Free Software Foundation; either version 2 of
34  *  the License, or (at your option) any later version.
35  *
36  *  This program is distributed in the hope that it will be useful,
37  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
38  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39  *  General Public License for more details.
40  *
41  * You should have received a copy of the GNU General Public License
42  * along with this program; if not, write to the Free Software
43  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
44  * 02111-1307, USA.
45  *
46  */
47 
48 
49 #include "config.h"
50 #include <assert.h>
51 #include "mjpeg_logging.h"
52 #include "mpeg2encoder.hh"
53 #include "mpeg2syntaxcodes.h"
54 #include "picture.hh"
55 #include "macroblock.hh"
56 #include "imageplanes.hh"
57 #include "predict_ref.h"
58 
59 
60 /* predict a rectangular block (all three components)
61  *
62  * src:     source frame (Y,U,V)
63  * sfield:  source field select (0: frame or top field, 1: bottom field)
64  * dst:     destination frame (Y,U,V)
65  * dfield:  destination field select (0: frame or top field, 1: bottom field)
66  *
67  * the following values are in luminance picture (frame or field) dimensions
68  * lx:      distance of vertically adjacent pels (selects frame or field pred.)
69  * w,h:     width and height of block (only 16x16 or 16x8 are used)
70  * x,y:     coordinates of destination block
71  * dx,dy:   half pel motion vector
72  * addflag: store or add (= average) prediction
73  */
74 
pred(uint8_t * src[],int sfield,uint8_t * dst[],int dfield,int lx,int w,int h,int x,int y,int dx,int dy,bool addflag)75 void pred (	uint8_t *src[], int sfield,
76 			uint8_t *dst[], int dfield,
77 			int lx, int w, int h, int x, int y,
78 			int dx, int dy, bool addflag
79 	)
80 {
81 	int cc;
82 
83 	for (cc=0; cc<3; cc++)
84 	{
85 		if (cc==1)
86 		{
87 			/* scale for color components */
88 			/* vertical */
89 			h >>= 1; y >>= 1; dy /= 2;
90 			/* horizontal */
91 			w >>= 1; x >>= 1; dx /= 2;
92 			lx >>= 1;
93 		}
94 		ppred_comp(	src[cc]+(sfield?lx>>1:0),dst[cc]+(dfield?lx>>1:0),
95 					lx,w,h,x,y,dx,dy, (int)addflag);
96 	}
97 }
98 
99 
100 
101 /* calculate derived motion vectors (DMV) for dual prime prediction
102  * dmvector[2]: differential motion vectors (-1,0,+1)
103  * mvx,mvy: motion vector (for same parity)
104  *
105  * DMV[2][2]: derived motion vectors (for opposite parity)
106  *
107  * uses global variables pict_struct and topfirst
108  *
109  * Notes:
110  *  - all vectors are in field coordinates (even for frame pictures)
111  *
112  */
113 
114 #ifndef DEBUG_DPME
115 static
116 #endif
calc_DMV(const Picture & picture,MotionVector DMV[Parity::dim],MotionVector & dmvector,int mvx,int mvy)117 void calc_DMV( const Picture &picture, /*int pict_struct,  int topfirst,*/
118 					  MotionVector DMV[Parity::dim],
119 					  MotionVector &dmvector,
120 					  int mvx, int mvy
121 	)
122 {
123 	if (picture.pict_struct==FRAME_PICTURE)
124 	{
125 		if (picture.topfirst)
126 		{
127 			/* vector for prediction of top field from bottom field */
128 			DMV[0][0] = ((mvx  +(mvx>0))>>1) + dmvector[0];
129 			DMV[0][1] = ((mvy  +(mvy>0))>>1) + dmvector[1] - 1;
130 
131 			/* vector for prediction of bottom field from top field */
132 			DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
133 			DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1;
134 		}
135 		else
136 		{
137 			/* vector for prediction of top field from bottom field */
138 			DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
139 			DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1;
140 
141 			/* vector for prediction of bottom field from top field */
142 			DMV[1][0] = ((mvx  +(mvx>0))>>1) + dmvector[0];
143 			DMV[1][1] = ((mvy  +(mvy>0))>>1) + dmvector[1] + 1;
144 		}
145 	}
146 	else
147 	{
148 		/* vector for prediction from field of opposite 'parity' */
149 		DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0];
150 		DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1];
151 
152 		/* correct for vertical field shift */
153 		if (picture.pict_struct==TOP_FIELD)
154 			DMV[0][1]--;
155 		else
156 			DMV[0][1]++;
157 	}
158 }
159 
160 
161 /* form prediction for one macroblock
162  *
163  * lx:     frame width (identical to global var `width')
164  *
165  * Notes:
166  * - when predicting a P type picture which is the second field of
167  *   a frame, the same parity reference field is in oldref, while the
168  *   opposite parity reference field is assumed to be in newref!
169  * - intra macroblocks are modelled to have a constant prediction of 128
170  *   for all pels; this results in a DC DCT coefficient symmetric to 0
171  * - vectors for field prediction in frame pictures are in half pel frame
172  *   coordinates (vertical component is twice the field value and always
173  *   even)
174  *
175  * already covers dual prime (not yet used)
176  */
177 
Predict()178 void MacroBlock::Predict()
179 {
180     const Picture &picture = ParentPicture();
181     const int bx = TopleftX();
182     const int by = TopleftY();
183     uint8_t **fwd_rec = picture.fwd_rec->Planes();   // Forward prediction
184     uint8_t **bwd_rec = picture.bwd_rec->Planes();   // Backward prediction
185     uint8_t **cur = picture.pred->Planes();      // Frame to predict
186     int lx = picture.encparams.phy_width;
187     int lx2 = picture.encparams.phy_width;
188 
189     bool addflag;
190     int currentfield;
191     uint8_t **predframe;
192     MotionVector DMV[Parity::dim /*pred*/];
193 
194     if (best_me->mb_type&MB_INTRA)
195     {
196         clearblock( cur,bx,by,
197                     picture.pict_struct==BOTTOM_FIELD ? lx : 0,
198                     lx2);
199         return;
200     }
201 
202     addflag = false; /* first prediction is stored, second is added and averaged */
203 
204     if ((best_me->mb_type & MB_FORWARD) || (picture.pict_type==P_TYPE))
205     {
206         /* forward prediction, including zero MV in P pictures */
207 
208         if (picture.pict_struct==FRAME_PICTURE)
209         {
210             /* frame picture */
211 
212             if ( (best_me->motion_type==MC_FRAME)
213                     || !(best_me->mb_type & MB_FORWARD))
214             {
215                 /* frame-based prediction in frame picture */
216                 pred( fwd_rec,0,cur,0,
217                     lx,16,16,bx,by,best_me->MV[0][0][0],best_me->MV[0][0][1],false);
218             }
219             else if (best_me->motion_type==MC_FIELD)
220             {
221                 /* field-based prediction in frame picture
222                 *
223                 * note scaling of the vertical coordinates (by, MV[][0][1])
224                 * from frame to field!
225                 */
226 
227                 /* top field prediction */
228                 pred(fwd_rec,best_me->field_sel[0][0],cur,0,
229                     lx<<1,16,8,bx,by>>1,
230                     best_me->MV[0][0][0],best_me->MV[0][0][1]>>1,false);
231 
232                 /* bottom field prediction */
233                 pred(fwd_rec,best_me->field_sel[1][0],cur,1,
234                     lx<<1,16,8,bx,by>>1,
235                     best_me->MV[1][0][0],best_me->MV[1][0][1]>>1,false);
236             }
237             else if (best_me->motion_type==MC_DMV)
238             {
239                 /* dual prime prediction calculate derived motion vectors */
240                 calc_DMV(picture,
241                         DMV,
242                         best_me->dualprimeMV,
243                         best_me->MV[0][0][0],
244                         best_me->MV[0][0][1]>>1);
245 
246 
247                 /* predict top field from top field */
248                 pred(fwd_rec,0,cur,0,
249                     lx<<1,16,8,bx,by>>1,
250                     best_me->MV[0][0][0],best_me->MV[0][0][1]>>1,false);
251 
252                 /* predict bottom field from bottom field */
253                 pred(fwd_rec,1,cur,1,
254                     lx<<1,16,8,bx,by>>1,
255                     best_me->MV[0][0][0],best_me->MV[0][0][1]>>1,false);
256 
257                 /* predict and add to top field from bottom field */
258                 pred(fwd_rec,1,cur,0,
259                     lx<<1,16,8,bx,by>>1,
260                     DMV[0][0],DMV[0][1],true);
261 
262 
263                 /* predict and add to bottom field from top field */
264                 pred(fwd_rec,0,cur,1,
265                     lx<<1,16,8,bx,by>>1,
266                     DMV[1][0],DMV[1][1],true);
267             }
268             else
269             {
270                 /* invalid motion_type in frame picture */
271                 mjpeg_error_exit1("Internal: invalid motion_type");
272             }
273         }
274         else /* TOP_FIELD or BOTTOM_FIELD */
275         {
276             /* field picture */
277 
278             currentfield = (picture.pict_struct==BOTTOM_FIELD);
279 
280             /* determine which frame to use for prediction */
281             if ((picture.pict_type==P_TYPE) && picture.secondfield
282                     && (currentfield!=best_me->field_sel[0][0]))
283                 predframe = bwd_rec; /* same frame */
284             else
285                 predframe = fwd_rec; /* previous frame */
286 
287             if ( best_me->motion_type==MC_FIELD
288                     || !(best_me->mb_type & MB_FORWARD))
289             {
290                 /* field-based prediction in field picture */
291                 pred(predframe,best_me->field_sel[0][0],cur,currentfield,
292                     lx<<1,16,16,bx,by,
293                     best_me->MV[0][0][0],best_me->MV[0][0][1],false);
294             }
295             else if (best_me->motion_type==MC_16X8)
296             {
297                 /* 16 x 8 motion compensation in field picture */
298 
299                 /* upper half */
300                 pred(predframe,best_me->field_sel[0][0],cur,currentfield,
301                     lx<<1,16,8,bx,by,
302                     best_me->MV[0][0][0],best_me->MV[0][0][1],false);
303 
304                 /* determine which frame to use for lower half prediction */
305                 if ((picture.pict_type==P_TYPE) && picture.secondfield
306                         && (currentfield!=best_me->field_sel[1][0]))
307                     predframe = bwd_rec; /* same frame */
308                 else
309                     predframe = fwd_rec; /* previous frame */
310 
311                 /* lower half */
312                 pred(predframe,best_me->field_sel[1][0],cur,currentfield,
313                     lx<<1,16,8,bx,by+8,
314                     best_me->MV[1][0][0],best_me->MV[1][0][1],false);
315             }
316             else if (best_me->motion_type==MC_DMV)
317             {
318                 /* dual prime prediction */
319 
320                 /* determine which frame to use for prediction */
321                 if (picture.secondfield)
322                     predframe = bwd_rec; /* same frame */
323                 else
324                     predframe = fwd_rec; /* previous frame */
325 
326                 /* calculate derived motion vectors */
327                 calc_DMV(picture,
328                         DMV,best_me->dualprimeMV,
329                         best_me->MV[0][0][0],
330                         best_me->MV[0][0][1]);
331 
332                 /* predict from field of same parity */
333                 pred(fwd_rec,currentfield,cur,currentfield,
334                     lx<<1,16,16,bx,by,
335                     best_me->MV[0][0][0],best_me->MV[0][0][1],false);
336 
337                 /* predict from field of opposite parity */
338                 pred(predframe,!currentfield,cur,currentfield,
339                     lx<<1,16,16,bx,by,
340                     DMV[0][0],DMV[0][1],true);
341             }
342             else
343             {
344                 /* invalid motion_type in field picture */
345                 mjpeg_error_exit1("Internal: invalid motion_type");
346             }
347         }
348         addflag = true; /* next prediction (if any) will be averaged with this one */
349     }
350 
351     if (best_me->mb_type & MB_BACKWARD)
352     {
353         /* backward prediction */
354 
355         if (picture.pict_struct==FRAME_PICTURE)
356         {
357             /* frame picture */
358 
359             if (best_me->motion_type==MC_FRAME)
360             {
361                 /* frame-based prediction in frame picture */
362                 pred(bwd_rec,0,cur,0,
363                     lx,16,16,bx,by,
364                     best_me->MV[0][1][0],best_me->MV[0][1][1],addflag);
365             }
366             else
367             {
368                 /* field-based prediction in frame picture
369                 *
370                 * note scaling of the vertical coordinates (by, MV[][1][1])
371                 * from frame to field!
372                 */
373 
374                 /* top field prediction */
375                 pred(bwd_rec,best_me->field_sel[0][1],cur,0,
376                     lx<<1,16,8,bx,by>>1,
377                     best_me->MV[0][1][0],best_me->MV[0][1][1]>>1,addflag);
378 
379                 /* bottom field prediction */
380                 pred(bwd_rec,best_me->field_sel[1][1],cur,1,
381                     lx<<1,16,8,bx,by>>1,
382                     best_me->MV[1][1][0],best_me->MV[1][1][1]>>1,addflag);
383             }
384         }
385         else /* TOP_FIELD or BOTTOM_FIELD */
386         {
387             /* field picture */
388 
389             currentfield = (picture.pict_struct==BOTTOM_FIELD);
390 
391             if (best_me->motion_type==MC_FIELD)
392             {
393                 /* field-based prediction in field picture */
394                 pred(bwd_rec,best_me->field_sel[0][1],cur,currentfield,
395                     lx<<1,16,16,bx,by,
396                     best_me->MV[0][1][0],best_me->MV[0][1][1],addflag);
397             }
398             else if (best_me->motion_type==MC_16X8)
399             {
400                 /* 16 x 8 motion compensation in field picture */
401 
402                 /* upper half */
403                 pred(bwd_rec,best_me->field_sel[0][1],cur,currentfield,
404                     lx<<1,16,8,bx,by,
405                     best_me->MV[0][1][0],best_me->MV[0][1][1],addflag);
406 
407                 /* lower half */
408                 pred(bwd_rec,best_me->field_sel[1][1],cur,currentfield,
409                     lx<<1,16,8,bx,by+8,
410                     best_me->MV[1][1][0],best_me->MV[1][1][1],addflag);
411             }
412             else
413             {
414                 /* invalid motion_type in field picture */
415                 mjpeg_error_exit1("Internal: invalid motion_type");
416             }
417         }
418     }
419 }
420