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

📄 encoder-h261.cxx

📁 开源的openh323的v1.18.0版,有1.19.0版无法编译过的朋友可以用这版
💻 CXX
📖 第 1 页 / 共 2 页
字号:
	u_int m = mba - mba_; // set macroblock address difference 
	mba_ = mba; // set last absolute macroblock address transmitted
	huffent* he = &hte_mba[m - 1]; // Huffman coded macroblock address
	/* MBA */
	PUT_BITS(he->val, he->nb, nbb_, bb_, bc_);
	if (q != mquant_) {
		/* MTYPE = INTRA + TC + MQUANT */
		PUT_BITS(1, 7, nbb_, bb_, bc_);
		PUT_BITS(q, 5, nbb_, bb_, bc_);
		mquant_ = q;
	} else {
		/* MTYPE = INTRA + TC (no quantizer) */
		PUT_BITS(1, 4, nbb_, bb_, bc_);
	}

	/* luminance */
	const char* lm = llm_[q];
	if (lm == 0) {
		lm = make_level_map(q, 1);
		llm_[q] = lm;
		clm_[q] = make_level_map(q, 2);
	}
	encode_blk(blk + 0, lm);
	encode_blk(blk + 64, lm);
	encode_blk(blk + 128, lm);
	encode_blk(blk + 192, lm);
	/* chominance */
	lm = clm_[q];
	encode_blk(blk + 256, lm);
	encode_blk(blk + 320, lm);
}


/*
 * H261DCTEncoder::encode_mb
 *	encode a macroblock given a set of input DCT coefs
 *	each coef is stored as a short
 */
void
H261DCTEncoder::encode_mb(u_int mba, const u_char* frm,
			  u_int loff, u_int coff, int how)
{
	short *lblk = (short *)frm + loff;
	short *ublk = (short *)frm + coff;
	short *vblk = (short *)frm + coff + 64;

	register u_int q;
	if (how == CR_MOTION)
		q = lq_;
	else if (how == CR_BG)
		q = hq_;
	else
		/* must be at age threshold */
		q = mq_;

	/*
	 * if the default quantizer is too small to handle the coef.
	 * dynamic range, spin through the blocks and see if any
	 * coef. would significantly overflow.
	 */
	if (q < 8) {
		register int cmin = 0, cmax = 0;
		register short* bp = lblk;
		register int i, j;

		// Y U and V blocks
		for (i = 6; --i >= 0; ) {
			++bp;	// ignore dc coef
			for (j = 63; --j >= 0; ) {
				register int v = *bp++;
				if (v < cmin)
					cmin = v;
				else if (v > cmax)
					cmax = v;
			}
		}

		if (cmax < -cmin)
			cmax = -cmin;
		cmax /= (q << 1);
		if (cmax >= 128) {
			/* need to re-quantize */
			register int s;

			for (s = 1; cmax >= (128 << s); ++s) {
			}
			q <<= s;

		}
	}

	u_int m = mba - mba_;
	mba_ = mba;
	huffent* he = &hte_mba[m - 1];
	/* MBA */
	PUT_BITS(he->val, he->nb, nbb_, bb_, bc_);
	if (q != mquant_) {
		/* MTYPE = INTRA + TC + MQUANT */
		PUT_BITS(1, 7, nbb_, bb_, bc_);
		PUT_BITS(q, 5, nbb_, bb_, bc_);
		mquant_ = q;
	} else {
		/* MTYPE = INTRA + TC (no quantizer) */
		PUT_BITS(1, 4, nbb_, bb_, bc_);
	}

	/* luminance */
	const char* lm = llm_[q];
	if (lm == 0) {
		/*
		 * the filter thresh is 0 since we assume the jpeg percept.
		 * quantizer already did the filtering.
		 */
		lm = make_level_map(q, 0);
		llm_[q] = lm;
		clm_[q] = make_level_map(q, 0);
	}
	encode_blk(lblk + 0, lm);
	encode_blk(lblk + 64, lm);
	encode_blk(lblk + 128, lm);
	encode_blk(lblk + 192, lm);
	/* chominance */
	lm = clm_[q];
	encode_blk(ublk, lm);
	encode_blk(vblk, lm);
}

int
H261Encoder::flush(Transmitter::pktbuf* pb, int nbit,
		       Transmitter::pktbuf* npb)
{
	/* flush bit buffer */
	STORE_BITS(bb_, bc_);

	int cc = (nbit + 7) >> 3;
	int ebit = (cc << 3) - nbit;

	/*XXX*/
	if (cc == 0 && npb != 0)
		return 0;

	pb->lenHdr = HDRSIZE;
	pb->lenBuf = cc;
	u_int* rh = (u_int*)pb->hdr;

	*rh = (*rh) | ebit << 26 | sbit_ << 29;

	if (npb != 0) {
		u_char* nbs = (u_char*)npb->buf->data;
		u_int bc = (bc_ - bs_) << 3;
		int tbit = bc + nbb_;
		int extra = ((tbit + 7) >> 3) - (nbit >> 3);
		if (extra > 0)
			memcpy(nbs, bs_ + (nbit >> 3), extra);
		bs_ = nbs;
		sbit_ = nbit & 7;
		tbit -= nbit &~ 7;
		bc = tbit &~ (NBIT - 1);
		nbb_ = tbit - bc;
		bc_ = bs_ + (bc >> 3);
		/*
		 * Prime the bit buffer.  Be careful to set bits that
		 * are not yet in use to 0, since output bits are later
		 * or'd into the buffer.
		 */
		if (nbb_ > 0) {
			u_int n = NBIT - nbb_;
			bb_ = (LOAD_BITS(bc_) >> n) << n;
		} else
			bb_ = 0;
	}
	tx_->StoreOnePacket(pb);
	return (cc + HDRSIZE);
}

int H261DCTEncoder::consume(const VideoFrame *vf)
{
	if (!SameSize(vf))
		SetSize(vf->width, vf->height);
	return(encode(vf, vf->crvec));
}

int H261PixelEncoder::consume(const VideoFrame *vf)
{
	if (!SameSize(vf))
		SetSize(vf->width, vf->height);
	return(encode(vf, vf->crvec));
}

//////NOTE: HDRSIZE is the size of the H261 hdr in the rtp packet.== 4
int H261Encoder::encode(const VideoFrame* vf, const BYTE *crvec) {
  Transmitter::pktbuf* pb = tx_->alloc();
	bs_ = (u_char*)pb->buf->data; // pointer to start of buffer
	bc_ = bs_; // pointer to destination in buffer
	u_int ec = (tx_->mtu() - HDRSIZE) << 3; // bits available in H261 packet
	bb_ = 0; // intermediate working space
	nbb_ = 0; // cumulative put bit count
	sbit_ = 0;
	/* RTP/H.261 header */
	u_int* rh = (u_int*)pb->hdr; // H.261 header (32 bits)
	*rh = (1 << 24) | (lq_ << 10); // set motion vector flag V to 1 & set QUANT

	/* PSC Picture Start Code */
	PUT_BITS(0x0001, 16, nbb_, bb_, bc_);
	/* GOB 0 -> picture header Finishes PSC */
	PUT_BITS(0, 4, nbb_, bb_, bc_);
	/* TR Temporal Reference (XXX should do this right) */
	PUT_BITS(0, 5, nbb_, bb_, bc_);

	/* PTYPE = CIF */
	int pt = cif_ ? 7 : 3;
	PUT_BITS(pt, 6, nbb_, bb_, bc_);

	/* PEI Picture Extra Information = none */
	PUT_BITS(0, 1, nbb_, bb_, bc_);

	int step = cif_ ? 1 : 2;
	int cc = 0;

	BYTE* frm = vf->frameptr;
  for (u_int gobIndex = 0; gobIndex < ngob_; gobIndex += step) { // fill in GOB layer
		u_int loff = loff_[gobIndex];
		u_int coff = coff_[gobIndex];
		u_int blkno = blkno_[gobIndex];
		u_int nbit = ((bc_ - bs_) << 3) + nbb_; // # of bits already in buffer

		/* GSC/GN */
		PUT_BITS(0x10 | (gobIndex + 1), 20, nbb_, bb_, bc_);
		/* GQUANT/GEI */
		mquant_ = lq_;
		PUT_BITS(mquant_ << 1, 6, nbb_, bb_, bc_);

		mba_ = 0;
		int line = 11;
		for (u_int mba = 1; mba <= 33; ++mba) {
			/*
			 * If the conditional replenishment algorithm
			 * has decided to send any of the blocks of
			 * this macroblock, code it.
			 */
			u_int s = crvec[blkno];

			if ((s & CR_SEND) != 0) {
				u_int mbpred = mba_;
				encode_mb(mba, frm, loff, coff, CR_STATE(s)); // encode MB
				u_int cbits = ((bc_ - bs_) << 3) + nbb_;
				if (cbits > ec) { // make new packet
					Transmitter::pktbuf* npb;
					npb = tx_->alloc();
					cc += flush(pb, nbit, npb);
					cbits -= nbit;
					pb = npb;
					/* RTP/H.261 header */
					u_int m = mbpred;
					u_int g;
					if (m != 0) {
						g = gobIndex + 1;
						m -= 1;
					} else
						g = 0;

					rh = (u_int*)pb->hdr;
					*rh =	1 << 24 |  //set motion vector flag.
 					      m << 15 |  //macroblock address predictor.
					      g << 20 |  //Group of blocks number.
             mquant_ << 10;//quantizer value.
                                        
				}
				nbit = cbits;
			}

			loff += loffsize_;
			coff += coffsize_;
			blkno += bloffsize_;
			if (--line <= 0) {
				line = 11;
				blkno += bstride_;
				loff += lstride_;
				coff += cstride_;
			}

		}
	}
	cc += flush(pb, ((bc_ - bs_) << 3) + nbb_, 0); 
	return (cc);
}

int H261PixelEncoder::PreIncEncodeSetup(const VideoFrame *vf)
{
  if (!SameSize(vf))
    SetSize(vf->width, vf->height);
  gVf = vf;
  gPicture = TRUE; //if TRUE, send picture layer header
  gNbytes = 0;  //number of bytes in previous packet
  gDbase = 0; //offset from gData where valid data starts
  nbb_ = 0; //# of valid bits in bb_
  bb_ = 0; //intermediate working space
  bc_ = gData; //where to put encoded bits
  gStep = cif_ ? 1 : 2; //Macro Block step size
  gGobMax = cif_ ? 12 : 5; //how many GOB per frame
  sbit_ = 0;
  gSendGOBhdr = TRUE; //must send GOB hdr before sending MB
  gGOBhdrNxt = TRUE; //will start out with GOB header
  //because gGOBhdrNxt == TRUE, no need to initialize the following 2 header variables:
  //gHdrGOBN; // next GOB number for last encoded MB
  //gHdrMBAP; // address of last macroblock encoded in previous packet 1..32
  //mba_= 0; // should not be necessary to initialize this
  gHdrQUANT = lq_; // QUANT in effect for next MB to be encoded
  gNxtMBA = 1; // address of next macroblock to be considered for encoding 1..33
  gNxtGOB = 1; // start encoding at GOB 1
  gDone = FALSE;
  return 1;
} 

void H261PixelEncoder::IncEncodeAndGetPacket(
  u_char * buffer,    // returns buffer of encoded data
  unsigned & length ) // returns actual length of encoded data buffer
{
  u_int previousBitCount = 0, currentBitCount;
  h261hdr_t h261hdr;

  if (gDone) {
    length = 0;
    return;
  }

  // TESTING
  if (!gGOBhdrNxt && ((33 <= gHdrMBAP) || (0 >= gHdrMBAP))) {
    cerr << __FILE__<< "(" << __LINE__ << ") " <<
      "illegal gHdrMBAP value when gGOBhdrNxt is FALSE = " << gHdrMBAP << endl;
    gHdrMBAP = 1;
  }
  //  unsigned t1 = sbit_ << 29;
  //  unsigned t2 = (gGOBhdrNxt?0:gHdrGOBN) << 20;
  //  unsigned t3 = (gGOBhdrNxt||(0==gHdrMBAP)?0:gHdrMBAP-1) << 15;
  //  unsigned t4 = (gGOBhdrNxt?0:gHdrQUANT) << 10;

  // set the H.261 header (32 bits) bits that we know now
  h261hdr =               1 << 24 | // V = 1, I = 0, HMVD = 0, VMVD = 0
                      sbit_ << 29 | // SBIT
    (gGOBhdrNxt?0:gHdrGOBN) << 20 | // GOBN
  (gGOBhdrNxt?0:gHdrMBAP-1) << 15 | // MBAP 
   (gGOBhdrNxt?0:gHdrQUANT) << 10;  // QUANT
                  // gHdrQUANT << 10;  // QUANT set the old & incorrect way

  // if any, move unsent bits encoded during previous packet encode
  unsigned usedBB_INTs;
  u_char* msrc;
  unsigned m1;
  if (sbit_) gNbytes--; // last byte of previous packet has bits needed for this packet
  usedBB_INTs = (gNbytes + gDbase)/sizeof(BB_INT);
  msrc = gData + usedBB_INTs*sizeof(BB_INT);
  gDbase = (gDbase + gNbytes) % sizeof(BB_INT);
  m1 = bc_ - msrc;
  if (m1) memcpy(gData, msrc, m1);
  bc_ = gData + m1; // set starting bc_ address
  
  // encode H.261 stream
  if (gPicture) { // only ever sent at start of 1st packet 
    /* PSC Picture Start Code */
    PUT_BITS(0x0001, 16, nbb_, bb_, bc_);
    /* GOB 0 -> picture header Finishes PSC */
    PUT_BITS(0, 4, nbb_, bb_, bc_);
    /* TR Temporal Reference (XXX should do this right) */
    PUT_BITS(0, 5, nbb_, bb_, bc_);
    /* PTYPE = CIF */
    int pt = cif_ ? 7 : 3;
    PUT_BITS(pt, 6, nbb_, bb_, bc_);
    /* PEI Picture Extra Information = none */
    PUT_BITS(0, 1, nbb_, bb_, bc_);
    gloff = loff_[0];
    gcoff = coff_[0];
    gblkno = blkno_[0];
    gline = 11;
    gPicture = FALSE;
  }
  unsigned bitLimit = 8*(RTP_MTU - sizeof(h261hdr));
  u_char* bbase = gData + gDbase;
  if (!(gNxtGOB > gGobMax)) {
    while ((currentBitCount = nbb_ + 8*(bc_ - bbase)) <= bitLimit) {
      // everything encoded up till now fits within the RTP_MTU buffer
      // test to see if the packet can be broken here
      if (gSendGOBhdr || (0 != mba_)){ // if packet can be broken,
        // record conditions that will be needed to construct the h261 header
        // for the next packet if the packet breaks here
        gHdrGOBN = gNxtGOB; // GOB number in effect for next MB to be encoded
        gHdrMBAP = mba_; // MBA of the last encoded MB & now in the buffer
        gHdrQUANT = mquant_; // QUANT in effect for next MB to be encoded
        gGOBhdrNxt = gSendGOBhdr; // is GOB header next?
        previousBitCount = currentBitCount; // encoded bits now in the buffer
      }
      if (gSendGOBhdr) { // need to send GOB header before can send MB ?
        /* GSC/GN */
        PUT_BITS(0x10 | gNxtGOB, 20, nbb_, bb_, bc_);
        /* GQUANT/GEI */
        mquant_ = lq_;
        PUT_BITS(mquant_ << 1, 6, nbb_, bb_, bc_);
        mba_= 0;
        gSendGOBhdr = FALSE;
      }
      /** If the conditional replenishment algorithm
      * has decided to send any of the blocks of
      * this macroblock, encode it.
      */
      u_int s = gVf->crvec[gblkno];
      if ((s & CR_SEND) != 0) {
        //H261PixelEncoder::encode_mb(u_int mba, // address of macroblock to encode
        //  const u_char* frm, // address of YUV pixels
        //  u_int loff, // Luminance offset from frm
        //  u_int coff, // Chrominance offset from frm
        //  int how)
        encode_mb(gNxtMBA, gVf->frameptr, gloff, gcoff, CR_STATE(s)); // encode MB
        mba_= gNxtMBA;
      }
      gNxtMBA++;
      if (gNxtMBA > 33) {
        gNxtGOB += gStep;
        if (gNxtGOB > gGobMax) {
          gDone = TRUE;
          break; // out of while(), done encoding frame
        }
        gNxtMBA = 1;
        gSendGOBhdr = TRUE; // must send GOB hdr before sending MB
        gloff = loff_[gNxtGOB-1];
        gcoff = coff_[gNxtGOB-1];
        gblkno = blkno_[gNxtGOB-1];
        gline = 11;
      }
      else {
        gloff += loffsize_;
        gcoff += coffsize_;
        gblkno += bloffsize_;
        if (--gline <= 0) {
          gline = 11;
          gblkno += bstride_;
          gloff += lstride_;
          gcoff += cstride_;
        }
      }
    }
  }
  else 
    gDone = TRUE;
  // have full packet now, finish & set up for next packet
  // break packet at end of previous MB unless this is end of frame
  // flush bits from bb_
  STORE_BITS(bb_, bc_); // necessary when gDbase != 0
  if (gDone) {
    unsigned totalBits = nbb_ + 8*(bc_ - bbase);
    if (totalBits <= bitLimit) { // would packet be too big?
      previousBitCount = totalBits;
    }
    else { // need another packet to finish frame
      gDone = FALSE;
    }
  }
  gNbytes = previousBitCount / 8;
  sbit_ = previousBitCount % 8; // SBIT for next packet = good bits for this packet
  if (sbit_) gNbytes++; // include last bits for this frame
  
  // set the H.261 header (32 bits) bits that we know now
  h261hdr |= ((8 - sbit_) & 7) << 26; //EBIT = 8 - SBIT for next packet
  h261hdr = htonl(h261hdr);
  *(h261hdr_t*)buffer = h261hdr;
  memcpy(buffer+sizeof(h261hdr), gData+gDbase, gNbytes);
  length = gNbytes+sizeof(h261hdr);

  if (RTP_MTU < length) { // test for too large packet (I haven't seen one yet)
    cerr << __FILE__<< "(" << __LINE__ << ") " <<
      "packet size of " << length << " > RTP_MTU(" << RTP_MTU << ")" << endl;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -