1 /* motion.c, motion vector decoding                                         */
2 
3 /* Copyright (C) 1994, 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 
30 #include <stdio.h>
31 
32 #include "config.h"
33 #include "global.h"
34 
35 /* private prototypes */
36 static void calcMV _ANSI_ARGS_((int *pred, int r_size, int motion_code,
37   int motion_r, int full_pel_vector));
38 
motion_vectors(PMV,dmvector,mv_field_sel,s,mv_count,mv_format,h_r_size,v_r_size,dmv,mvscale)39 void motion_vectors(PMV,dmvector,
40   mv_field_sel,s,mv_count,mv_format,h_r_size,v_r_size,dmv,mvscale)
41 int PMV[2][2][2];
42 int dmvector[2];
43 int mv_field_sel[2][2];
44 int s, mv_count, mv_format, h_r_size, v_r_size, dmv, mvscale;
45 {
46   if (mv_count==1)
47   {
48     if (mv_format==MV_FIELD && !dmv)
49     {
50       mv_field_sel[1][s] = mv_field_sel[0][s] = getbits(1);
51 #ifdef TRACE
52       if (trace)
53       {
54         printf("motion_vertical_field_select[][%d] (%d): %d\n",s,
55           mv_field_sel[0][s],mv_field_sel[0][s]);
56       }
57 #endif
58     }
59 
60     motion_vector(PMV[0][s],dmvector,h_r_size,v_r_size,dmv,mvscale,0);
61 
62     /* update other motion vector predictors */
63     PMV[1][s][0] = PMV[0][s][0];
64     PMV[1][s][1] = PMV[0][s][1];
65   }
66   else
67   {
68     mv_field_sel[0][s] = getbits(1);
69 #ifdef TRACE
70     if (trace)
71     {
72       printf("motion_vertical_field_select[0][%d] (%d): %d\n",s,
73         mv_field_sel[0][s],mv_field_sel[0][s]);
74     }
75 #endif
76     motion_vector(PMV[0][s],dmvector,h_r_size,v_r_size,dmv,mvscale,0);
77 
78     mv_field_sel[1][s] = getbits(1);
79 #ifdef TRACE
80     if (trace)
81     {
82       printf("motion_vertical_field_select[1][%d] (%d): %d\n",s,
83         mv_field_sel[1][s],mv_field_sel[1][s]);
84     }
85 #endif
86     motion_vector(PMV[1][s],dmvector,h_r_size,v_r_size,dmv,mvscale,0);
87   }
88 }
89 
90 /* get and decode motion vector and differential motion vector */
motion_vector(PMV,dmvector,h_r_size,v_r_size,dmv,mvscale,full_pel_vector)91 void motion_vector(PMV,dmvector,
92   h_r_size,v_r_size,dmv,mvscale,full_pel_vector)
93 int *PMV;
94 int *dmvector;
95 int h_r_size;
96 int v_r_size;
97 int dmv; /* MPEG-2 only: get differential motion vectors */
98 int mvscale; /* MPEG-2 only: field vector in frame pic */
99 int full_pel_vector; /* MPEG-1 only */
100 {
101   int motion_code,motion_r;
102 
103   motion_code = getMV();
104   motion_r = (h_r_size!=0 && motion_code!=0) ? getbits(h_r_size) : 0;
105 
106 #ifdef TRACE
107   if (trace)
108   {
109     if (h_r_size!=0 && motion_code!=0)
110     {
111       printf("motion_residual (");
112       printbits(motion_r,h_r_size,h_r_size);
113       printf("): %d\n",motion_r);
114     }
115   }
116 #endif
117 
118   calcMV(&PMV[0],h_r_size,motion_code,motion_r,full_pel_vector);
119 
120   if (dmv)
121     dmvector[0] = getDMV();
122 
123   motion_code = getMV();
124   motion_r = (v_r_size!=0 && motion_code!=0) ? getbits(v_r_size) : 0;
125 
126 #ifdef TRACE
127   if (trace)
128   {
129     if (v_r_size!=0 && motion_code!=0)
130     {
131       printf("motion_residual (");
132       printbits(motion_r,v_r_size,v_r_size);
133       printf("): %d\n",motion_r);
134     }
135   }
136 #endif
137 
138   if (mvscale)
139     PMV[1] >>= 1; /* DIV 2 */
140 
141   calcMV(&PMV[1],v_r_size,motion_code,motion_r,full_pel_vector);
142 
143   if (mvscale)
144     PMV[1] <<= 1;
145 
146   if (dmv)
147     dmvector[1] = getDMV();
148 
149 #ifdef TRACE
150   if (trace)
151     printf("PMV = %d,%d\n",PMV[0],PMV[1]);
152 #endif
153 }
154 
155 /* calculate motion vector component */
calcMV(pred,r_size,motion_code,motion_r,full_pel_vector)156 static void calcMV(pred,r_size,motion_code,motion_r,full_pel_vector)
157 int *pred;
158 int r_size, motion_code, motion_r, full_pel_vector;
159 {
160   int lim, vec;
161 
162   lim = 16<<r_size;
163   vec = full_pel_vector ? (*pred >> 1) : (*pred);
164 
165   if (motion_code>0)
166   {
167     vec+= ((motion_code-1)<<r_size) + motion_r + 1;
168     if (vec>=lim)
169       vec-= lim + lim;
170   }
171   else if (motion_code<0)
172   {
173     vec-= ((-motion_code-1)<<r_size) + motion_r + 1;
174     if (vec<-lim)
175       vec+= lim + lim;
176   }
177   *pred = full_pel_vector ? (vec<<1) : vec;
178 }
179 
calc_DMV(DMV,dmvector,mvx,mvy)180 void calc_DMV(DMV,dmvector,mvx,mvy)
181 int DMV[][2];
182 int *dmvector; /* differential motion vector */
183 int mvx, mvy;  /* decoded mv components (always in field format) */
184 {
185   if (pict_struct==FRAME_PICTURE)
186   {
187     if (topfirst)
188     {
189       /* vector for prediction of top field from bottom field */
190       DMV[0][0] = ((mvx  +(mvx>0))>>1) + dmvector[0];
191       DMV[0][1] = ((mvy  +(mvy>0))>>1) + dmvector[1] - 1;
192 
193       /* vector for prediction of bottom field from top field */
194       DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
195       DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1;
196     }
197     else
198     {
199       /* vector for prediction of top field from bottom field */
200       DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0];
201       DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1;
202 
203       /* vector for prediction of bottom field from top field */
204       DMV[1][0] = ((mvx  +(mvx>0))>>1) + dmvector[0];
205       DMV[1][1] = ((mvy  +(mvy>0))>>1) + dmvector[1] + 1;
206     }
207   }
208   else
209   {
210     /* vector for prediction from field of opposite 'parity' */
211     DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0];
212     DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1];
213 
214     /* correct for vertical field shift */
215     if (pict_struct==TOP_FIELD)
216       DMV[0][1]--;
217     else
218       DMV[0][1]++;
219   }
220 }
221 
222