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

📄 encoder-h261.cpp

📁 MPEG4音频视频压缩编码(含G.711/ACC/H.261等)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	uint32_t h = pb->h261_rtp_hdr | (ebit << 26) | (sbit_ << 29);	pb->h261_rtp_hdr = htonl(h);	if (pNewBuffer != 0) {		u_char* new_buffer_start = pNewBuffer->data;		// bc is bit count including last macroblock that we're not		// sending (in bytes)		u_int bc = (m_pBufferCurrent - m_encoded_frame_buffer) << 3;		// tbit is bit count including last macroblock, including bit		// that we STORE_BITS above		int tbit = bc + m_bitsInCache;		// extra is # of bits in buffer that we want to save (pretty much			// the whole macro block		int extra = ((tbit + 7) >> 3) - (last_mb_start_bits >> 3);		if (extra > 0)			memcpy(new_buffer_start, m_encoded_frame_buffer + (last_mb_start_bits >> 3), extra);		m_encoded_frame_buffer = new_buffer_start;		sbit_ = last_mb_start_bits & 7;		tbit -= last_mb_start_bits &~ 7;		bc = tbit &~ (NBIT - 1);		m_bitsInCache = tbit - bc;		m_pBufferCurrent = m_encoded_frame_buffer + (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 (m_bitsInCache > 0) {			u_int n = NBIT - m_bitsInCache;			m_bitCache = (LOAD_BITS(m_pBufferCurrent) >> n) << n;		} else			m_bitCache = 0;	}#if 0	target_->recv(pb);#else	pb->next = pNewBuffer;#endif	return (cc + HLEN);}static pktbuf_t *alloc_pktbuf(uint32_t mtu){  pktbuf_t *ret = MALLOC_STRUCTURE(pktbuf_t);  ret->data = (uint8_t *)malloc(mtu * 2);  ret->next = NULL;  ret->len = 0;  return ret;}void free_pktbuf (pktbuf_t *pkt){  free(pkt->data);  free(pkt);}void free_pktbuf_list(pktbuf_t *p){  pktbuf_t *q;  while (p != NULL) {    q = p->next;    free_pktbuf(p);    p = q;  }}media_free_f CH261Encoder::GetMediaFreeFunction(void){  return (media_free_f)free_pktbuf_list;}void CH261Encoder::encode(const uint8_t* vf, const u_int8_t *crvec){  pktbuf_t* pb = alloc_pktbuf(mtu_);  if (m_head != NULL) {    free_pktbuf_list(m_head);  }  m_head = pb;	m_encoded_frame_buffer = pb->data;	m_pBufferCurrent = m_encoded_frame_buffer;	u_int max_bits_in_buffer = (mtu_ - HLEN) << 3;	m_bitCache = 0;	m_bitsInCache = 0;	sbit_ = 0;	/* RTP/H.261 header */	pb->h261_rtp_hdr = (1 << 25) | (lq_ << 10);	/* PSC */	PUT_BITS(0x0001, 16, m_bitsInCache, m_bitCache, m_pBufferCurrent);	/* GOB 0 -> picture header */	PUT_BITS(0, 4, m_bitsInCache, m_bitCache, m_pBufferCurrent);	/* TR (FIXME should do this right) */	PUT_BITS(0, 5, m_bitsInCache, m_bitCache, m_pBufferCurrent);	/* PTYPE = CIF */	int pt = cif_ ? 6 : 2;	PUT_BITS(pt, 6, m_bitsInCache, m_bitCache, m_pBufferCurrent);	/* PEI */	PUT_BITS(0, 1, m_bitsInCache, m_bitCache, m_pBufferCurrent);	int step = cif_ ? 1 : 2;	const u_int8_t* frm = vf;	for (u_int gob = 0; gob < ngob_; gob += step) {		u_int loff = loff_[gob];		u_int coff = coff_[gob];		u_int blkno = blkno_[gob];		u_int last_mb_start_bits = ((m_pBufferCurrent - m_encoded_frame_buffer) << 3) + m_bitsInCache;		/* GSC/GN */		PUT_BITS(0x10 | (gob + 1), 20, m_bitsInCache, m_bitCache, m_pBufferCurrent);		/* GQUANT/GEI */		mquant_ = lq_;		PUT_BITS(mquant_ << 1, 6, m_bitsInCache, m_bitCache, m_pBufferCurrent);		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_QUALITY(s));				u_int cbits = ((m_pBufferCurrent - m_encoded_frame_buffer) << 3) + m_bitsInCache;				if (cbits > max_bits_in_buffer) {					pktbuf_t* npb;					npb = alloc_pktbuf(mtu_);					m_encodedBytes += 					  flush(pb, last_mb_start_bits, npb);					cbits -= last_mb_start_bits;					pb = npb;					/* RTP/H.261 header */					u_int m = mbpred;					u_int g;					if (m != 0) {						g = gob + 1;						m -= 1;					} else						g = 0;					pb->h261_rtp_hdr = 						1 << 25 |						m << 15 |						g << 20 |						mquant_ << 10;				}				last_mb_start_bits = cbits;			}			loff += loffsize_;			coff += coffsize_;			blkno += bloffsize_;			if (--line <= 0) {				line = 11;				blkno += bstride_;				loff += lstride_;				coff += cstride_;			}		}	}	m_encodedBytes += flush(pb, ((m_pBufferCurrent - m_encoded_frame_buffer) << 3) + m_bitsInCache, 0);}boolCH261PixelEncoder::EncodeImage(const uint8_t *pY, 			       const uint8_t *pU,			       const uint8_t *pV,			       uint32_t yStride,			       uint32_t uvStride,			       bool wantKeyFrame,			       Duration elapsedDuration,			       Timestamp srcTimestamp){  uint32_t y;  const uint8_t *pFrame;  // check if everything is all together  m_srcFrameTimestamp = srcTimestamp;  pFrame = pY;  if (m_localbuffer == NULL) {    m_localbuffer = (uint8_t *)malloc(framesize_ + (framesize_ / 2));  }  CopyYuv(pY, pU, pV, yStride, uvStride, uvStride,	  m_localbuffer, m_localbuffer + framesize_, 	  m_localbuffer + framesize_ + (framesize_ / 4),	  width_, width_ / 2, width_ / 2, 	  width_, height_);  pFrame = m_localbuffer;  pY = m_localbuffer;  pU = m_localbuffer + framesize_;  pV = pU + framesize_ / 4;  // check if we should adjust quality  if (m_framesEncoded == 0) {    m_firstDuration = elapsedDuration;    m_framesEncoded++;  } else {    if (m_framesEncoded >= m_framesForQualityCheck) {      Duration dur8frames = elapsedDuration - m_firstDuration;      dur8frames /= 1000;      Duration realBps = (m_encodedBytes * 8);      Duration calcBps;      calcBps = m_bitRate;      realBps *= 1000;      realBps /= dur8frames;      int adj = 0;      Duration diff = 0;      if (calcBps > realBps) {	// we can up the quality a bit	diff = (calcBps - realBps) / m_framerate;	if (diff > m_bitsPerFrame / 2) {	  adj = 2;	} else if (diff > m_bitsPerFrame / 4) {	  adj = 1;	}      } else if (calcBps < realBps) {	diff = (realBps - calcBps) / m_framerate;	if (diff > m_bitsPerFrame / 2) {	  adj = -6;	} else if (diff > m_bitsPerFrame / 4) {	  adj = -4;	} else if (diff > m_bitsPerFrame / 5) {	  adj = -3;	} else if (diff > m_bitsPerFrame / 8) {	  adj = -2;	} else if (diff > 0) {	  adj = -1;	}	// lower quality - we're sending more      }#ifdef DEBUG_QUALITY_ADJUSTMENT	error_message("dur "D64" calc bps "D64" should %u "D64" diff "D64" cmp "D64", adjust %d %d", 		      dur8frames, calcBps, m_encodedBytes, realBps, diff,		      m_bitsPerFrame,		      adj, lq_ - adj);#endif      if (adj != 0) {	setq(lq_ - adj);      }      m_firstDuration = elapsedDuration;      m_encodedBytes = 0;      m_framesEncoded = 0;    }    m_framesEncoded++;  }  //debug_message("encoding h261 image");  if (m_started == false) {    /* Frame size changed. Reallocate frame data space and reinit crvec */    if (frame_data_ != 0) {      delete [] frame_data_;    }    frame_data_ = new u_int8_t[width_*height_*3/2];    if (pY != 0) {      memcpy(frame_data_, pY, framesize_);    }    if (pU != 0) {      memcpy(frame_data_+framesize_,	     pU, framesize_/4);    }    if (pV != 0) {      memcpy(frame_data_+ framesize_*5/4,	     pU, framesize_/ 4);    }    crinit(width_, height_);    m_started = true;  } else {    /* Frame size is the same, so do conditional replenishment. */    int mark = age_blocks() | CR_MOTION_BIT | CR_LQ;    register int _stride = width_;    const u_char* rb = &(frame_data_[scan_ * _stride]);    const u_char* lb = &(pY[scan_ * _stride]);    u_char* crv = crvec_;    uint32_t bw = width_/16;    uint32_t bh = height_/16;    for (y = 0; y < bh; y++) {      const u_char* nrb = rb;      const u_char* nlb = lb;      u_char* ncrv = crv;      for (uint32_t x = 0; x < bw; x++) {	int tl = 0;	int tc1 = 0;	int tc2 = 0;	int tr = 0;	int bl = 0;	int bc1 = 0;	int bc2 = 0;	int br = 0;	tl = lb[0] - rb[0] + lb[1] - rb[1] + lb[2] - rb[2] + lb[3] - rb[3];	if (tl < 0) tl = -tl;	tc1 = lb[4] - rb[4] + lb[5] - rb[5] + lb[6] - rb[6] + lb[7] - rb[7];	if (tc1 < 0) tc1 = -tc1;	tc2 = lb[8] - rb[8] + lb[9] - rb[9] + lb[10] - rb[10] + lb[11] -rb[11];	if (tc2 < 0) tc2 = -tc2;	tr = lb[12] - rb[12] + lb[13] - rb[13] + lb[14] - rb[14] +	  lb[15] - rb[15];	if (tr < 0) tr = -tr;	lb += _stride << 3;	rb += _stride << 3;	bl = lb[0] - rb[0] + lb[1] - rb[1] + lb[2] - rb[2] + lb[3] - rb[3];	if (bl < 0) bl = -bl;	bc1 = lb[4] - rb[4] + lb[5] - rb[5] + lb[6] - rb[6] + lb[7] - rb[7];	if (bc1 < 0) bc1 = -bc1;	bc2 = lb[8] - rb[8] + lb[9] - rb[9] + lb[10] - rb[10] + lb[11] -rb[11];	if (bc2 < 0) bc2 = -bc2;	br = lb[12] - rb[12] + lb[13] - rb[13] + lb[14] - rb[14] +	  lb[15] - rb[15];	if (br < 0) br = -br;	lb -= _stride << 3;	rb -= _stride << 3;	if (scan_ < 4) {	  /* north-west */	  if ((tl >= 24) && (x > 0) && (y > 0)) {	    crv[-bw-1] = mark;	  }	  /* north */	  if (((tl >= 24) || (tc1 >= 24) || (tc2 >= 24) || (tr >= 24)) &&	      (y > 0)) {	    crv[-bw] = mark;	  }	  /* north-east */	  if ((tr >= 24) && (x < bw - 1) && (y > 0)) {	    crv[-bw+1] = mark;	  }	  /* west */	  if (((tl >= 24) || (bl >= 24)) && (x > 0)) {	    crv[-1] = mark;	  }	  /* middle */	  if ((tl >= 24) || (tc1 >= 24) || (tc2 >= 24) || (tr >= 24) ||	      (bl >= 24) || (bc1 >= 24) || (bc2 >= 24) || (br >= 24)) {	    crv[0] = mark;	  }	  /* east */	  if (((tr >= 24) || (br >=24)) && (x < bw - 1)) {	    crv[1] = 0;	  }	} else {	  /* south-west */	  if ((bl >= 24) && (x > 0) && (y < bh-1)) {	    crv[bw-1] = mark;	  }	  /* south */	  if (((bl >= 24) || (bc1 >= 24) || (bc2 >= 24) || (br >= 24)) &&	      (y < bh-1)) {	    crv[bw] = mark;	  }	  /* south-east */	  if ((br >= 24) && (x < bw - 1) && (y < bh - 1)) {	    crv[bw+1] = mark;	  }	  /* west */	  if (((bl >= 24) || (tl >= 24)) && (x > 0)) {	    crv[-1] = mark;	  }	  /* middle */	  if ((bl >= 24) || (bc1 >= 24) || (bc2 >= 24) || (br >= 24) ||	      (tl >= 24) || (tc1 >= 24) || (tc2 >= 24) || (tr >= 24)) {	    crv[0] = mark;	  }	  /* east */	  if (((br >= 24) || (tr >=24)) && (x < bw - 1)) {	    crv[1] = 0;	  }	}	lb += 16;	rb += 16;	crv++;      }      lb = nlb + (_stride << 4);      rb = nrb + (_stride << 4);      crv = ncrv + bw;    }    /* Copy blocks into frame based on conditional replenishment */    crv = crvec_;    uint32_t off = framesize_;    u_char* dest_lum = frame_data_;    u_char* dest_cr = frame_data_+off;    u_char* dest_cb = frame_data_+off+(off/4);    const u_char* src_lum = pFrame;    const u_char* src_cr = pFrame + off;    const u_char* src_cb = pFrame + off + (off / 4);    //debug_message("Sending start");    for (y = 0; y < bh; y++) {      int i;      for (uint32_t x = 0; x < bw; x++) {	int s = *crv++;	if ((s & CR_SEND) != 0) {	  //  debug_message("Sending %u %u", y, x);	  int idx = y*_stride*16+x*16;	  u_int32_t* sl = (u_int32_t*) &(src_lum[idx]);	  u_int32_t* dl = (u_int32_t*) &(dest_lum[idx]);	  for(i=0; i<16; i++) {	    dl[0] = sl[0];	    dl[1] = sl[1];	    dl[2] = sl[2];	    dl[3] = sl[3];	    dl += (_stride / 4);	    sl += (_stride / 4);	  }	  idx = y*(_stride/2)*8+x*8;	  u_int32_t* scr = (u_int32_t*) &(src_cr[idx]);	  u_int32_t* scb = (u_int32_t*) &(src_cb[idx]);	  u_int32_t* dcr = (u_int32_t*) &(dest_cr[idx]);	  u_int32_t* dcb = (u_int32_t*) &(dest_cb[idx]);	  for(i=0; i<8; i++) {	    dcr[0] = scr[0];	    dcr[1] = scr[1];	    dcb[0] = scb[0];	    dcb[1] = scb[1];	    dcr += _stride / 8;	    dcb += _stride / 8;	    scr += _stride / 8;	    scb += _stride / 8;	  }	}      }    }  }  encode(pFrame, crvec_);  return true;}bool CH261PixelEncoder::GetEncodedImage(uint8_t **ppBuffer, 				       uint32_t *pBufferLength,					Timestamp *dts, 					Timestamp *pts){  *dts = *pts = m_srcFrameTimestamp;  *ppBuffer = (uint8_t *)m_head;  m_head = NULL;  *pBufferLength = 0;  return true;}bool CH261PixelEncoder::GetReconstructedImage(uint8_t *pY, 					     uint8_t *pU, 					     uint8_t *pV){  uint32_t uvsize = framesize_ / 4;  memcpy(pY,frame_data_, framesize_);  memcpy(pU, frame_data_ + framesize_, uvsize);  memcpy(pV, frame_data_ + framesize_ + uvsize, uvsize);  return true;}bool CH261Encoder::Init(void){  float value;  setq(Profile()->GetIntegerValue(CFG_VIDEO_H261_QUALITY));  m_bitRate = Profile()->GetIntegerValue(CFG_VIDEO_BIT_RATE) * 1000;  value = Profile()->GetFloatValue(CFG_VIDEO_FRAME_RATE);  value = value + 0.5;  m_framerate = (uint8_t)value;  m_bitsPerFrame = m_bitRate / m_framerate;  m_framesForQualityCheck = Profile()->GetIntegerValue(CFG_VIDEO_H261_QUALITY_ADJ_FRAMES);  size(Profile()->m_videoWidth, Profile()->m_videoHeight);  mtu_ = m_mtu;  //  mtu_ = m_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE);  return true;}

⌨️ 快捷键说明

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