/* * Copyright (c) 1993-1994 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. */ /* * This code is derived from the P64 software implementation by the * Stanford PVRG group: * * Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved. * PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research * Group. If you use this software, you agree to the following: This * program package is purely experimental, and is licensed "as is". * Permission is granted to use, modify, and distribute this program * without charge for any purpose, provided this license/ disclaimer * notice appears in the copies. No warranty or maintenance is given, * either expressed or implied. In no event shall the author(s) be * liable to you or a third party for any special, incidental, * consequential, or other damages, arising out of the use or inability * to use the program for any purpose (or the loss of data), even if we * have been advised of such possibilities. Any public reference or * advertisement of this source code should refer to it as the Portable * Video Research Group (PVRG) code, and not by any author(s) (or * Stanford University) name. */ #include #include #include #include "bsd-endian.h" #include "p64/p64-huff.h" #include "transmitter.h" #include "module.h" #define IT_QCIF 0 #define IT_CIF 1 #define MBPERGOB 33 #if BYTE_ORDER == LITTLE_ENDIAN #define HUFFRQ(bs, bb) \ { \ register int t = *bs++; \ bb <<= 16; \ bb |= (t & 0xff) << 8; \ bb |= t >> 8; \ } #else #define HUFFRQ(bs, bb) \ { \ bb <<= 16; \ bb |= *bs++; \ } #endif #define MASK(s) ((1 << (s)) - 1) #define HUFF_DECODE(bs, ht, nbb, bb, result) { \ register int s__, v__; \ \ if (nbb < 16) { \ HUFFRQ(bs, bb); \ nbb += 16; \ } \ s__ = ht.maxlen; \ v__ = (bb >> (nbb - s__)) & MASK(s__); \ s__ = (ht.prefix)[v__]; \ nbb -= (s__ & 0x1f); \ result = s__ >> 5; \ } #define GET_BITS(bs, n, nbb, bb, result) \ { \ nbb -= n; \ if (nbb < 0) { \ HUFFRQ(bs, bb); \ nbb += 16; \ } \ (result) = ((bb >> nbb) & MASK(n)); \ } #define SKIP_BITS(bs, n, nbb, bb) \ { \ nbb -= n; \ if (nbb < 0) { \ HUFFRQ(bs, bb); \ nbb += 16; \ } \ } class H261hwFramer : public TransmitterModule { public: H261hwFramer(); ~H261hwFramer(); virtual int consume(const VideoFrame*); virtual int command(int argc,const char *const *argv); // void setq(int x); protected: int parse_block(); int parse_gob_hdr(int ebit); int parse_mb_hdr(unsigned int &); int decode_mb(); int decode(const unsigned char *, int, int, int); int mq_; struct hufftab { int maxlen; const short* prefix; }; hufftab ht_mba_; hufftab ht_mvd_; hufftab ht_cbp_; hufftab ht_tcoeff_; hufftab ht_mtype_; int nbb_; // number of bits in buffer int bb_; // bitbuffer u_int fmt_; // format int mt_; // mtype int mba_; //macroblock address const u_short *bs_; // bit stream to read from... int mvdv_,mvdh_; //motion vector int gob_; //current gob const u_short* es_; /* pointer to end if input stream */ char transmitter_; // tclobject transmitter }; static class H261hwFramerMatcher : public Matcher { public: H261hwFramerMatcher() : Matcher("module") {} TclObject* match(const char* fmt) { //fprintf(stderr,"H261hwFramerMatcher::match(%s)\n",fmt); if (strcasecmp(fmt, "h261/hw") == 0) return (new H261hwFramer); return (0); } } framer_matcher_h261hw; H261hwFramer::H261hwFramer() : TransmitterModule(FT_H261) { /* * Set up the huffman tables. */ ht_mtype_.prefix = htd_mtype; ht_mtype_.maxlen = htd_mtype_width; ht_mba_.prefix = htd_mba; ht_mba_.maxlen = htd_mba_width; ht_mvd_.prefix = htd_dvm; ht_mvd_.maxlen = htd_dvm_width; ht_cbp_.prefix = htd_cbp; ht_cbp_.maxlen = htd_cbp_width; ht_tcoeff_.prefix = htd_tcoeff; ht_tcoeff_.maxlen = htd_tcoeff_width; } H261hwFramer::~H261hwFramer() { /* if (tx_ != 0) tx_->flush(); */ } /* void H261hwFramer::setq(int arg) { //fprintf(stderr,"H261hwFramer::setq(%d)\n",arg); } */ int H261hwFramer::command(int argc,const char* const *argv) { /* fprintf(stderr,"H261hwFramer::command("); for (int i=0;i> (nbb - 1)) & 1) { /* * In CBP blocks, the first block present must be * non-empty (otherwise it's mask bit wouldn't * be set), so the first code cannot be an EOB. * CCITT optimizes this case by using a huffman * table equivalent to ht_tcoeff_ but without EOB, * in which 1 is coded as "1" instead of "11". * We grab two bits, the first bit is the code * and the second is the sign. */ SKIP_BITS(bs, 2, nbb, bb); } int nc = 0; for (;;) { register int r; HUFF_DECODE(bs, ht_tcoeff_, nbb, bb, r); if (r <= 0) { /* SYM_EOB, SYM_ILLEGAL, or SYM_ESCAPE */ if (r == SYM_ESCAPE) { SKIP_BITS(bs, 14, nbb, bb); } else { if (r == SYM_ILLEGAL) { bb_ = bb; nbb_ = nbb; bs_ = bs; } /* EOB */ break; } } } /* * Done reading input. Update bit buffer. */ bb_ = bb; nbb_ = nbb; bs_ = bs; return (nc); } /* * Parse a GOB header, which consists of the GOB quantiation * factor (GQUANT) and spare bytes that we ignore. */ int H261hwFramer::parse_gob_hdr(int ebit) { mba_ = -1; mvdh_ = 0; mvdv_ = 0; /* * Get the next GOB number (or 0 for a picture header). * The invariant at the top of this loop is that the * bit stream is positioned immediately past the last * start code. */ int gob; for (;;) { u_int tempref; GET_BITS(bs_, 4, nbb_, bb_, gob); if (gob != 0) break; /* * should happen only on first iteration * (if at all). pictures always start on * packet boundaries per section 5 of the * Internet Draft. */ /* throw away the temporal reference */ GET_BITS(bs_, 5, nbb_, bb_, tempref); /* Picture Type */ int pt; GET_BITS(bs_, 6, nbb_, bb_, pt); u_int fmt = (pt >> 2) & 1; if (fmt_ != fmt) { /* change formats */ fmt_ = fmt; } /* Extra information PEI */ int v; GET_BITS(bs_, 1, nbb_, bb_, v); while (v != 0) { u_int ei; GET_BITS(bs_, 8 , nbb_, bb_, ei); GET_BITS(bs_, 1, nbb_, bb_, v); } /* * Check to see that the next 16 bits * are a start code and throw them away. * But first check that we have the bits. */ int nbit = ((es_ - bs_) << 4) + nbb_ - ebit; if (nbit < 20) return (0); GET_BITS(bs_, 16, nbb_, bb_, v); if (v != 0x0001) { fprintf(stderr,"[bad start code %04x]", v); return (-1); } } gob -= 1; if (fmt_ == IT_QCIF) /* * Number QCIF GOBs 0,1,2 instead of 0,2,4. */ gob >>= 1; /* MQUANT */ GET_BITS(bs_, 5, nbb_, bb_, mq_); /* GEI Gob Extra Information */ int v; GET_BITS(bs_, 1, nbb_, bb_, v); while (v != 0) { SKIP_BITS(bs_, 8, nbb_, bb_); GET_BITS(bs_, 1, nbb_, bb_, v); } gob_ = gob; return (gob); } /* * Parse a macroblock header. If there is no mb header because * we hit the next start code, return -1, otherwise 0. */ int H261hwFramer::parse_mb_hdr(u_int& cbp) { register u_int omt = mt_; /* * Read the macroblock address (MBA) */ int v; HUFF_DECODE(bs_, ht_mba_, nbb_, bb_, v); if (v <= 0) { /* * (probably) hit a start code; either the * next GOB or the next picture header. * If we got MBA stuffing (0) we need to return * so the outer loop can check if we're at the * end of the buffer (lots of codecs put stuffing * at the end of a picture to byte align the psc). */ return (v); } /* * MBA is differentially encoded. */ mba_ += v; if (mba_ >= MBPERGOB) { fprintf(stderr,"[mba too big %d]", mba_); return (SYM_ILLEGAL); } HUFF_DECODE(bs_, ht_mtype_, nbb_, bb_, mt_); if (mt_ & MT_MQUANT) { GET_BITS(bs_, 5, nbb_, bb_, mq_); } if (mt_ & MT_MVD) { int dh,dv; /* * Read motion vector. */ HUFF_DECODE(bs_, ht_mvd_, nbb_, bb_, dh); HUFF_DECODE(bs_, ht_mvd_, nbb_, bb_, dv); /* * Section 4.2.3.4 * The vector is differentially coded unless any of: * - the current mba delta isn't 1 * - the current mba is 1, 12, or 23 (mba mod 11 = 1) * - the last block didn't have motion vectors. * * This arithmetic is twos-complement restricted * to 5 bits. */ if ((omt&MT_MVD)!=0 && v==1 && mba_!=0 && mba_!=11 && mba_!=22){ dh += mvdh_; dv += mvdv_; } mvdh_ = (dh << 27) >> 27; mvdv_ = (dv << 27) >> 27; } else { mvdh_ = mvdv_ = 0; } /* * Coded block pattern. */ if (mt_ & MT_CBP) { HUFF_DECODE(bs_, ht_cbp_, nbb_, bb_, cbp); if (cbp > 0x3f) { fprintf(stderr,"[cbp invalid %x]", cbp); return (SYM_ILLEGAL); } } else cbp = 0x3f; return (1); } /* * Decompress the next macroblock. Return 0 if the macroblock * was present (with no errors). Return SYM_STARTCODE (-1), * if there was no macroblock but instead the start of the * next GOB or picture (in which case the start code has * been consumed). Return SYM_ILLEGAL (-2) if there was an error. */ /* * Handle the next block in the current macroblock. * If tc is non-zero, then coefficients are present * in the input stream and they are parsed. Otherwise, * coefficients are not present, but we take action * according to the type macroblock that we have. */ int H261hwFramer::decode_mb() { u_int cbp; register int v; if ((v = parse_mb_hdr(cbp)) <= 0) return (v); /* * Decode the six blocks in the MB (4Y:1U:1V). * (This code assumes MT_TCOEFF is 1.) */ register u_int tc = mt_ & MT_TCOEFF; if(tc & (cbp >> 5)) parse_block(); if(tc & (cbp >> 4)) parse_block(); if(tc & (cbp >> 3)) parse_block(); if(tc & (cbp >> 2)) parse_block(); if(tc & (cbp >> 1)) parse_block(); if(tc & (cbp >> 0)) parse_block(); return (0); } /* * Decode H.261 stream. Decoding can begin on either * a GOB or macroblock header. All the macroblocks of * a given frame can be decoded in any order, but chunks * cannot be reordered across frame boundaries. Since data * can be decoded in any order, this entry point can't tell * when a frame is fully decoded (actually, we could count * macroblocks but if there is loss, we would not know when * to sync). Instead, the callee should sync the decoder * by calling the sync() method after the entire frame * has been decoded (modulo loss). * * This routine should not be called with more than * one frame present since there is no callback mechanism * for renderering frames (i.e., don't call this routine * with a buffer that has a picture header that's not * at the front). */ int H261hwFramer::consume(const VideoFrame* vf) { H261Frame* p = (H261Frame*)vf; int i; int cc = p->len_; int sentbytes = 0; char *frameend; pktbuf* pb = pool_->alloc(p->ts_, RTP_PT_H261); /* RTP/H.261 header */ rtphdr* rh = (rtphdr*)pb->data; *(u_int*)(rh + 1) = (1<<24) | (mq_ << 10); char *lastaddr,*lastsentaddr; u_int lastmt,lastgob,lastmquant,lastmba,lastbit,lastsentbit; int lastmvdv,lastmvdh; u_int ec = tx_->mtu() - HDRSIZE ; // payload byte int stuffzero; struct { int mask; int comp; } tab[] = { {0xff,0x01}, {0xfe,0x02}, {0xfc,0x04}, {0xf8,0x08}, {0xf0,0x10}, {0xe0,0x20}, {0xc0,0x40}, {0x80,0x80} }; tx_->flush(); bs_ = (u_short*)p->bp_; es_ = (u_short*)(p->bp_ + ((cc - 1) &~ 1)); frameend = (char*)p->bp_+cc-1; /* * If input buffer not aligned, prime bit-buffer * with 8 bits; otherwise, prime it with a 16. */ lastaddr = (char*)p->bp_; lastsentaddr = (char*)p->bp_; lastmquant = 0; lastbit = 0; lastsentbit = 0; lastmvdv = lastmvdh = 0; stuffzero = 0; if ((int)p->bp_ & 1) { bs_ = (u_short*)(p->bp_ + 1); bb_ = *p->bp_; for (i=0;i<8;i++) { if (((*(u_char*)bs_) & tab[i].mask) == tab[i].comp) break; } /* 0000 0000 00X0 0000 * 7654 3210 */ lastsentbit = 8-i; if (lastsentbit==8) lastsentbit=0; else stuffzero=1; nbb_= 8+i; } else { bs_ = (u_short*)p->bp_; bb_ = 0; for (i=0;i<8;i++) { if (((*(((u_char*)bs_)+1)) & tab[i].mask) == tab[i].comp) break; } nbb_= i; // already in bitbuffer...so we read 0001 as start. lastsentbit = 8-i; if (lastsentbit==8) lastsentbit = 0; else stuffzero=1; /* 0000 0000 00X0 0000 * 7654 3210 */ } gob_ = 0; // will be reread before doing anything serious while (bs_ < es_ || (bs_ == es_ && nbb_ > 0)) { int v = decode_mb(); if ((char*)bs_ - (char*)lastsentaddr >= ec-1) { u_int cc = lastaddr-lastsentaddr+1; if (stuffzero) { //*(pb->iov[1].iov_base)=0; pb->data[HDRSIZE]=0; //memcpy(pb->iov[1].iov_base+1,lastsentaddr,cc); memcpy(&pb->data[HDRSIZE+1],lastsentaddr,cc); //pb->iov[1].iov_len = cc+1; pb->len = cc+HDRSIZE+1; stuffzero = 0; } else { //memcpy(pb->iov[1].iov_base,lastsentaddr,cc); memcpy(&pb->data[HDRSIZE],lastsentaddr,cc); //pb->iov[1].iov_len = cc; pb->len = cc+HDRSIZE; } //pb->iov[0].iov_len = HDRSIZE; u_int h=(*(u_int*)(rh+1))|(lastbit<<26)|(lastsentbit<<29); *(u_int*)(rh+1) = htonl(h); tx_->send(pb); sentbytes+= HDRSIZE+cc; pb = pool_->alloc(vf->ts_, RTP_PT_H261); //rh = (rtphdr*)pb->iov[0].iov_base; rh = (rtphdr*)pb->data; *(u_int*)(rh + 1) = (lastgob << 20) | (lastmba << 15) | (mq_ << 10); /* motion vector data: */ *(u_int*)(rh+1)|=1<<24; /* M Bit */ if (lastmt & MT_MVD) { if (lastmvdv>=0) *(u_int*)(rh+1)|=lastmvdv; else *(u_int*)(rh+1)|=(32+lastmvdv); if (lastmvdh>=0) *(u_int*)(rh+1)|=lastmvdh<<5; else *(u_int*)(rh+1)|=(32+lastmvdh)<<5; } lastsentbit = lastbit; lastsentaddr = lastaddr; if (!lastbit) { lastsentaddr++; } else { lastsentbit = 8-lastsentbit; } } if (v == 0) { // store the current address as GOOD latest address. // lastaddr is the last byte read from the bytestream. lastaddr = ((char*)bs_) - ((nbb_+8) >> 3); // how much bits do we have NOT used from the last byte. lastbit = nbb_&7; lastmquant = mq_; lastmvdv = mvdv_; lastmvdh = mvdh_; lastmba = mba_; lastgob = gob_+1; lastmt = mt_; continue; } if (v != SYM_STARTCODE) { fprintf(stderr,"[expected GOB startcode,v=%d]",v); break;/*return (0);*/ } gob_ = parse_gob_hdr(lastsentbit); lastgob = gob_; lastmba = 0; lastmvdv= lastmvdh = 0; lastmt = mt_; if (gob_ < 0) { fprintf(stderr,"[GOB < 0]"); return (0); } } /* just dump the rest... don't care about cc and bitshifts, * but trust the grabbing device... */ cc = frameend-lastsentaddr+1; //pb->iov[0].iov_len = HDRSIZE; //memcpy(pb->iov[1].iov_base,lastsentaddr,cc); memcpy(&pb->data[HDRSIZE],lastsentaddr,cc); //pb->iov[1].iov_len = cc; pb->len = cc+HDRSIZE; rh->rh_flags |= htons(RTP_M); u_int h = *(u_int*)(rh+1)|((nbb_&7)<<26) | (lastsentbit<<29); *(u_int*)(rh+1) = htonl(h); tx_->send(pb); sentbytes+= HDRSIZE+cc; //tx_->flush(); return sentbytes; }