[cvs] / xvidcore / src / motion / vop_type_decision.c Repository:
ViewVC logotype

Diff of /xvidcore/src/motion/vop_type_decision.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1, Wed Sep 10 22:19:00 2003 UTC revision 1.1.2.1, Wed Sep 10 22:19:00 2003 UTC
# Line 0  Line 1 
1    /*****************************************************************************
2     *
3     *  XVID MPEG-4 VIDEO CODEC
4     *  - ME-based Frame Type Decision -
5     *
6     *  Copyright(C) 2002-2003 Radoslaw Czyz <xvid@syskin.cjb.net>
7     *
8     *  This program is free software ; you can redistribute it and/or modify
9     *  it under the terms of the GNU General Public License as published by
10     *  the Free Software Foundation ; either version 2 of the License, or
11     *  (at your option) any later version.
12     *
13     *  This program is distributed in the hope that it will be useful,
14     *  but WITHOUT ANY WARRANTY ; without even the implied warranty of
15     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     *  GNU General Public License for more details.
17     *
18     *  You should have received a copy of the GNU General Public License
19     *  along with this program ; if not, write to the Free Software
20     *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21     *
22     * $Id$
23     *
24     ****************************************************************************/
25    
26    #include "../encoder.h"
27    #include "../prediction/mbprediction.h"
28    #include "estimation.h"
29    #include "motion.h"
30    #include "sad.h"
31    #include "gmc.h"
32    #include "../utils/emms.h"
33    #include "motion_inlines.h"
34    
35    
36    #define INTRA_THRESH    2200
37    #define INTER_THRESH    40
38    #define INTRA_THRESH2   95
39    
40    static void
41    CheckCandidate32I(const int x, const int y, const SearchData * const data, const unsigned int Direction)
42    {
43            /* maximum speed */
44            int32_t sad;
45    
46            if ( (x > data->max_dx) || (x < data->min_dx)
47                    || (y > data->max_dy) || (y < data->min_dy) ) return;
48    
49            sad = sad32v_c(data->Cur, data->RefP[0] + x + y*((int)data->iEdgedWidth),
50                                            data->iEdgedWidth, data->temp);
51    
52            if (sad < *(data->iMinSAD)) {
53                    *(data->iMinSAD) = sad;
54                    data->currentMV[0].x = x; data->currentMV[0].y = y;
55                    *data->dir = Direction;
56            }
57            if (data->temp[0] < data->iMinSAD[1]) {
58                    data->iMinSAD[1] = data->temp[0]; data->currentMV[1].x = x; data->currentMV[1].y = y; }
59            if (data->temp[1] < data->iMinSAD[2]) {
60                    data->iMinSAD[2] = data->temp[1]; data->currentMV[2].x = x; data->currentMV[2].y = y; }
61            if (data->temp[2] < data->iMinSAD[3]) {
62                    data->iMinSAD[3] = data->temp[2]; data->currentMV[3].x = x; data->currentMV[3].y = y; }
63            if (data->temp[3] < data->iMinSAD[4]) {
64                    data->iMinSAD[4] = data->temp[3]; data->currentMV[4].x = x; data->currentMV[4].y = y; }
65    }
66    
67    static __inline void
68    MEanalyzeMB (   const uint8_t * const pRef,
69                                    const uint8_t * const pCur,
70                                    const int x,
71                                    const int y,
72                                    const MBParam * const pParam,
73                                    MACROBLOCK * const pMBs,
74                                    SearchData * const Data)
75    {
76    
77            int i;
78            VECTOR pmv[3];
79            MACROBLOCK * const pMB = &pMBs[x + y * pParam->mb_width];
80    
81            unsigned int simplicity = 0;
82    
83            for (i = 0; i < 5; i++) Data->iMinSAD[i] = MV_MAX_ERROR;
84    
85            get_range(&Data->min_dx, &Data->max_dx, &Data->min_dy, &Data->max_dy, x, y, 4,
86                            pParam->width, pParam->height, Data->iFcode - Data->qpel - 1, 0, 0);
87    
88            Data->Cur = pCur + (x + y * pParam->edged_width) * 16;
89            Data->RefP[0] = pRef + (x + y * pParam->edged_width) * 16;
90    
91            pmv[0].x = pMB->mvs[0].x;
92            pmv[0].y = pMB->mvs[0].y;
93    
94            CheckCandidate32I(pmv[0].x, pmv[0].y, Data, 0);
95    
96            if (*Data->iMinSAD > 200) {
97    
98                    pmv[1].x = pmv[1].y = 0;
99    
100                    /* median is only used as prediction. it doesn't have to be real */
101                    if (x == 1 && y == 1) Data->predMV.x = Data->predMV.y = 0;
102                    else
103                            if (x == 1) /* left macroblock does not have any vector now */
104                                    Data->predMV = (pMB - pParam->mb_width)->mvs[0]; /* top instead of median */
105                            else if (y == 1) /* top macroblock doesn't have it's vector */
106                                    Data->predMV = (pMB - 1)->mvs[0]; /* left instead of median */
107                            else Data->predMV = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0); /* else median */
108    
109                    pmv[2].x = Data->predMV.x;
110                    pmv[2].y = Data->predMV.y;
111    
112                    if (!vector_repeats(pmv, 1))
113                            CheckCandidate32I(pmv[1].x, pmv[1].y, Data, 1);
114                    if (!vector_repeats(pmv, 2))
115                            CheckCandidate32I(pmv[2].x, pmv[2].y, Data, 2);
116    
117                    if (*Data->iMinSAD > 500) { /* diamond only if needed */
118                            unsigned int mask = make_mask(pmv, 3, *Data->dir);
119                            xvid_me_DiamondSearch(Data->currentMV->x, Data->currentMV->y, Data, mask, CheckCandidate32I);
120                    } else simplicity++;
121    
122                    if (*Data->iMinSAD > 500) /* refinement from 2-pixel to 1-pixel */
123                            xvid_me_SubpelRefine(Data, CheckCandidate32I);
124                    else simplicity++;
125            } else simplicity++;
126    
127            for (i = 0; i < 4; i++) {
128                    MACROBLOCK * MB = &pMBs[x + (i&1) + (y+(i>>1)) * pParam->mb_width];
129                    MB->mvs[0] = MB->mvs[1] = MB->mvs[2] = MB->mvs[3] = Data->currentMV[i];
130                    MB->mode = MODE_INTER;
131                    /* if we skipped some search steps, we have to assume that SAD would be lower with them */
132                    MB->sad16 = Data->iMinSAD[i+1] - (simplicity<<7);
133            }
134    }
135    
136    int
137    MEanalysis(     const IMAGE * const pRef,
138                            const FRAMEINFO * const Current,
139                            const MBParam * const pParam,
140                            const int maxIntra, //maximum number if non-I frames
141                            const int intraCount, //number of non-I frames after last I frame; 0 if we force P/B frame
142                            const int bCount, // number of B frames in a row
143                            const int b_thresh)
144    {
145            uint32_t x, y, intra = 0;
146            int sSAD = 0;
147            MACROBLOCK * const pMBs = Current->mbs;
148            const IMAGE * const pCurrent = &Current->image;
149            int IntraThresh = INTRA_THRESH, InterThresh = INTER_THRESH + b_thresh;
150            int blocks = 0;
151            int complexity = 0;
152    
153            int32_t iMinSAD[5], temp[5];
154            uint32_t dir;
155            VECTOR currentMV[5];
156            SearchData Data;
157            Data.iEdgedWidth = pParam->edged_width;
158            Data.currentMV = currentMV;
159            Data.iMinSAD = iMinSAD;
160            Data.iFcode = Current->fcode;
161            Data.temp = temp;
162            Data.dir = &dir;
163            Data.qpel = (pParam->vol_flags & XVID_VOL_QUARTERPEL)? 1: 0;
164            Data.qpel_precision = 0;
165    
166            if (intraCount != 0) {
167                    if (intraCount < 10) // we're right after an I frame
168                            IntraThresh += 15* (intraCount - 10) * (intraCount - 10);
169                    else
170                            if ( 5*(maxIntra - intraCount) < maxIntra) // we're close to maximum. 2 sec when max is 10 sec
171                                    IntraThresh -= (IntraThresh * (maxIntra - 8*(maxIntra - intraCount)))/maxIntra;
172            }
173    
174            InterThresh -= 20 * bCount;
175            if (InterThresh < 10 + b_thresh) InterThresh = 10 + b_thresh;
176    
177            if (sadInit) (*sadInit) ();
178    
179            for (y = 1; y < pParam->mb_height-1; y += 2) {
180                    for (x = 1; x < pParam->mb_width-1; x += 2) {
181                            int i;
182                            blocks += 10;
183    
184                            if (bCount == 0) pMBs[x + y * pParam->mb_width].mvs[0] = zeroMV;
185                            else { //extrapolation of the vector found for last frame
186                                    pMBs[x + y * pParam->mb_width].mvs[0].x =
187                                            (pMBs[x + y * pParam->mb_width].mvs[0].x * (bCount+1) ) / bCount;
188                                    pMBs[x + y * pParam->mb_width].mvs[0].y =
189                                            (pMBs[x + y * pParam->mb_width].mvs[0].y * (bCount+1) ) / bCount;
190                            }
191    
192                            MEanalyzeMB(pRef->y, pCurrent->y, x, y, pParam, pMBs, &Data);
193    
194                            for (i = 0; i < 4; i++) {
195                                    int dev;
196                                    MACROBLOCK *pMB = &pMBs[x+(i&1) + (y+(i>>1)) * pParam->mb_width];
197                                    dev = dev16(pCurrent->y + (x + (i&1) + (y + (i>>1)) * pParam->edged_width) * 16,
198                                                                    pParam->edged_width);
199    
200                                    complexity += MAX(dev, 300);
201                                    if (dev + IntraThresh < pMB->sad16) {
202                                            pMB->mode = MODE_INTRA;
203                                            if (++intra > ((pParam->mb_height-2)*(pParam->mb_width-2))/2) return I_VOP;
204                                    }
205    
206                                    if (pMB->mvs[0].x == 0 && pMB->mvs[0].y == 0)
207                                            if (dev > 1000 && pMB->sad16 < 1000)
208                                                    sSAD += 1000;
209    
210                                    sSAD += (dev < 4000) ? pMB->sad16 : pMB->sad16/2; /* blocks with big contrast differences usually have large SAD - while they look very good in b-frames */
211                            }
212                    }
213            }
214            complexity >>= 7;
215    
216            sSAD /= complexity + 4*blocks;
217    
218            if (intraCount > 80 && sSAD > INTRA_THRESH2 ) return I_VOP;
219            if (sSAD > InterThresh ) return P_VOP;
220            emms();
221            return B_VOP;
222    }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.1.2.1

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4