⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p64.cxx

📁 开源的openh323的v1.18.0版,有1.19.0版无法编译过的朋友可以用这版
💻 CXX
📖 第 1 页 / 共 3 页
字号:
		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 + -