1 /*
2  * Copyright (c) 1993-1994 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and the Network Research Group at
17  *      Lawrence Berkeley Laboratory.
18  * 4. Neither the name of the University nor of the Laboratory may be used
19  *    to endorse or promote products derived from this software without
20  *    specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 /************ Change log
36  *
37  * $Log$
38  * Revision 1.1  2010/02/24 02:19:22  shorne
39  * First commit of h323plus mirror
40  *
41  * Revision 1.3  2006/12/19 03:11:55  dereksmithies
42  * Add excellent fixes from Ben Weekes to suppress valgrind error messages.
43  * This will help memory management - many thanks.
44  *
45  * Revision 1.2  2006/07/31 09:09:22  csoutheren
46  * Checkin of validated codec used during development
47  *
48  * Revision 1.1.2.1  2006/04/06 01:17:17  csoutheren
49  * Initial version of H.261 video codec plugin for OPAL
50  *
51  * Revision 2.2  2005/08/31 13:16:02  rjongbloed
52  * Ported video fast update from OpenH323
53  *
54  * Revision 2.1  2003/03/15 23:43:00  robertj
55  * Update to OpenH323 v1.11.7
56  *
57  * Revision 1.6  2003/04/03 23:54:15  robertj
58  * Added fast update to H.261 codec, thanks Gustavo Garc�a Bernardo
59  *
60  * Revision 1.5  2000/09/22 02:40:13  dereks
61  * Tidied code for generating test images.
62  * Added mechanism to ensure the entire frame is sent on startup.
63  *
64  * Revision 1.4  2000/08/25 03:18:50  dereks
65  * Add change log facility (Thanks Robert for the info on implementation)
66  *
67  *
68  *
69  ********/
70 
71 
72 #include "vid_coder.h"
73 
SetSize(int _width,int _height)74 void Pre_Vid_Coder::SetSize(int _width,int _height)
75 {
76   if((_width!=width)||(_height!=height)) {
77      Free_Memory();
78      width    =_width;
79      height   =_height;
80      outw     =_width;
81      //   idle_high= 60;
82      idle_low = 2;
83      framesize=width*height;
84      allocref();
85      crinit();
86      rover=0;
87   }
88 }
89 
Pre_Vid_Coder()90 Pre_Vid_Coder::Pre_Vid_Coder():Encoder(NULL)
91 {
92  rover = 0;
93  frameCount = 0;
94 
95  ref  =NULL;
96  crvec=NULL;
97 
98  fastUpdCount = 0;
99 }
100 
~Pre_Vid_Coder()101 Pre_Vid_Coder::~Pre_Vid_Coder()
102 {
103   Free_Memory();
104 }
105 
Free_Memory()106 void Pre_Vid_Coder::Free_Memory()
107 {
108     if(crvec)
109 	delete [] crvec;
110     crvec= NULL;
111     if(ref)
112 	delete [] ref;
113     ref= NULL;
114 }
115 
crinit()116 void Pre_Vid_Coder::crinit()
117 {
118 	blkw = width >> 4;
119 	blkh = height >> 4;
120 	scan = 0;
121 	nblk = blkw * blkh;
122         if (crvec)
123            delete [] crvec;
124 	crvec = new u_char[nblk];
125 	for (int i = 0; i < nblk; ++i)
126 		crvec[i] = CR_MOTION|CR_SEND;
127 }
128 
129 /* must call after set_size_xxx */
allocref()130 void Pre_Vid_Coder::allocref()
131 {
132 	if(ref)
133            delete [] ref;
134 	ref = new u_char[framesize];
135 	memset((char*)ref, 0, framesize);
136 }
137 
138 /*
139  * define these for REPLENISH macro used below
140  */
141 #define ABS(v) if (v < 0) v = -v;
142 
143 #define DIFF4(in, frm, v) \
144 	v += (in)[0] - (frm)[0]; \
145 	v += (in)[1] - (frm)[1]; \
146 	v += (in)[2] - (frm)[2]; \
147 	v += (in)[3] - (frm)[3];
148 
149 #define DIFFLINE(in, frm, left, center, right) \
150 	DIFF4(in, frm, left); \
151 	DIFF4(in + 1*4, frm + 1*4, center); \
152 	DIFF4(in + 2*4, frm + 2*4, center); \
153 	DIFF4(in + 3*4, frm + 3*4, right); \
154 	ABS(right); \
155 	ABS(left); \
156 	ABS(center);
157 
suppress(const u_char * devbuf)158 void Pre_Vid_Coder::suppress(const u_char* devbuf)
159 {
160 	REPLENISH(devbuf, ref, outw, 1, 0, blkw, 0, blkh);
161 }
162 
save(u_char * lum,u_char * cache,int stride)163 inline void Pre_Vid_Coder::save(u_char* lum, u_char* cache, int stride)
164 {
165 	for (int i = 16; --i >= 0; ) {
166 		((u_int*)cache)[0] = ((u_int*)lum)[0];
167 		((u_int*)cache)[1] = ((u_int*)lum)[1];
168 		((u_int*)cache)[2] = ((u_int*)lum)[2];
169 		((u_int*)cache)[3] = ((u_int*)lum)[3];
170 		cache += stride;
171 		lum += stride;
172 	}
173 }
174 
ProcessFrame(VideoFrame * vf)175 void Pre_Vid_Coder::ProcessFrame(VideoFrame *vf)
176 {
177   if (!SameSize(vf))
178     SetSize(vf->width,vf->height);
179   frametime= vf->ts;  //Need frametime for deciding what blocks are old.
180   suppress(vf->frameptr);
181   saveblks(vf->frameptr);
182   vf->crvec= crvec;
183 }
184 
185 
186 /*
187  * Default save routine -- stuff new luma blocks into cache.
188  */
saveblks(u_char * lum)189 void Pre_Vid_Coder::saveblks(u_char* lum)
190 {
191 	u_char* crv = crvec;
192 	u_char* cache = ref;
193 	int stride = outw;
194 	stride = (stride << 4) - stride;
195 	for (int y = 0; y < blkh; y++) {
196 		for (int x = 0; x < blkw; x++) {
197 			if ((*crv++ & CR_SEND) != 0)
198 				save(lum, cache, outw);
199 			cache += 16;
200 			lum += 16;
201 		}
202 		lum += stride;
203 		cache += stride;
204 	}
205 }
206 
age_blocks()207 void Pre_Vid_Coder::age_blocks()
208 {
209   frameCount++;
210   fastUpdCount++;
211   if( (frameCount<3) || (fastUpdCount< 3) ) {
212 	for (int i = 0; i < nblk; ++i)
213 		crvec[i] = CR_MOTION|CR_SEND;
214         return;
215   }
216   /* The lines at the head of this routine are a hack.
217    * They ensure that for the first two frames of the current
218    * connection, all blocks in the frame are sent.
219    * Without these lines, netmeeting fills in the image over a
220    * series of frames. These lines ensure that netmeeting starts
221    * up with a full image.
222    */
223 	for (int i = 0; i < nblk; ++i) {
224 		int s = CR_STATE(crvec[i]);
225 		/*
226 		 * Age this block.
227 		 * Once we hit the age threshold, we
228 		 * set CR_SEND as a hint to send a
229 		 * higher-quality version of the block.
230 		 * After this the block will stop aging,
231 		 * until there is motion.  In the meantime,
232 		 * we might send it as background fill
233 		 * using the highest quality.
234 		 */
235 		if (s <= CR_AGETHRESH) {
236 			if (s == CR_AGETHRESH)
237 				s = CR_IDLE;
238 			else {  s++;
239 				if  (s == CR_AGETHRESH)
240 					s |= CR_SEND;
241 			}
242 			crvec[i] = s;
243 		} else if (s == CR_BG)
244 			/*
245 			 * reset the block to IDLE if it was sent
246 			 * as a BG block in the last frame.
247 			 */
248 			crvec[i] = CR_IDLE;
249 	}
250 	/*
251 	 * Now go through and look for some idle blocks to send
252 	 * as background fill.
253 	 */
254     //TODO: HORRIBLE, need better algorithm for determining n.
255 
256 	int n = (frametime >= 1) ? idle_high : idle_low;
257 
258 	while (n > 0) {
259 		int s = CR_STATE(crvec[rover]);
260 		if (s == CR_IDLE) {
261 			crvec[rover] = CR_SEND|CR_BG;
262 			--n;
263 		}
264                 rover++;
265 		if (rover >= nblk) {
266 			rover = 0;
267 			/* guarantee loop termination */
268 			break;
269 		}
270 	}
271 
272 	/*
273 	 * Bump the CR scan pointer.  This variable controls which
274 	 * scan line of a block we use to make the replenishment
275 	 * decision.  We skip 3 lines at a time to quickly precess
276 	 * over the block.  Since 3 and 8 are coprime, we will
277 	 * sweep out every line.
278 	 */
279 	scan = (scan + 3) & 7;
280 }
281 
282 
FastUpdatePicture()283 void Pre_Vid_Coder::FastUpdatePicture()  //ADDED
284 {
285   fastUpdCount = 0;
286 }
287 
288 
289