📄 p64.cxx
字号:
qt_ = &quant_[mq << 8];
}
if (mt_ & MT_MVD) {
/*
* Read motion vector.
*/
int dh;
int dv;
HUFF_DECODE(bs_, ht_mvd_, nbb_, bb_, dh);
HUFF_DECODE(bs_, ht_mvd_, nbb_, bb_, dv);
/*
* Section 4.2.3.4
* The vector is differentially coded unless any of:
* - the current mba delta isn't 1
* - the current mba is 1, 12, or 23 (mba mod 11 = 1)
* - the last block didn't have motion vectors.
*
* This arithmetic is twos-complement restricted
* to 5 bits.
*/
if ((omt & MT_MVD) != 0 && v == 1 &&
mba_ != 0 && mba_ != 11 && mba_ != 22) {
dh += mvdh_;
dv += mvdv_;
}
mvdh_ = (dh << 27) >> 27;
mvdv_ = (dv << 27) >> 27;
}
/*
* Coded block pattern.
*/
if (mt_ & MT_CBP) {
HUFF_DECODE(bs_, ht_cbp_, nbb_, bb_, cbp);
if (cbp > 63) {
err("cbp invalid %x", cbp);
return (SYM_ILLEGAL);
}
} else
cbp = 0x3f;
return (1);
}
/*
* Handle the next block in the current macroblock.
* If tc is non-zero, then coefficients are present
* in the input stream and they are parsed. Otherwise,
* coefficients are not present, but we take action
* according to the type macroblock that we have.
*/
void P64Decoder::decode_block(u_int tc, u_int x, u_int y, u_int stride,
u_char* front, u_char* back, int sf)
{
short blk[64];
#ifdef INT_64
INT_64 mask;
#define MASK_VAL mask
#define MASK_REF &mask
#else
u_int mask[2];
#define MASK_VAL mask[0], mask[1]
#define MASK_REF mask
#endif
int nc=0;
if (tc != 0)
nc = parse_block(blk, MASK_REF);
int off = y * stride + x;
u_char* out = front + off;
if (mt_ & MT_INTRA) {
if (tc != 0) {
if (nc == 0)
dcfill((blk[0] + 4) >> 3, out, stride);
#ifdef notdef
else if (nc == 1) {
#ifdef INT_64
u_int dc = (mask & 1) ? (blk[0] + 4) >> 3 : 0;
for (int k = 1; k < 64; ++k) {
if (mask & ((INT_64)1 << k)) {
bv_rdct1(dc, blk, k,
out, stride);
return;
}
}
#else
u_int m0 = mask[0];
u_int m1 = mask[1];
u_int dc = (m0 & 1) ? (blk[0] + 4) >> 3 : 0;
for (int k = 1; k < 64; ++k) {
m0 >>= 1;
m0 |= m1 << 31;
m1 >>= 1;
if (m0 & 1) {
bv_rdct1(dc, blk, k,
out, stride);
return;
}
}
#endif
#endif
else
rdct(blk, MASK_VAL, out, stride, (u_char*)0);
} else {
u_char* in = back + off;
mvblka(in, out, stride);
}
return;
}
if ((mt_ & MT_MVD) == 0) {
u_char* in = back + off;
if (tc != 0) {
if (nc == 0) {
dcsum((blk[0] + 4) >> 3, in, out, stride);
} else
rdct(blk, MASK_VAL, out, stride, in);
} else
mvblka(in, out, stride);
return;
}
u_int sx = x + (mvdh_ / sf);
u_int sy = y + (mvdv_ / sf);
u_char* in = back + sy * stride + sx;
if (mt_ & MT_FILTER) {
filter(in, out, stride);
if (tc != 0) {
if (nc == 0)
dcsum2((blk[0] + 4) >> 3, out, out, stride);
else
rdct(blk, MASK_VAL, out, stride, out);
}
} else {
if (tc != 0) {
if (nc == 0)
dcsum2((blk[0] + 4) >> 3, in, out, stride);
else
rdct(blk, MASK_VAL, out, stride, in);
} else
mvblk(in, out, stride);
}
}
/*
* Decompress the next macroblock. Return 0 if the macroblock
* was present (with no errors). Return SYM_STARTCODE (-1),
* if there was no macroblock but instead the start of the
* next GOB or picture (in which case the start code has
* been consumed). Return SYM_ILLEGAL (-2) if there was an error.
*/
int P64Decoder::decode_mb()
{
u_int cbp;
register int v;
if ((v = parse_mb_hdr(cbp)) <= 0)
return (v);
/*
* Lookup the base coordinate for this MBA.
* Convert from a block to a pixel coord.
*/
register u_int x, y;
x = coord_[mba_];
y = (x & 0xff) << 3;
x >>= 8;
x <<= 3;
/* Update bounding box */
if (x < minx_)
minx_ = x;
if (x > maxx_)
maxx_ = x;
if (y < miny_)
miny_ = y;
if (y > maxy_)
maxy_ = y;
/*
* Decode the six blocks in the MB (4Y:1U:1V).
* (This code assumes MT_TCOEFF is 1.)
*/
register u_int tc = mt_ & MT_TCOEFF;
register u_int s = width_;
decode_block(tc & (cbp >> 5), x, y, s, front_, back_, 1);
decode_block(tc & (cbp >> 4), x + 8, y, s, front_, back_, 1);
decode_block(tc & (cbp >> 3), x, y + 8, s, front_, back_, 1);
decode_block(tc & (cbp >> 2), x + 8, y + 8, s, front_, back_, 1);
s >>= 1;
int off = size_;
decode_block(tc & (cbp >> 1), x >> 1, y >> 1, s,
front_ + off, back_ + off, 2);
off += size_ >> 2;
decode_block(tc & (cbp >> 0), x >> 1, y >> 1, s,
front_ + off, back_ + off, 2);
mbst_[mba_] = MBST_NEW;
/*
* If a marking table was attached, take note.
* This allows us to dither only the blocks that have changed,
* rather than the entire image on each frame.
*/
if (marks_) {
/* convert to 8x8 block offset */
off = (x >> 3) + (y >> 3) * (width_ >> 3);
int m = mark_;
marks_[off] = m;
marks_[off + 1] = m;
off += width_ >> 3;
marks_[off] = m;
marks_[off + 1] = m;
}
return (0);
}
/*
* Decode H.261 stream. Decoding can begin on either
* a GOB or macroblock header. All the macroblocks of
* a given frame can be decoded in any order, but chunks
* cannot be reordered across frame boundaries. Since data
* can be decoded in any order, this entry point can't tell
* when a frame is fully decoded (actually, we could count
* macroblocks but if there is loss, we would not know when
* to sync). Instead, the callee should sync the decoder
* by calling the sync() method after the entire frame
* has been decoded (modulo loss).
*
* This routine should not be called with more than
* one frame present since there is no callback mechanism
* for renderering frames (i.e., don't call this routine
* with a buffer that has a picture header that's not
* at the front).
*/
BOOL P64Decoder::decode(const unsigned char *hdrPtr, int buffLen,
BOOL lostPreviousPacket)
{
const u_char *bp;
int cc, sbit, ebit, gob;
h261hdr_t h261hdr;
// preventing accidential crashes
if (buffLen == 0)
return FALSE;
// get 32 bit H261 header
h261hdr = ntohl(*(u_int*)hdrPtr);
// decode values we need from the RTP H261 header
sbit = (h261hdr >> 29) & 0x07;
ebit = (h261hdr >> 26) & 0x07;
gob = (h261hdr >> 20) & 0xf;
// get remaining values from H261 header only when previous packet was lost
if (lostPreviousPacket) {
PTRACE(3, "H261\tLost or out of order packet, using values from H261 header");
mba_ = (h261hdr >> 15) & 0x1f;
int quant = (h261hdr >> 10) & 0x1f;
qt_ = &quant_[quant << 8];
mvdh_ = (h261hdr >> 5) & 0x1f; // sometimes NetMeeting sends bad values for these fields
mvdv_ = h261hdr & 0x1f; // use them only when the previous packet was lost
}
// adjust for length of H.261 header
bp = hdrPtr + sizeof(h261hdr_t);
ps_ = (u_short*)bp; // this does not seem to be used anywhere
cc = buffLen - sizeof(h261hdr_t);
/*
* If cc is odd, ignore 8 extra bits in last short.
*/
int odd = cc & 1;
ebit += odd << 3;
pebit_ = ebit;
es_ = (u_short*)(bp + ((cc - 1) &~ 1));
/*
* If input buffer not aligned, prime bit-buffer
* with 8 bits; otherwise, prime it with a 16.
*/
if ((long)bp & 1) {
bs_ = (u_short*)(bp + 1);
bb_ = *bp;
nbb_ = 8 - sbit;
} else {
bs_ = (u_short*)bp;
HUFFRQ(bs_, bb_);
nbb_ = 16 - sbit;
}
if (gob > 12) {
//count(STAT_BAD_HEADER);
return FALSE; // bad header value, what to do?
}
/*XXX don't rely on this*/
if (gob != 0) {
gob -= 1;
if (fmt_ == IT_QCIF) gob >>= 1;
}
while (bs_ < es_ || (bs_ == es_ && nbb_ > ebit)) {
mbst_ = &mb_state_[gob << 6];
coord_ = &base_[gob << 6];
ndblk_++;
int v = decode_mb();
if (v == 0)
continue;
if (v != SYM_STARTCODE) {
err("expected GOB startcode");
++bad_bits_;
return (FALSE);
}
gob = parse_gob_hdr(ebit);
if (gob < 0) {
/*XXX*/
++bad_bits_;
return (FALSE);
}
}
return (TRUE);
}
FullP64Decoder::FullP64Decoder()
{
init();
}
void FullP64Decoder::allocate()
{
delete fs_;
int n = size_ + (size_ >> 1);
fs_ = new u_char[2 * n];
/* initialize to gray */
memset(fs_, 0x80, 2 * n);
front_ = fs_;
back_ = front_ + n;
}
/*
* Swap the `front' and `back' frame buffers. While decoding a
* frame, the front buffer is the image being constructed while
* the back buffer is the reference image. Rather than copy
* the whole image each time, we just swap pointers here.
* We defer this copying until we find out that we're skipping
* over a macroblock, or even a whole gob. In this case, we
* go ahead and copy it, but take note in the mb_skip_ array.
* Next time we need to copy it, we skip it if the skip array
* says it's okay (e.g., there is no reason to copy a given block
* back and forth between buffers if it never changes). When we
* modify a macroblock, we clear out it's entry in mb_skip_.
*/
void FullP64Decoder::swap()
{
u_char* p = front_;
front_ = back_;
back_ = p;
}
/*
* Copy a macroblock from the saved frame (back buffer)
* to the current frame (front buffer). coord_ determines
* which GOB we're in.
*/
void FullP64Decoder::mbcopy(u_int mba)
{
u_int x, y;
x = coord_[mba];
y = (x & 0xff) << 3;
x >>= 8;
x <<= 3;
u_int stride = width_;
u_int off = y * stride + x;
u_char* in = back_ + off;
u_char* out = front_ + off;
mvblka(in, out, stride);
mvblka(in + 8, out + 8, stride);
in += stride << 3;
out += stride << 3;
mvblka(in, out, stride);
mvblka(in + 8, out + 8, stride);
x >>= 1;
y >>= 1;
stride >>= 1;
off = y * stride + x;
off += size_;
in = back_ + off;
out = front_ + off;
mvblka(in, out, stride);
off += size_ >> 2;
in = back_ + off;
out = front_ + off;
mvblka(in, out, stride);
}
void P64Decoder::sync()
{
bbx_ = minx_;
bby_ = miny_;
bbw_ = maxx_ - minx_ + 16;
bbh_ = maxy_ - miny_ + 16;
minx_ = width_;
miny_ = height_;
maxx_ = 0;
maxy_ = 0;
maxgob_ = 0;
}
void FullP64Decoder::sync()
{
for (int k = 0; k < ngob_; ++k) {
coord_ = &base_[k << 6];
u_char* mbst = &mb_state_[k << 6];
for (int mba = 0; mba < MBPERGOB; ++mba) {
int s = mbst[mba];
if (s == MBST_FRESH) {
mbcopy(mba);
mbst[mba] = MBST_OLD;
} else if (s == MBST_NEW)
mbst[mba] = MBST_FRESH;
}
}
swap();
P64Decoder::sync();
}
IntraP64Decoder::IntraP64Decoder()
{
init();
}
void IntraP64Decoder::allocate()
{
delete fs_;
int n = size_ + (size_ >> 1);
fs_ = new u_char[n];
/* initialize to gray */
memset(fs_, 0x80, n);
front_ = back_ = fs_;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -