📄 vid_coder.cxx
字号:
/*
* Copyright (c) 1993-1994 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and the Network Research Group at
* Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/************ Change log
*
* $Log: vid_coder.cxx,v $
* Revision 1.6 2003/04/03 23:54:15 robertj
* Added fast update to H.261 codec, thanks Gustavo Garc韆 Bernardo
*
* Revision 1.5 2000/09/22 02:40:13 dereks
* Tidied code for generating test images.
* Added mechanism to ensure the entire frame is sent on startup.
*
* Revision 1.4 2000/08/25 03:18:50 dereks
* Add change log facility (Thanks Robert for the info on implementation)
*
*
*
********/
#include "vid_coder.h"
void Pre_Vid_Coder::SetSize(int _width,int _height)
{
if((_width!=width)||(_height!=height)) {
Free_Memory();
width =_width;
height =_height;
outw =_width;
// idle_high= 60;
idle_low = 2;
framesize=width*height;
allocref();
crinit();
rover=0;
}
}
Pre_Vid_Coder::Pre_Vid_Coder():Encoder(NULL)
{
rover = 0;
frameCount = 0;
ref =NULL;
crvec=NULL;
fastUpdCount = 0;
}
Pre_Vid_Coder::~Pre_Vid_Coder()
{
Free_Memory();
}
void Pre_Vid_Coder::Free_Memory()
{
if(crvec)
delete crvec;
crvec= NULL;
if(ref)
delete ref;
ref= NULL;
}
void Pre_Vid_Coder::crinit()
{
blkw = width >> 4;
blkh = height >> 4;
scan = 0;
nblk = blkw * blkh;
if (crvec)
delete crvec;
crvec = new u_char[nblk];
for (int i = 0; i < nblk; ++i)
crvec[i] = CR_MOTION|CR_SEND;
}
/* must call after set_size_xxx */
void Pre_Vid_Coder::allocref()
{
if(ref)
delete ref;
ref = new u_char[framesize];
memset((char*)ref, 0, framesize);
}
/*
* define these for REPLENISH macro used below
*/
#define ABS(v) if (v < 0) v = -v;
#define DIFF4(in, frm, v) \
v += (in)[0] - (frm)[0]; \
v += (in)[1] - (frm)[1]; \
v += (in)[2] - (frm)[2]; \
v += (in)[3] - (frm)[3];
#define DIFFLINE(in, frm, left, center, right) \
DIFF4(in, frm, left); \
DIFF4(in + 1*4, frm + 1*4, center); \
DIFF4(in + 2*4, frm + 2*4, center); \
DIFF4(in + 3*4, frm + 3*4, right); \
ABS(right); \
ABS(left); \
ABS(center);
void Pre_Vid_Coder::suppress(const u_char* devbuf)
{
REPLENISH(devbuf, ref, outw, 1, 0, blkw, 0, blkh);
}
inline void Pre_Vid_Coder::save(u_char* lum, u_char* cache, int stride)
{
for (int i = 16; --i >= 0; ) {
((u_int*)cache)[0] = ((u_int*)lum)[0];
((u_int*)cache)[1] = ((u_int*)lum)[1];
((u_int*)cache)[2] = ((u_int*)lum)[2];
((u_int*)cache)[3] = ((u_int*)lum)[3];
cache += stride;
lum += stride;
}
}
void Pre_Vid_Coder::ProcessFrame(VideoFrame *vf)
{
if (!SameSize(vf))
SetSize(vf->width,vf->height);
frametime= vf->ts; //Need frametime for deciding what blocks are old.
suppress(vf->frameptr);
saveblks(vf->frameptr);
vf->crvec= crvec;
}
/*
* Default save routine -- stuff new luma blocks into cache.
*/
void Pre_Vid_Coder::saveblks(u_char* lum)
{
u_char* crv = crvec;
u_char* cache = ref;
int stride = outw;
stride = (stride << 4) - stride;
for (int y = 0; y < blkh; y++) {
for (int x = 0; x < blkw; x++) {
if ((*crv++ & CR_SEND) != 0)
save(lum, cache, outw);
cache += 16;
lum += 16;
}
lum += stride;
cache += stride;
}
}
void Pre_Vid_Coder::age_blocks()
{
frameCount++;
fastUpdCount++;
if( (frameCount<3) || (fastUpdCount< 3) ) {
for (int i = 0; i < nblk; ++i)
crvec[i] = CR_MOTION|CR_SEND;
return;
}
/* The lines at the head of this routine are a hack.
* They ensure that for the first two frames of the current
* connection, all blocks in the frame are sent.
* Without these lines, netmeeting fills in the image over a
* series of frames. These lines ensure that netmeeting starts
* up with a full image.
*/
for (int i = 0; i < nblk; ++i) {
int s = CR_STATE(crvec[i]);
/*
* Age this block.
* Once we hit the age threshold, we
* set CR_SEND as a hint to send a
* higher-quality version of the block.
* After this the block will stop aging,
* until there is motion. In the meantime,
* we might send it as background fill
* using the highest quality.
*/
if (s <= CR_AGETHRESH) {
if (s == CR_AGETHRESH)
s = CR_IDLE;
else { s++;
if (s == CR_AGETHRESH)
s |= CR_SEND;
}
crvec[i] = s;
} else if (s == CR_BG)
/*
* reset the block to IDLE if it was sent
* as a BG block in the last frame.
*/
crvec[i] = CR_IDLE;
}
/*
* Now go through and look for some idle blocks to send
* as background fill.
*/
//HORRIBLE, need better algorithm for determining n.
int n = ((0*frametime) < frametime)? idle_high : idle_low;
while (n > 0) {
int s = CR_STATE(crvec[rover]);
if (s == CR_IDLE) {
crvec[rover] = CR_SEND|CR_BG;
--n;
}
rover++;
if (rover >= nblk) {
rover = 0;
/* guarantee loop termination */
break;
}
}
/*
* Bump the CR scan pointer. This variable controls which
* scan line of a block we use to make the replenishment
* decision. We skip 3 lines at a time to quickly precess
* over the block. Since 3 and 8 are coprime, we will
* sweep out every line.
*/
scan = (scan + 3) & 7;
}
void Pre_Vid_Coder::FastUpdatePicture() //ADDED
{
fastUpdCount = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -