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