📄 p64.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: p64.cpp,v 1.1.8.1 2004/07/09 01:50:08 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** *//* * Copyright (c) 1993-1995 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 Network Research * Group at Lawrence Berkeley National 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. *//* * This code is derived from the P64 software implementation by the * Stanford PVRG group: * * Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. * PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research * Group. If you use this software, you agree to the following: This * program package is purely experimental, and is licensed "as is". * Permission is granted to use, modify, and distribute this program * without charge for any purpose, provided this license/ disclaimer * notice appears in the copies. No warranty or maintenance is given, * either expressed or implied. In no event shall the author(s) be * liable to you or a third party for any special, incidental, * consequential, or other damages, arising out of the use or inability * to use the program for any purpose (or the loss of data), even if we * have been advised of such possibilities. Any public reference or * advertisement of this source code should refer to it as the Portable * Video Research Group (PVRG) code, and not by any author(s) (or * Stanford University) name. */#ifndef lintstatic char rcsid[] = "@(#) $Header: /cvsroot/datatype/h261/renderer/p64.cpp,v 1.1.8.1 2004/07/09 01:50:08 hubbe Exp $ (LBL)";#endif#include <stdarg.h>#include <stdio.h>#include <string.h>#include "hxtypes.h"#include "hxmarsh.h"#ifndef _MACINTOSH #ifdef WIN32 # include <winsock.h> #else # include <sys/param.h> # include <sys/file.h> #endif // WIN32# include <sys/stat.h>#else# include "config.h"#endif // _MACINTOSH#include "p64.h"#include "p64-huff.h"#include "dct.h"#include "bsd-endian.h"#include "hxheap.h"#ifdef _DEBUG #undef HX_THIS_FILE static char HX_THIS_FILE[] = __FILE__;#endifvoid P64Decoder::err(const char* msg ...) const{#ifdef DEVELOPMENT_VERSION va_list ap; va_start(ap, msg); vfprintf(stderr, msg, ap); fprintf(stderr, " @g%d m%d %d/%d of %d/%d: %04x %04x %04x %04x|%04x\n", gob_, mba_, (int)((u_char*)bs_ - (u_char*)ps_), nbb_, (int)((u_char*)es_ - (u_char*)ps_), pebit_, bs_[-4], bs_[-3], bs_[-2], bs_[-1], bs_[0]);#endif#ifdef WIN32#ifdef _DEBUG char sz[ 512 ]; /* Flawfinder: ignore */ va_list ap; va_start(ap, msg); vsprintf( sz, msg, ap); /* Flawfinder: ignore */ OutputDebugString(sz); sprintf(sz, " @g%d m%d %d/%d of %d/%d: %04x %04x %04x %04x|%04x\n", /* Flawfinder: ignore */ gob_, mba_, (int)((u_char*)bs_ - (u_char*)ps_), nbb_, (int)((u_char*)es_ - (u_char*)ps_), pebit_, bs_[-4], bs_[-3], bs_[-2], bs_[-1], bs_[0]); OutputDebugString(sz);#endif#endif}P64Decoder::P64Decoder() : mt_(0), mvdh_(0), mvdv_(0), mba_(0), ngob_(0), ndblk_(0), gobquant_(0), gob_(0), maxgob_(0), bad_psc_(0), bad_bits_(0), bad_GOBno_(0), bad_fmt_(0), fs_(0), front_(0), back_(0), marks_(0), mark_(0){ fmt_ = IT_CIF;/*XXX*/ inithuff(); initquant();}P64Decoder::~P64Decoder(){ delete fs_;}void P64Decoder::init(){ if (fmt_ == IT_CIF) { ngob_ = 12; width_ = 352; height_ = 288; } else { ngob_ = 3; width_ = 176; height_ = 144; } size_ = width_ * height_; memset(mb_state_, MBST_OLD, sizeof(mb_state_)); for (u_int gob = 0; gob < 12; ++gob) { u_short* p = &base_[gob << 6]; for (int mba = 0; mba < MBPERGOB; ++mba) { u_int x = 2 * (mba % 11); u_int y; if (fmt_ == IT_CIF) { y = 2 * (3 * (gob >> 1) + mba / 11); if (gob & 1) x += 22; } else y = 2 * (3 * gob + mba / 11); p[mba] = (x << 8) | y; } } minx_ = width_; miny_ = height_; maxx_ = 0; maxy_ = 0; allocate();}#if BYTE_ORDER == LITTLE_ENDIAN#define HUFFRQ(bs, bb) \ { \ register int t = *bs++; \ bb <<= 16; \ bb |= (t & 0xff) << 8; \ bb |= t >> 8; \}#else#define HUFFRQ(bs, bb) \ { \ bb <<= 16; \ bb |= *bs++; \}#endif#define MASK(s) ((1 << (s)) - 1)#define HUFF_DECODE(bs, ht, nbb, bb, result) { \ register int s__, v__; \ \ if (nbb < 16) { \ HUFFRQ(bs, bb); \ nbb += 16; \ } \ s__ = ht.maxlen; \ v__ = (bb >> (nbb - s__)) & MASK(s__); \ s__ = (ht.prefix)[v__]; \ nbb -= (s__ & 0x1f); \ result = s__ >> 5; \ }#define GET_BITS(bs, n, nbb, bb, result) \{ \ nbb -= n; \ if (nbb < 0) { \ HUFFRQ(bs, bb); \ nbb += 16; \ } \ (result) = ((bb >> nbb) & MASK(n)); \}#define SKIP_BITS(bs, n, nbb, bb) \{ \ nbb -= n; \ if (nbb < 0) { \ HUFFRQ(bs, bb); \ nbb += 16; \ } \}/* * Set up the huffman tables. */void P64Decoder::inithuff(){ ht_mtype_.prefix = htd_mtype; ht_mtype_.maxlen = htd_mtype_width; ht_mba_.prefix = htd_mba; ht_mba_.maxlen = htd_mba_width; ht_mvd_.prefix = htd_dvm; ht_mvd_.maxlen = htd_dvm_width; ht_cbp_.prefix = htd_cbp; ht_cbp_.maxlen = htd_cbp_width; ht_tcoeff_.prefix = htd_tcoeff; ht_tcoeff_.maxlen = htd_tcoeff_width;}int P64Decoder::quantize(int v, int q){ if (v > 0) return (((v << 1) + 1) * q) - (~q & 1); else return (((v << 1) - 1) * q) + (~q & 1);}/* * Build quantization lookup table. * One for each possible MQUANT paramenter. */void P64Decoder::initquant(){ for (int mq = 0; mq < 32; ++mq) { short* qt = &quant_[mq << 8]; for (int v = 0; v < 256; ++v) { int s = (v << 24) >> 24; qt[v] = quantize(s, mq); } }}/* * Decode the next block of transform coefficients * from the input stream. * Return number of non-zero ac coefficients. */#ifdef INT_64int P64Decoder::parse_block(short* blk, INT_64* mask)#elseint P64Decoder::parse_block(short* blk, u_int* mask)#endif{#ifdef INT_64 INT_64 m0 = 0;#else u_int m1 = 0, m0 = 0;#endif /* * Cache bit buffer in registers. */ register int nbb = nbb_; register int bb = bb_; register short* qt = qt_; int k; if ((mt_ & MT_CBP) == 0) { int v; GET_BITS(bs_, 8, nbb, bb, v); if (v == 255) v = 128; if (mt_ & MT_INTRA) v <<= 3; else v = qt[v]; blk[0] = v; k = 1; m0 |= 1; } else if ((bb >> (nbb - 1)) & 1) { /* * In CBP blocks, the first block present must be * non-empty (otherwise it's mask bit wouldn't * be set), so the first code cannot be an EOB. * CCITT optimizes this case by using a huffman * table equivalent to ht_tcoeff_ but without EOB, * in which 1 is coded as "1" instead of "11". * We grab two bits, the first bit is the code * and the second is the sign. */ int v; GET_BITS(bs_, 2, nbb, bb, v); /*XXX quantize?*/ blk[0] = qt[(v & 1) ? 0xff : 1]; k = 1; m0 |= 1; } else { k = 0;#ifndef INT_64 blk[0] = 0;/*XXX need this because the way we set bits below*/#endif } int nc = 0; for (;;) { int r, v; // this is a hack to prevent player crash. if (nbb < 16 && bs_ > es_) { register int s__, v__; bb <<= 16; nbb += 16; s__ = ht_tcoeff_.maxlen; v__ = (bb >> (nbb - s__)) & MASK(s__); s__ = (ht_tcoeff_.prefix)[v__]; nbb -= (s__ & 0x1f); r = s__ >> 5; } else { HUFF_DECODE(bs_, ht_tcoeff_, nbb, bb, r); } if (r <= 0) { /* SYM_EOB, SYM_ILLEGAL, or SYM_ESCAPE */ if (r == SYM_ESCAPE) { GET_BITS(bs_, 14, nbb, bb, r); v = r & 0xff; r >>= 8; } else { if (r == SYM_ILLEGAL) { bb_ = bb; nbb_ = nbb; err("illegal symbol in block"); } /* EOB */ break; } } else { v = (r << 22) >> 27; r = r & 0x1f; } k += r; if (k >= 64) { bb_ = bb; nbb_ = nbb; err("bad run length %d (r %d, v %d)", k, r, v); break; } r = COLZAG[k++]; blk[r] = qt[v & 0xff]; ++nc;#ifdef INT_64 m0 |= (INT_64)1 << r;#else if (r < 32) m0 |= 1 << r; else m1 |= 1 << (r - 32);#endif } /* * Done reading input. Update bit buffer. */ bb_ = bb; nbb_ = nbb; *mask = m0;#ifndef INT_64 mask[1] = m1;#endif return (nc);}/* * Mix in a motion-compensated, filtered block. Note that * the input block may be misaligned so we cannot try fancy, * word-at-a-time accesses without being careful. The output * block is, of course, aligned. * * The 2-D loop filter is separable into 1-D FIR (0.25 0.5 0.25) * horizontal and vertical passes. At the block edge, the filter * taps are (0 1 0). Full arithmetic precision must be maintained, * until the output stage, where values are rounded (up). * * The code below tries to be efficient by caching the input * rows in registers, and running the filter on 3x3 chunks. * Multiple columns can be computed in parallel by using * two 16-bit adds in a 32-bit register, or four 16-bit adds * in a 64-bit register. */void P64Decoder::filter(u_char* in, u_char* out, u_int stride){ /* Corner pixel has filter coef 1 */ u_int s = in[0]; u_int o = 0; SPLICE(o, s, 24); u_int r00 = s << 24 | in[1] << 16 | in[2] << 8 | in[3]; u_int r01 = in[4] << 24 | in[5] << 16 | in[6] << 8 | in[7]; in += stride; /* * First row. */ s += (r00 >> 15) & 0x1fe; s += (r00 >> 8) & 0xff; /* round */ s += 2; s >>= 2; SPLICE(o, s, 16); s = (r00 >> 16) & 0xff; s += (r00 >> 7) & 0x1fe; s += r00 & 0xff; /* round */ s += 2; s >>= 2; SPLICE(o, s, 8); s = (r00 >> 8) & 0xff; s += (r00 & 0xff) << 1; s += r01 >> 24; /* round */ s += 2; s >>= 2; SPLICE(o, s, 0); *(u_int*)out = o; s = r00 & 0xff; s += (r01 >> 23) & 0x1fe; s += (r01 >> 16) & 0xff; /* round */ s += 2; s >>= 2; o = 0; SPLICE(o, s, 24); s = r01 >> 24; s += (r01 >> 15) & 0x1fe; s += (r01 >> 8) & 0xff; /* round */ s += 2; s >>= 2; SPLICE(o, s, 16); s = (r01 >> 16) & 0xff; s += (r01 >> 7) & 0x1fe; s += r01 & 0xff; /* round */ s += 2; s >>= 2; SPLICE(o, s, 8); /* corner has filter coef 1 */ s = r01 & 0xff; SPLICE(o, s, 0); *(u_int*)(out + 4) = o; out += stride; /* load next rows into cache */ u_int r10 = in[0] << 24 | in[1] << 16 | in[2] << 8 | in[3]; u_int r11 = in[4] << 24 | in[5] << 16 | in[6] << 8 | in[7]; in += stride; u_int r20, r21; u_int mask = 0xff00ff; for (int k = 6; --k >= 0; ) { /* load next row */ r20 = in[0] << 24 | in[1] << 16 | in[2] << 8 | in[3]; r21 = in[4] << 24 | in[5] << 16 | in[6] << 8 | in[7]; in += stride; /* columns 0,2 */ u_int v = (r00 >> 8) & mask; v += ((r10 >> 8) & mask) << 1; v += (r20 >> 8) & mask; /* first pixel */ s = v >> 16; /* round */ s += 2; s >>= 2; o = 0; SPLICE(o, s, 24); /* columns 1,3 */ u_int w = r00 & mask; w += (r10 & mask) << 1; w += r20 & mask; /* row */ s = v >> 16; s += v & 0xffff; s += w >> (16-1); /* round */ s += 8; s >>= 4; SPLICE(o, s, 16); s = w >> 16; s += w & 0xffff; s += (v & 0xffff) << 1; /* round */ s += 8; s >>= 4; SPLICE(o, s, 8); /* start next row */ s = v & 0xffff; s += (w & 0xffff) << 1; /* but first do columns 4,6 */ v = (r01 >> 8) & mask; v += ((r11 >> 8) & mask) << 1; v += (r21 >> 8) & mask; /* finish row */ s += v >> 16; /* round */ s += 8; s >>= 4; SPLICE(o, s, 0); *(u_int*)out = o; /* start next row */ s = w & 0xffff; s += (v >> 16) << 1; /* but first do columns 5,7 */ w = r01 & mask; w += (r11 & mask) << 1; w += r21 & mask; /* finish row */ s += w >> 16; /* round */ s += 8; s >>= 4; o = 0; SPLICE(o, s, 24); s = v >> 16; s += v & 0xffff; s += w >> (16-1); /* round */ s += 8; s >>= 4; SPLICE(o, s, 16); s = w >> 16; s += w & 0xffff; s += (v & 0xffff) << 1; /* round */ s += 8; s >>= 4; SPLICE(o, s, 8); s = w & 0xffff; /* round */ s += 2; s >>= 2; SPLICE(o, s, 0); *(u_int*)(out + 4) = o; out += stride; /* roll lines up cache */ r00 = r10; r01 = r11; r10 = r20; r11 = r21; } /* * last row */ s = r20 >> 24; o = 0; SPLICE(o, s, 24); s += (r20 >> 15) & 0x1fe; s += (r20 >> 8) & 0xff; /* round */ s += 2; s >>= 2; SPLICE(o, s, 16); s = (r20 >> 16) & 0xff; s += (r20 >> 7) & 0x1fe; s += r20 & 0xff; /* round */ s += 2; s >>= 2; SPLICE(o, s, 8); s = (r20 >> 8) & 0xff; s += (r20 & 0xff) << 1; s += r21 >> 24; /* round */ s += 2; s >>= 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -