?? encoder-h261.cpp
字號:
/* * encoder-h261.cc -- * * H.261 video encoder * * Copyright (c) 1994-2002 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * A. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * B. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * C. Neither the names of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * modifications done 3/2003, wmay@cisco.com */#include "mpeg4ip.h"#include "dct.h"#include "p64-huff.h"#include "crdef.h"#include "util.h"#include "encoder-h261.h"#include "mp4live_config.h"#include "video_util_resize.h"static config_index_t CFG_VIDEO_H261_QUALITY;static config_index_t CFG_VIDEO_H261_QUALITY_ADJ_FRAMES;static SConfigVariable H261ConfigVariables[] = { CONFIG_INT(CFG_VIDEO_H261_QUALITY, "videoH261Quality", 10), CONFIG_INT(CFG_VIDEO_H261_QUALITY_ADJ_FRAMES, "videoH261QualityAdjFrames", 8),};GUI_INT_RANGE(gui_q, CFG_VIDEO_H261_QUALITY, "H.261 Quality", 1, 32);GUI_INT_RANGE(gui_qf, CFG_VIDEO_H261_QUALITY_ADJ_FRAMES, "Frames before Adjusting Quality", 1, 100);DECLARE_TABLE(h261_gui_options) = { TABLE_GUI(gui_q), TABLE_GUI(gui_qf),};DECLARE_TABLE_FUNC(h261_gui_options);void AddH261ConfigVariables (CVideoProfile *pConfig){ pConfig->AddConfigVariables(H261ConfigVariables, NUM_ELEMENTS_IN_ARRAY(H261ConfigVariables));}//#define DEBUG_QUALITY_ADJUSTMENT 1#define HLEN (4)#define CIF_WIDTH 352#define CIF_HEIGHT 288#define QCIF_WIDTH 176#define QCIF_HEIGHT 144#define BMB 6 /* # blocks in a MB */#define MBPERGOB 33 /* # of Macroblocks per GOB */#if BYTE_ORDER == LITTLE_ENDIAN#if NBIT == 64#define STORE_BITS(bb, bc) \ bc[0] = bb >> 56; \ bc[1] = bb >> 48; \ bc[2] = bb >> 40; \ bc[3] = bb >> 32; \ bc[4] = bb >> 24; \ bc[5] = bb >> 16; \ bc[6] = bb >> 8; \ bc[7] = bb;#define LOAD_BITS(bc) \ ((BB_INT)bc[0] << 56 | \ (BB_INT)bc[1] << 48 | \ (BB_INT)bc[2] << 40 | \ (BB_INT)bc[3] << 32 | \ (BB_INT)bc[4] << 24 | \ (BB_INT)bc[5] << 16 | \ (BB_INT)bc[6] << 8 | \ (BB_INT)bc[7])#else#define STORE_BITS(bb, bc) \ bc[0] = bb >> 24; \ bc[1] = bb >> 16; \ bc[2] = bb >> 8; \ bc[3] = bb;#define LOAD_BITS(bc) (ntohl(*(BB_INT*)(bc)))#endif#else#define STORE_BITS(bb, bc) *(BB_INT*)bc = (bb);#define LOAD_BITS(bc) (*(BB_INT*)(bc))#endif#define PUT_BITS(bits, n, nbb, bb, bc) \{ \ nbb += (n); \ if (nbb > NBIT) { \ u_int extra = (nbb) - NBIT; \ bb |= (BB_INT)(bits) >> extra; \ STORE_BITS(bb, bc) \ bc += sizeof(BB_INT); \ bb = (BB_INT)(bits) << (NBIT - extra); \ nbb = extra; \ } else \ bb |= (BB_INT)(bits) << (NBIT - (nbb)); \}CH261Encoder::CH261Encoder(CVideoProfile *vp, uint16_t mtu, CVideoEncoder *next, bool realTime) : CVideoEncoder(vp, mtu, next, realTime), m_encoded_frame_buffer(0), m_pBufferCurrent(0), ngob_(12){ m_head = NULL; frame_data_ = NULL; m_framesEncoded = 0; m_localbuffer = NULL; for (int q = 0; q < 32; ++q) { llm_[q] = 0; clm_[q] = 0; }}void CH261Encoder::StopEncoder (void){ for (int q = 0; q < 32; ++q) { if (llm_[q] != 0) delete[] llm_[q]; if (clm_[q] != 0) delete[] clm_[q]; } CHECK_AND_FREE(m_localbuffer);}CH261PixelEncoder::CH261PixelEncoder(CVideoProfile *vp, uint16_t mtu, CVideoEncoder *next, bool realTime) : CH261Encoder(vp, mtu, next, realTime), ConditionalReplenisher(){ quant_required_ = 0; setq(10); m_started = false;}/* * Set up the forward DCT quantization table for * INTRA mode operation. */voidCH261Encoder::setquantizers(int lq, int mq, int hq){ int qt[64]; if (lq > 31) lq = 31; if (lq <= 0) lq = 1; lq_ = lq; if (mq > 31) mq = 31; if (mq <= 0) mq = 1; mq_ = mq; if (hq > 31) hq = 31; if (hq <= 0) hq = 1; hq_ = hq; /* * quant_required_ indicates quantization is not folded * into fdct [because fdct is not performed] */ if (quant_required_ == 0) { /* * Set the DC quantizer to 1, since we want to do this * coefficient differently (i.e., the DC is rounded while * the AC terms are truncated). */ qt[0] = 1; int i; for (i = 1; i < 64; ++i) qt[i] = lq_ << 1; dct_fdct_fold_q(qt, lqt_); qt[0] = 1; for (i = 1; i < 64; ++i) qt[i] = mq_ << 1; dct_fdct_fold_q(qt, mqt_); qt[0] = 1; for (i = 1; i < 64; ++i) qt[i] = hq_ << 1; dct_fdct_fold_q(qt, hqt_); }}voidCH261Encoder::setq(int q){ setquantizers(q, q / 2, 1);}voidCH261PixelEncoder::size(int w, int h){ // next 3 lines is FrameModule::size(w, h); width_ = w; height_ = h; framesize_ = w * h; if (w == CIF_WIDTH && h == CIF_HEIGHT) { /* CIF */ cif_ = 1; ngob_ = 12; bstride_ = 11; lstride_ = 16 * CIF_WIDTH - CIF_WIDTH / 2; cstride_ = 8 * 176 - 176 / 2; loffsize_ = 16; coffsize_ = 8; bloffsize_ = 1; } else if (w == QCIF_WIDTH && h == QCIF_HEIGHT) { /* QCIF */ cif_ = 0; ngob_ = 6; /* not really number of GOBs, just loop limit */ bstride_ = 0; lstride_ = 16 * QCIF_WIDTH - QCIF_WIDTH; cstride_ = 8 * 88 - 88; loffsize_ = 16; coffsize_ = 8; bloffsize_ = 1; } else { /*FIXME*/ fprintf(stderr, "CH261PixelEncoder: H.261 bad geometry: %dx%d\n", w, h); exit(1); } u_int loff = 0; u_int coff = 0; u_int blkno = 0; for (u_int gob = 0; gob < ngob_; gob += 2) { loff_[gob] = loff; coff_[gob] = coff; blkno_[gob] = blkno; /* width of a GOB (these aren't ref'd in QCIF case) */ loff_[gob + 1] = loff + 11 * 16; coff_[gob + 1] = coff + 11 * 8; blkno_[gob + 1] = blkno + 11; /* advance to next GOB row */ loff += (16 * 16 * MBPERGOB) << cif_; coff += (8 * 8 * MBPERGOB) << cif_; blkno += MBPERGOB << cif_; }}/* * Make a map to go from a 12 bit dct value to an 8 bit quantized * 'level' number. The 'map' includes both the quantizer (for the * dct encoder) and the perceptual filter 'threshold' (for both * the pixel & dct encoders). The first 4k of the map is for the * unfiltered coeff (the first 20 in zigzag order; roughly the * upper left quadrant) and the next 4k of the map are for the * filtered coef. */char*CH261Encoder::make_level_map(int q, u_int fthresh){ /* make the luminance map */ char* lm = new char[0x2000]; char* flm = lm + 0x1000; int i; lm[0] = 0; flm[0] = 0; q = quant_required_? q << 1 : 0; for (i = 1; i < 0x800; ++i) { int l = i; if (q) l /= q; lm[i] = l; lm[-i & 0xfff] = -l; if ((u_int)l <= fthresh) l = 0; flm[i] = l; flm[-i & 0xfff] = -l; } return (lm);}/* * encode_blk: * encode a block of DCT coef's */voidCH261Encoder::encode_blk(const short* blk, const char* lm){ BB_INT bb = m_bitCache; u_int nbb = m_bitsInCache; uint8_t * bc = m_pBufferCurrent; /* * Quantize DC. Round instead of truncate. */ int dc = (blk[0] + 4) >> 3; if (dc <= 0) /* shouldn't happen with CCIR 601 black (level 16) */ dc = 1; else if (dc > 254) dc = 254; else if (dc == 128) /* per Table 6/H.261 */ dc = 255; /* Code DC */ PUT_BITS(dc, 8, nbb, bb, bc); int run = 0; const u_char* colzag = &DCT_COLZAG[0]; for (int zag; (zag = *++colzag) != 0; ) { if (colzag == &DCT_COLZAG[20]) lm += 0x1000; int level = lm[((const u_short*)blk)[zag] & 0xfff]; if (level != 0) { int val, nb; huffent* he; if (u_int(level + 15) <= 30 && (nb = (he = &hte_tc[((level&0x1f) << 6)|run])->nb)) /* we can use a VLC. */ val = he->val; else { /* Can't use a VLC. Escape it. */ val = (1 << 14) | (run << 8) | (level & 0xff); nb = 20; } PUT_BITS(val, nb, nbb, bb, bc); run = 0; } else ++run; } /* EOB */ PUT_BITS(2, 2, nbb, bb, bc); m_bitCache = bb; m_bitsInCache = nbb; m_pBufferCurrent = bc;}/* * CH261PixelEncoder::encode_mb * encode a macroblock given a set of input YUV pixels */voidCH261PixelEncoder::encode_mb(u_int mba, const u_char* frm, u_int loff, u_int coff, int how){ register int q; float* qt; if (how == CR_LQ) { q = lq_; qt = lqt_; } else if (how == CR_HQ) { q = hq_; qt = hqt_; } else { /* must be medium quality */ q = mq_; qt = mqt_; } /* * encode all 6 blocks of the macro block to find the largest * coef (so we can pick a new quantizer if gquant doesn't have * enough range). */ /*FIXME this can be u_char instead of short but need smarts in fdct */ short blk[64 * 6]; register int stride = width_; /* luminance */ const u_char* p = &frm[loff]; dct_fdct(p, stride, blk + 0, qt); dct_fdct(p + 8, stride, blk + 64, qt); dct_fdct(p + 8 * stride, stride, blk + 128, qt); dct_fdct(p + (8 * stride + 8), stride, blk + 192, qt); /* chominance */ int fs = framesize_; p = &frm[fs + coff]; stride >>= 1; dct_fdct(p, stride, blk + 256, qt); dct_fdct(p + (fs >> 2), stride, blk + 320, qt); /* * 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 = blk; for (register int i = 6; --i >= 0; ) { ++bp; // ignore dc coef for (register int j = 63; --j >= 0; ) { register int v = *bp++; if (v < cmin) cmin = v; else if (v > cmax) cmax = v; } } if (cmax < -cmin) cmax = -cmin; if (cmax >= 128) { /* need to re-quantize */ register int s; for (s = 1; cmax >= (128 << s); ++s) { } q <<= s; if (q > 31) q = 31; if (q < 1) q = 1; register short* bp = blk; for (register int i = 6; --i >= 0; ) { ++bp; // ignore dc coef for (register int j = 63; --j >= 0; ) { register int v = *bp; *bp++ = v >> s; } } } } u_int m = mba - mba_; mba_ = mba; huffent* he = &hte_mba[m - 1]; /* MBA */ PUT_BITS(he->val, he->nb, m_bitsInCache, m_bitCache, m_pBufferCurrent); if (q != mquant_) { /* MTYPE = INTRA + TC + MQUANT */ PUT_BITS(1, 7, m_bitsInCache, m_bitCache, m_pBufferCurrent); PUT_BITS(q, 5, m_bitsInCache, m_bitCache, m_pBufferCurrent); mquant_ = q; } else { /* MTYPE = INTRA + TC (no quantizer) */ PUT_BITS(1, 4, m_bitsInCache, m_bitCache, m_pBufferCurrent); } /* 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);}intCH261Encoder::flush(pktbuf_t* pb, int last_mb_start_bits, pktbuf_t* pNewBuffer){ /* flush bit buffer */ STORE_BITS(m_bitCache, m_pBufferCurrent); int cc = (last_mb_start_bits + 7) >> 3; int ebit = (cc << 3) - last_mb_start_bits; /*FIXME*/ if (cc == 0 && pNewBuffer != 0) abort(); pb->len = cc;#if 0 rtphdr* rh = (rtphdr*)pb->data; if (pNewBuffer == 0) rh->rh_flags |= htons(RTP_M);#endif
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -