📄 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.1 2006/06/26 03:03:20 joegenbaclor
* I have decided to include the latest development realease of OPAL tagged Deimos Devel 1 (June 8 2006) as inegrated classes to opensipstack to avoid future version conflicts due to the fast pace in OPAL development. This move is also aimed to reduce the size of projects using OPAL componets such as the soon to be relased OpenSIPPhone.
*
* Revision 2.2 2005/08/31 13:16:02 rjongbloed
* Ported video fast update from OpenH323
*
* Revision 2.1 2003/03/15 23:43:00 robertj
* Update to OpenH323 v1.11.7
*
* 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 + -