📄 encoder-h261.cxx
字号:
}
}
}
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 + -