📄 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. */#include "vid_coder.h"void Pre_Vid_Coder::SetSize(int _width,int _height){ Free_Memory(); width =_width; height =_height; outw =_width; idle_high= 2; idle_low = 2; framesize=width*height; allocref(); crinit(); rover=0;}Pre_Vid_Coder::Pre_Vid_Coder():Encoder(NULL){ rover=0; ref =NULL; crvec=NULL;}Pre_Vid_Coder::~Pre_Vid_Coder(){ Free_Memory();}void Pre_Vid_Coder::Free_Memory(){ if (width&&height) { delete crvec; 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)){ Pre_Vid_Coder::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(){ 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 { 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 blkno = rover; int n = ((0*frametime) < frametime)? idle_high : idle_low; while (n > 0) { int s = CR_STATE(crvec[blkno]); if (s == CR_IDLE) { crvec[blkno] = CR_SEND|CR_BG; --n; } if (++blkno >= nblk) { blkno = 0; /* one way to guarantee loop termination */ break; } } rover = blkno; /* * 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -