📄 encoder-h261.h
字号:
/*encoder-h261.h (c) 1999-2000 Derek J Smithies (dereks@ibm.net)
* Indranet Technologies ltd (lara@indranet.co.nz)
*
* This file is derived from vic, http://www-nrg.ee.lbl.gov/vic/
* Their copyright notice is below.
*/
/*-
* Copyright (c) 1993-1995 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:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and the Network Research Group at
* Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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.
*/
/************ Change log
*
* $Log: encoder-h261.h,v $
* Revision 1.12 2002/05/17 01:47:33 dereks
* backout the integer maths in the h261 codec.
*
* Revision 1.11 2002/04/26 04:57:41 dereks
* Add Walter Whitlocks fixes, based on Victor Ivashim's suggestions to
* improve the quality with Netmeeting. Thanks guys!!!!
*
* Revision 1.10 2002/04/05 00:53:19 dereks
* Modify video frame encoding so that frame is encoded on an incremental basis.
* Thanks to Walter Whitlock - good work.
*
* Revision 1.9 2001/10/16 23:51:42 dereks
* Change vic's fdct() from floating-point to fix-point. Improves performance
* for h261 video significantly on some machines. Thanks to Cosmos Jiang
*
* Revision 1.8 2001/10/16 21:20:07 yurik
* Removed warnings on Windows CE. Submitted by Jehan Bing, jehan@bravobrava.com
*
* Revision 1.6 2001/05/10 05:25:44 robertj
* Removed need for VIC code to use ptlib.
*
* Revision 1.5 2000/08/25 03:18:49 dereks
* Add change log facility (Thanks Robert for the info on implementation)
*
*
*
********/
#include "bsd-endian.h"
#include "dct.h"
#include "p64-huff.h"
#include "crdef.h"
#include "transmitter.h"
#include "encoder.h"
/*
* H.261 encapsulation.in payload of h261 packet.
* See Internet draft.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |SBIT |EBIT |I|V| GOBN | MBAP | QUANT | HMVD | VMVD |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
// define H261 header related values
// (currently these are defined in both p64.h and encoder-h261.h for use
// in decode and encode. Should there be one common include file?)
typedef unsigned h261hdr_t;
#define HDRSIZE 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 */
#ifdef INT_64
#define NBIT 64
#define BB_INT INT_64
#else
#define NBIT 32
#define BB_INT u_int
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
#if NBIT == 64
#define STORE_BITS(bb, bc) \
bc[0] = (u_char)(bb >> 56); \
bc[1] = (u_char)(bb >> 48); \
bc[2] = (u_char)(bb >> 40); \
bc[3] = (u_char)(bb >> 32); \
bc[4] = (u_char)(bb >> 24); \
bc[5] = (u_char)(bb >> 16); \
bc[6] = (u_char)(bb >> 8); \
bc[7] = (u_char)(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] = (u_char)(bb >> 24); \
bc[1] = (u_char)(bb >> 16); \
bc[2] = (u_char)(bb >> 8); \
bc[3] = (u_char)(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
/** append the "n" LSbits of "bits" to the place pointed to by bc
post-increment "bc" as needed. "bb" is used for intermediate storage
"nbb" keeps track of bits in "bb"
note that ALL bits in "n" are OR'ed into the result
*/
#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)); \
}
class H261Encoder :public Encoder {
public:
void setq(int q);
protected:
int encode(const VideoFrame*, const u_char *crvec);
H261Encoder(Transmitter *T);
virtual ~H261Encoder(void)=0;
void encode_blk(const short* blk, const char* lm);
int flush(Transmitter::pktbuf* pb, int nbit, Transmitter::pktbuf* npb);
char* make_level_map(int q, u_int fthresh);
void setquantizers(int lq, int mq, int hq);
virtual void SetSize(int /*w*/, int /*h*/){};
virtual void encode_mb(u_int /*mba*/, const u_char* /*frm*/,
u_int /*loff*/, u_int /*coff*/, int /*how*/){};
/* bit buffer */
BB_INT bb_; // intermediate working space for encoding bits
u_int nbb_; // # of valid bits in bb_
u_char* bs_; // used as pointer to start of buffer
u_char* bc_; // where to put encoded bits in buffer
int sbit_; // SBIT value obtained from previous packet for use on next packet
u_char lq_; /* low quality quantizer */
u_char mq_; /* medium quality quantizer */
u_char hq_; /* high quality quantizer */
u_char mquant_; /* the last quantizer we sent to other side */
int quant_required_; /* 1 if not quant'd in dct */
u_int ngob_; // number of GOBs for this frame size, (3 or 12)
u_int mba_; // address of just encoded macroblock
u_int cif_; /* 1 for CIF, 0 for QCIF */
u_int bstride_;
u_int lstride_;
u_int cstride_;
u_int loffsize_; /* amount of 1 luma block */
u_int coffsize_; /* amount of 1 chroma block */
u_int bloffsize_; /* amount of 1 block advance */
const char* llm_[32]; /* luma dct val -> level maps */
const char* clm_[32]; /* chroma dct val -> level maps */
float lqt_[64]; /* low quality quantizer */
float mqt_[64]; /* medium quality quantizer */
float hqt_[64]; /* high quality quantizer */
u_int coff_[12]; /* where to find U given gob# */
u_int loff_[12]; /* where to find Y given gob# */
u_int blkno_[12]; /* for CR */
const VideoFrame *gVf; // current video frame YUV data
BOOL gPicture; // if TRUE, send picture layer header
int gHdrGOBN; // next GOB number for last encoded MB
int gNxtGOB; // GOB number for next marcroblock to be considered for encoding
int gGobMax; // maximum GOB number in frame
BOOL gGOBhdrNxt; // set TRUE when GOB header is next data
BOOL gSendGOBhdr; // set TRUE when GOB header must be encoded before next MB
int gHdrMBAP; // address of last macroblock encoded in previous packet 1..33
int gNxtMBA; // address of next macroblock to be considered for encoding
int gHdrQUANT; // QUANT in effect for next MB in buffer
int gStep; // Macro Block step size
BOOL gDone; // Set TRUE when encoding of frame is done
int gDbase; //offset from gData where valid data starts
int gNbytes; // number of bytes in gData buffer from previous packet
u_int gloff;
u_int gcoff;
u_int gblkno;
int gline;
};
class H261DCTEncoder: public H261Encoder
{
public:
H261DCTEncoder(Transmitter *T);
int consume(const VideoFrame*);
void SetSize(int w, int h);
protected:
void encode_mb(u_int mba, const u_char* frm,
u_int loff, u_int coff, int how);
};
class H261PixelEncoder : public H261Encoder
{
public:
H261PixelEncoder(Transmitter *T);
int consume(const VideoFrame*);
void SetSize(int w, int h);
int PreIncEncodeSetup(const VideoFrame*);
void IncEncodeAndGetPacket(u_char * buffer, unsigned & length );
/** When incrementally encoding, return true if there is still
more encoding waiting to be done for the current video frame.
*/
int MoreToIncEncode()
{ return !gDone; }
protected:
void encode_mb(u_int mba, const u_char* frm,
u_int loff, u_int coff, int how);
//
u_char gData[2 * RTP_MTU];
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -