?? encoder-h261.cpp
字號:
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 + -