📄 p64.cxx
字号:
/*
* 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.
*/
/************ Change log
*
* $Log: p64.cxx,v $
* Revision 1.15 2005/12/04 22:33:35 csoutheren
* Removed warning
*
* Revision 1.14 2005/11/25 00:10:23 csoutheren
* Applied patch #1303543 from Hannes Friederich
* Added guard to weird conditions in H261 codec
*
* Revision 1.13 2005/02/25 01:21:12 dominance
* fixed building on amd64 with gcc-4.0 according to
* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=287864
*
* Thanks fly to Andreas Jochens <aj@andaco.de>.
*
* Revision 1.12 2003/03/14 07:25:55 robertj
* Removed $header keyword so is not different on alternate repositories
*
* Revision 1.11 2002/10/10 05:40:29 robertj
* VxWorks port, thanks Martijn Roest
*
* Revision 1.10 2002/04/26 04:57:41 dereks
* Add Walter Whitlocks fixes, based on Victor Ivashim's suggestions to
* improve the quality with Netmeeting. Thanks guys!!!!
*
* Revision 1.9 2001/05/10 05:25:44 robertj
* Removed need for VIC code to use ptlib.
*
* Revision 1.8 2001/05/08 14:53:29 yurik
* Fixed misshap with removing non Wince def!
*
* Revision 1.7 2001/05/08 05:26:24 yurik
* No ifdef _WIN32_WCE anymore - 3+ version of SDK allows it
*
* Revision 1.6 2001/01/30 06:39:44 yurik
* Modification submitted by Dave Cassel, dcassel@cyberfone.com.
*
* Revision 1.5 2000/12/19 22:22:34 dereks
* Remove connection to grabber-OS.cxx files. grabber-OS.cxx files no longer used.
* Video data is now read from a video channel, using the pwlib classes.
*
* Revision 1.4 2000/08/25 03:18:50 dereks
* Add change log facility (Thanks Robert for the info on implementation)
*
*
*
********/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "config.h"
#if defined(WIN32) || defined(_WIN32_WCE)
#include <winsock.h>
#else
#include <sys/file.h>
#endif
#include <sys/stat.h>
#include "p64.h"
#include "p64-huff.h"
#include "dct.h"
#include "bsd-endian.h"
#define SPLICE(v, p, n) (v) |= (p) << SHIFT(n)
void 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
}
P64Decoder::P64Decoder()
: fs_(0), front_(0), back_(0),
ngob_(0), maxgob_(0), ndblk_(0),
gobquant_(0), mt_(0), gob_(0),
mba_(0), mvdh_(0), mvdv_(0),
marks_(0), mark_(0),
bad_psc_(0), bad_bits_(0), bad_GOBno_(0), bad_fmt_(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_64
int P64Decoder::parse_block(short* blk, INT_64* mask)
#else
int 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;
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -