/* * Copyright (c) 1998-1999 Marcus Meissner and The Regents of the University of * Erlangen. * 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. */ /* History: * * This h263 packager was written for a DFN project (http://www.dfn.de/) at the * University of Erlangen-Nuremberg, Lehrstuhl fuer Nachrichtentechnik by * Marcus Meissner in 1998. * * Merged into UCL vic development tree in 1998 by ? * * Cleanups, endianess, translation of comments into english, bugfixes, * done by Marcus Meissner in June 1999. */ #include #include #include #include #include #include "defs.h" #include "h263.h" /* Bit masks used by bit i/o operations. */ unsigned int nBitMask[] = { 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe}; unsigned int bitMask[] = { 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff, 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff, 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff, 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff, 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f, 0x0000000f, 0x00000007, 0x00000003, 0x00000001}; unsigned int rBitMask[] = { 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000}; unsigned int bitTest[] = { 0x80000000, 0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000, 0x01000000, 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000, 0x00040000, 0x00020000, 0x00010000, 0x00008000, 0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200, 0x00000100, 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008, 0x00000004, 0x00000002, 0x00000001}; #define HDRSIZE_A 4 #define HDRSIZE_B 8 /* FIXME: bitextraction can be done faster, yes */ #ifndef inline static u_long extract_bits(const u_char *bp,const int x,const int n) { #else static inline u_long extract_bits(const u_char *bp,const int x,const int n) { #endif u_long xx; int i; #define BIT(x) !!(bp[x>>3]&(1<<(7-(x&7)))) xx = 0; for (i=x;isyncword = BIT(0,17); h263sh->gobnr = BIT(17,5); h263sh->tr = BIT(22,8); h263sh->reserved0 = BIT(30,1); h263sh->reserved1 = BIT(31,1); h263sh->splitscreen = BIT(32,1); h263sh->doccamera = BIT(33,1); h263sh->freeze_picture_release = BIT(34,1); h263sh->srcformat = BIT(35,3); h263sh->picture_coding_type = BIT(38,1); h263sh->unrestricted_motion_vector = BIT(39,1); h263sh->syntax_based_arithmetic = BIT(40,1); h263sh->advanced_prediction = BIT(41,1); h263sh->pb_frames = BIT(42,1); h263sh->pquant = BIT(43,5); h263sh->cpm = BIT(48,1); h263sh->psbi = BIT(49,1); h263sh->trb = BIT(50,1); h263sh->dbq = BIT(51,2); } #define SBIT(x,to) bp[x>>3]|=(to<<(7-(x&7))) #ifndef inline static void xset_bits(u_char *bp,int x,int to,int n) { #else static inline void xset_bits(u_char *bp,int x,int to,int n) { #endif int i; for (i=n;i--;) { SBIT((x+i),(to&1)); to>>=1; } } #undef SBIT void copy_headerB_to_buf(h263rtpheader_B *h263rh,u_char *bp) { memset(bp,0,8); #define SBIT(x,to,n) xset_bits(bp,x,to,n) SBIT(0,1,1); SBIT(1,h263rh->pbframes,1); SBIT(2,h263rh->sbit,3); SBIT(5,h263rh->ebit,3); SBIT(8,h263rh->srcformat,3); SBIT(11,h263rh->quant,5); SBIT(16,h263rh->gobn,5); SBIT(21,h263rh->mba,9); SBIT(30,h263rh->reserved,2); SBIT(32,h263rh->picture_coding_type,1); SBIT(33,h263rh->unrestricted_motion_vector,1); SBIT(34,h263rh->syntax_based_arithmetic,1); SBIT(35,h263rh->advanced_prediction,1); SBIT(36,h263rh->hmv1,7); SBIT(43,h263rh->vmv1,7); SBIT(50,h263rh->hmv2,7); SBIT(57,h263rh->vmv2,7); } void copy_headerA_to_buf(h263rtpheader_A *h263rh,u_char *bp) { memset(bp,0,4); SBIT(0,0,1); SBIT(1,h263rh->pbframes,1); SBIT(2,h263rh->sbit,3); SBIT(5,h263rh->ebit,3); SBIT(8,h263rh->srcformat,3); SBIT(11,h263rh->picture_coding_type,1); SBIT(12,h263rh->unrestricted_motion_vector,1); SBIT(13,h263rh->syntax_based_arithmetic,1); SBIT(15,h263rh->reserved,4); SBIT(19,h263rh->dbq,2); SBIT(21,h263rh->trb,3); SBIT(24,h263rh->tr,8); } int split_h263stream( u_char *bs, /* bitstream [in] */ u_int bitcount, /* bitstream length in bits [in] */ u_int gobs_per_frame, /* gobs per frame [in] */ u_int mbs_per_gob, /* mbs per gob [in] */ int *mbind, /* macroblock indices [in] */ int *mbquant, /* quantifiers [in] */ MVField mvfield, /* motion vectors [in] */ u_int ts_, /* timestamp [in] */ int headersize, /* headerlength [in] */ h263_rtp_packet **packets /* rtp packets [out] */ ) { h263streamheader h263sh; int i,sendmodeb,plen,lastgobind,lastsentbit,curind; int lastind,psize=headersize-HDRSIZE_B,nrofrtps=0; copy_buf_to_streamheader(bs,&h263sh); *packets = NULL;lastsentbit=0;curind=0;sendmodeb=0; while (lastsentbitheadersize = HDRSIZE_B; /* fill in header stuff */ h263rhb.ftype = 1; /* mode b */ h263rhb.pbframes = 0; /* no pb frames */ h263rhb.srcformat = h263sh.srcformat; assert(h263rhb.srcformat); h263rhb.picture_coding_type = h263sh.picture_coding_type; h263rhb.unrestricted_motion_vector= h263sh.unrestricted_motion_vector; h263rhb.syntax_based_arithmetic= h263sh.syntax_based_arithmetic; h263rhb.advanced_prediction = h263sh.advanced_prediction; h263rhb.reserved = 0; h263rhb.quant = 0; h263rhb.hmv2 = 0; h263rhb.vmv2 = 0; h263rhb.gobn = gobs_per_frame-1; if (sendmodeb) { /* Motion vectors/mba are only relevant * if the packet before was modeB too */ h263rhb.mba = lastind % mbs_per_gob; h263rhb.hmv1 = mvfield.mx[lastind]; h263rhb.vmv1 = mvfield.my[lastind]; h263rhb.quant = mbquant[lastind]; /* look if we can split at a GOB */ lastgobind = -1; for (i=0;i<=gobs_per_frame;i++) if (mbind[i*mbs_per_gob]lastsentbit) { /* got (at least) one GOB. */ sendmodeb = 0; } else { /* no GOB end in this block(again) * look for maximum number of fitting * macroblocks */ lastgobind = -1; for (i=lastind;(i<=mbs_per_gob*gobs_per_frame) && (mbind[i]lastsentbit); } sendmodeb = 1; lastind = i; } } else { h263rhb.mba = 0; h263rhb.quant = 0; h263rhb.hmv1 = 0; h263rhb.vmv1 = 0; for ( i=0 ; (i<=mbs_per_gob*gobs_per_frame) && (mbind[i]header); plen = ((lastgobind+7)>>3)-(lastsentbit>>3); assert(plen>0); assert(plen<=psize); assert(lastsentbit!=lastgobind); curpacket->datasize = plen; curpacket->data = bs+(lastsentbit>>3); lastsentbit = lastgobind; } else { h263rtpheader_A h263rh; curpacket->headersize = HDRSIZE_A; h263rh.ftype = 0; /*only mode a*/ h263rh.pbframes = 0; /*no pb frames*/ h263rh.srcformat = h263sh.srcformat; assert(h263rh.srcformat); h263rh.picture_coding_type = h263sh.picture_coding_type; h263rh.unrestricted_motion_vector= h263sh.unrestricted_motion_vector; h263rh.syntax_based_arithmetic = h263sh.syntax_based_arithmetic; h263rh.advanced_prediction = h263sh.advanced_prediction; h263rh.reserved = 0; h263rh.dbq = h263sh.dbq; h263rh.trb = h263sh.trb; h263rh.tr = h263sh.tr; h263rh.sbit = lastsentbit&7; h263rh.ebit = 7-((lastgobind-1) &7); copy_headerA_to_buf(&h263rh,curpacket->header); plen = ((lastgobind+7)>>3)-(lastsentbit>>3); assert(plen>0); assert(lastgobind>lastsentbit); assert(plen<=psize); curpacket->data = bs+(lastsentbit>>3); curpacket->datasize = plen; lastsentbit = lastgobind; sendmodeb = 0; } } return nrofrtps; }