⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bitstrm.cpp

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 CPP
字号:
/*************************************************************************

This software module was originally developed by 

	Ming-Chieh Lee (mingcl@microsoft.com), Microsoft Corporation
	Wei-ge Chen (wchen@microsoft.com), Microsoft Corporation
	Bruce Lin (blin@microsoft.com), Microsoft Corporation
	Chuang Gu (chuanggu@microsoft.com), Microsoft Corporation
	(date: March, 1996)

and edited by
	Yoshihiro Kikuchi (TOSHIBA CORPORATION)
	Takeshi Nagai (TOSHIBA CORPORATION)
	Toshiaki Watanabe (TOSHIBA CORPORATION)
	Noboru Yamaguchi (TOSHIBA CORPORATION)

in the course of development of the MPEG-4 Video (ISO/IEC 14496-2). 
This software module is an implementation of a part of one or more MPEG-4 Video tools 
as specified by the MPEG-4 Video. 
ISO/IEC gives users of the MPEG-4 Video free license to this software module or modifications 
thereof for use in hardware or software products claiming conformance to the MPEG-4 Video. 
Those intending to use this software module in hardware or software products are advised that its use may infringe existing patents. 
The original developer of this software module and his/her company, 
the subsequent editors and their companies, 
and ISO/IEC have no liability for use of this software module or modifications thereof in an implementation. 
Copyright is not released for non MPEG-4 Video conforming products. 
Microsoft retains full right to use the code for his/her own purpose, 
assign or donate the code to a third party and to inhibit third parties from using the code for non MPEG-4 Video conforming products. 
This copyright notice must be included in all copies or derivative works. 

Copyright (c) 1996, 1997.

Module Name:
	
	bitstrm.cpp

Abstract:

	Classes for bitstream I/O.

Revision History:

*************************************************************************/

#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include "typeapi.h"
#include "bitstrm.hpp"
#include "inbits.h"


#ifdef __MFC_
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

#define new DEBUG_NEW				   
#endif // __MFC_

UInt getbit (UInt data, UInt position, UInt num) // get the num-bit field of x starting from position p
{
	return ((data >> (position + 1 - num)) & ~(~0 << num));
}

Void print_bit (UInt x, UInt num, UInt startPos) // print num bits starting from startPos
{
	for (Int k = 0; k <= (Int) (num - startPos); k++) {
		UInt y = getbit (x, num, 1);
		printf ("%u ", y);
		x = x << 1;
	}
	printf ("\n");
}


unsigned int bit_msk[33] =
{
  0x00000000, 0x00000001, 0x00000003, 0x00000007,
  0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
  0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
  0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
  0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
  0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
  0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
  0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
  0xffffffff
};


COutBitStream::COutBitStream (Char* pchBuffer, Int iBitPosition, ostream* pstrmTrace) : 
	m_pstrmTrace (pstrmTrace),
	m_chEncBuffer (0),
	m_uEncNumEmptyBits (8)
{
	assert (iBitPosition < 8);
	assert (iBitPosition >= 0);
	m_iBitPosition = iBitPosition;
	m_pchBuffer = pchBuffer;
	m_lCounter = 0;
	m_pchBufferRun = m_pchBuffer;
	m_iBuffer = 0;
// Added for Data Partitioning mode by Toshiba(1998-1-16)
	m_bDontSendBits = FALSE;
// End Toshiba(1998-1-16)
}
 

Void COutBitStream::reset ()		//but keep the byte buffer
{
//	m_uEncNumEmptyBits = 8;
//	m_chEncBuffer = 0;
	m_pchBufferRun = m_pchBuffer;
	m_iBuffer = 0;
}

Void COutBitStream::resetAll ()
{
	m_iBitPosition = 0;
	m_lCounter = 0;
	m_uEncNumEmptyBits = 8;
	m_chEncBuffer = 0;
	m_pchBufferRun = m_pchBuffer;
	m_iBuffer = 0;
}

Void COutBitStream::setBookmark ()
{
	bookmark (1);
}

Void COutBitStream::gotoBookmark ()
{
	bookmark (0);
}

Void COutBitStream::bookmark (Bool bSet)
{
	static Bool bBookmarkOn = FALSE;
	static Int iBitPosition;
	static Int lCounter;
	static UInt uEncNumEmptyBits;
	static U8 chEncBuffer;
	static Char* pchBufferRun;
	static Int iBuffer;

	if (bSet) {
		iBitPosition = m_iBitPosition;
		lCounter = m_lCounter;
		uEncNumEmptyBits = m_uEncNumEmptyBits;
		chEncBuffer = m_chEncBuffer;
		pchBufferRun = m_pchBufferRun;
		iBuffer = m_iBuffer;
		bBookmarkOn = TRUE;
	}
	else {
		m_iBitPosition = iBitPosition;
		m_lCounter = lCounter;
		m_uEncNumEmptyBits = uEncNumEmptyBits;
		m_chEncBuffer = chEncBuffer;
		m_pchBufferRun = pchBufferRun;
		m_iBuffer = iBuffer;
		bBookmarkOn = FALSE;
	}
}

Void COutBitStream::putBitsC (Char cBits,Int iNOfBits)
{
	putBits ((Int) cBits, (UInt) iNOfBits); 
}


Void COutBitStream::putBits (Int data, UInt numBits, const Char* rgchSymbolName)
{	
	assert (numBits < 100);				//usually not that large
	if (numBits == 0) return;

// Added for Data Partitioning mode by Toshiba(1998-1-16)
	if(m_bDontSendBits) return;
// End Toshiba(1998-1-16)

#ifdef __TRACE_AND_STATS_
	if (m_pstrmTrace != NULL && rgchSymbolName != NULL)	{
		Char* rgchBinaryForm = new Char [numBits + 1];
		assert (rgchBinaryForm != NULL);
		m_pstrmTrace->width (20);
		(*m_pstrmTrace) << rgchSymbolName << ": ";
		Int iMask = 0xFFFFFFFF;
		iMask = iMask << numBits;
		iMask = ~iMask;
		Int iCleanData = data & iMask;
		//_itoa (iCleanData, rgchBinaryForm, 2);	// win32 only
		Int iBit;
		iMask = 0x00000001;
		for (iBit = (Int) numBits - 1; iBit >= 0; iBit--)	{
			rgchBinaryForm [iBit] = ((iCleanData & iMask) == 0) ? '0' : '1';
			iMask = iMask << 1;
		}
		rgchBinaryForm [numBits] = '\0';
		m_pstrmTrace->width (numBits);
		m_pstrmTrace->fill ('0');
		(*m_pstrmTrace) << rgchBinaryForm;
		m_pstrmTrace->fill (' ');
		(*m_pstrmTrace) << " @" << m_lCounter << '\n';
		m_pstrmTrace->flush ();
		delete rgchBinaryForm;
	}
#endif // __TRACE_AND_STATS_

	if (m_uEncNumEmptyBits > numBits) {	// not ready to put the data to buffer since it's not full
		m_uEncNumEmptyBits -= numBits;
		Char mskData = (0xFF >> (8 - numBits)) & data; 
		mskData = mskData << m_uEncNumEmptyBits;
		m_chEncBuffer = m_chEncBuffer ^ mskData;
        m_lCounter += numBits;
	}
	else if (m_uEncNumEmptyBits == numBits) { // ready
		Char mskData = (0xFF >> (8 - numBits)) & data; 
		m_chEncBuffer = m_chEncBuffer ^ mskData;
		*m_pchBufferRun++ = m_chEncBuffer;
		m_iBuffer++;
		m_chEncBuffer = 0;
		m_uEncNumEmptyBits = 8;
        m_lCounter += numBits;
	}
	else { // ready, but need to handle the leftover part
		UInt temp = getbit (data, numBits - 1, m_uEncNumEmptyBits);
		numBits -= m_uEncNumEmptyBits; // length of unhandled part
		m_chEncBuffer = m_chEncBuffer ^ temp;
        m_lCounter += m_uEncNumEmptyBits;
		*m_pchBufferRun++ = m_chEncBuffer;
		m_iBuffer++;
		m_chEncBuffer = 0;
		m_uEncNumEmptyBits = 8;
		data = data ^ (temp << numBits);
		putBits (data, numBits);
	}
}


Void COutBitStream::putBits (Char *pBits, Int lNOfBits)
{
    assert(lNOfBits>=0);
    while(lNOfBits>0)
    {
        if(lNOfBits>8)
        {
            putBitsC((Int)(*pBits),8);
            lNOfBits-=8;
            pBits++;
        }
        else
        {
            putBitsC((Int)(*pBits),(UInt)lNOfBits);
            break;
        }
    }
}

Void COutBitStream::putBitStream(COutBitStream &cStrm)
{
	cStrm.m_pchBufferRun[0]=cStrm.m_chEncBuffer >> cStrm.m_uEncNumEmptyBits;
	putBits(cStrm.m_pchBuffer,cStrm.m_lCounter);
}

Int COutBitStream::flush ()
{
	Int nBits = 0;
	if (m_uEncNumEmptyBits != 8) {
		nBits = m_uEncNumEmptyBits;
		putBits ((Int) 0, (UInt) 1);
		putBits ((Int) 0xFFFF, nBits - 1);

/*
		*m_pchBufferRun++ = m_chEncBuffer;
		m_iBuffer++;
		m_lCounter += m_uEncNumEmptyBits;
		nBits = m_uEncNumEmptyBits;
		m_uEncNumEmptyBits = 8;
		m_chEncBuffer = 0;
*/
	}
	else	{
		nBits = 8;
		putBits ((Int) 0x007F, nBits);
	}
	return nBits;
}

Void COutBitStream::trace (const Char* rgchSymbolName)
{
	if (m_pstrmTrace != NULL)	{
		m_pstrmTrace->width (20);
		(*m_pstrmTrace) << rgchSymbolName;
		m_pstrmTrace->flush ();
	}
}

Void COutBitStream::trace (Int iValue, const Char* rgchSymbolName)
{
	if (m_pstrmTrace != NULL)	{
		m_pstrmTrace->width (20);
		(*m_pstrmTrace) << rgchSymbolName << "= ";
		(*m_pstrmTrace) << iValue << "\n";
		m_pstrmTrace->flush ();
	}
}

Void COutBitStream::trace (UInt uiValue, const Char* rgchSymbolName)
{
	if (m_pstrmTrace != NULL)	{
		m_pstrmTrace->width (20);
		(*m_pstrmTrace) << rgchSymbolName << "= ";
		(*m_pstrmTrace) << uiValue << "\n";
		m_pstrmTrace->flush ();
	}
}

Void COutBitStream::trace (Float fltValue, const Char* rgchSymbolName)
{
	if (m_pstrmTrace != NULL)	{
		m_pstrmTrace->width (20);
		(*m_pstrmTrace) << rgchSymbolName << "= ";
		(*m_pstrmTrace) << fltValue << "\n";
		m_pstrmTrace->flush ();
	}
}

#ifndef __DOUBLE_PRECISION_
Void COutBitStream::trace (Double dblValue, const Char* rgchSymbolName)
{
	if (m_pstrmTrace != NULL)	{
		m_pstrmTrace->width (20);
		(*m_pstrmTrace) << rgchSymbolName << "= ";
		(*m_pstrmTrace) << dblValue << "\n";
		m_pstrmTrace->flush ();
	}
}
#endif

Void COutBitStream::trace (const CMotionVector& mvValue, const Char* rgchSymbolName)
{
	if (m_pstrmTrace != NULL)	{
		m_pstrmTrace->width (20);
		(*m_pstrmTrace) << rgchSymbolName << "= ";
		(*m_pstrmTrace) << mvValue.iMVX + mvValue.iMVX + mvValue.iHalfX << ", ";
		(*m_pstrmTrace) << mvValue.iMVY + mvValue.iMVY + mvValue.iHalfY << "\n ";
		m_pstrmTrace->flush ();
	}
}

Void COutBitStream::trace (const CVector2D& vctValue, const Char* rgchSymbolName)
{
	if (m_pstrmTrace != NULL)	{
		m_pstrmTrace->width (20);
		(*m_pstrmTrace) << rgchSymbolName << "= ";
		(*m_pstrmTrace) << vctValue.x << ", ";
		(*m_pstrmTrace) << vctValue.y << "\n ";
		m_pstrmTrace->flush ();
	}
}

Void COutBitStream::trace (const CSite& stValue, const Char* rgchSymbolName)
{
	if (m_pstrmTrace != NULL)	{
		m_pstrmTrace->width (20);
		(*m_pstrmTrace) << rgchSymbolName << "= ";
		(*m_pstrmTrace) << stValue.x << ", ";
		(*m_pstrmTrace) << stValue.y << "\n ";
		m_pstrmTrace->flush ();
	}
}

Void COutBitStream::trace (const CFloatImage* pfi, const Char* rgchSymbolName, CRct rct)
{
	if (m_pstrmTrace == NULL)
		return;
	Int iValue;
	(*m_pstrmTrace) << rgchSymbolName << "= \n";
	if (rct.valid ())	{
		for (CoordI iY = rct.top; iY < rct.bottom; iY++)	{
			const PixelF* ppxlf = pfi->pixels (rct.left, iY);
			for (CoordI iX = rct.left; iX < rct.right; iX++)	{	
				iValue = (Int) *ppxlf;
				(*m_pstrmTrace) << iValue << " ";
				ppxlf++;
			}
			(*m_pstrmTrace) << "\n";
		}

	}
	else	{
		const PixelF* ppxlf = pfi->pixels ();
		for (CoordI iY = pfi->where ().top; iY < pfi->where ().bottom; iY++)	{
			for (CoordI iX = pfi->where ().left; iX < pfi->where ().right; iX++)	{	
				iValue = (Int) *ppxlf;
				(*m_pstrmTrace) << iValue << " ";
				ppxlf++;
			}
			(*m_pstrmTrace) << "\n";
		}
	}
	m_pstrmTrace->flush ();
}

Void COutBitStream::trace (const Float* ppxlf, UInt cElem, const Char* rgchSymbolName)
{
	if (m_pstrmTrace == NULL)
			return;	
	Int iValue;	
	(*m_pstrmTrace) << rgchSymbolName << ": \n";
	for (UInt iElem = 0; iElem < cElem; iElem++)	{
			iValue = (Int) *ppxlf;
			(*m_pstrmTrace) << iValue << " ";
			ppxlf++;
	}
	(*m_pstrmTrace) << "\n";
	m_pstrmTrace->flush ();
}

Void COutBitStream::trace (const Int* rgi, UInt cElem, const Char* rgchSymbolName)
{
	if (m_pstrmTrace == NULL)
		return;	
	(*m_pstrmTrace) << rgchSymbolName << ": \n";
	for (UInt iElem = 0; iElem < cElem; iElem++)	{
		(*m_pstrmTrace) << *rgi++ << " ";
	}
	(*m_pstrmTrace) << "\n";
	m_pstrmTrace->flush ();
}

Void COutBitStream::trace (const PixelC* rgpxlc, Int cCol, Int cRow, const Char* rgchSymbolName)	//this is for tracing shape buffers
{
	if (m_pstrmTrace == NULL)
		return;	
	(*m_pstrmTrace) << rgchSymbolName << ": \n";
	for (Int iRow = -1; iRow < cRow; iRow++)	{
		for (Int iCol = -1; iCol < cCol; iCol++)	{
			if (iRow == -1)
				(*m_pstrmTrace) << "-";
			else if (iCol == -1)	{
				m_pstrmTrace->width (2);
				(*m_pstrmTrace) << iRow << "|"; 
			}
			else
				(*m_pstrmTrace) << (*rgpxlc++ == MPEG4_OPAQUE); 
		}
		(*m_pstrmTrace) << "\n";		
	}
	m_pstrmTrace->flush ();
}

CInBitStream::CInBitStream (void) 
{
  m_pistrm = -1;
  init();
}

CInBitStream::CInBitStream (int istrm)
{
  m_pistrm = istrm;
  init();
}

CInBitStream::~CInBitStream() 
{
  if (m_pistrm >= 0) {
    free(m_buffer);
  };
}
  
void CInBitStream::init (void) {
  m_bookmark = 0;
  m_buffer = NULL;
  m_framebits = m_framebits_max = 0;
}


uint32_t CInBitStream::getBits (uint32_t numBits)
{
  uint32_t ret = peekBits(numBits);
  flushbits(numBits);
  return ret;
}

int CInBitStream::peekOneBit (uint32_t numBits)
{
  return peekBits(numBits) & 0x1;
}

int CInBitStream::peekBitsTillByteAlign (int &nBitsToPeek)
{
  nBitsToPeek = 8 - m_bitcnt;
  return peekBits(nBitsToPeek);
}

int CInBitStream::peekBitsFromByteAlign (int nBitsToPeek) 
{
  int ret;
  if (nBitsToPeek == 0) return 0;
  setBookmark();
  getBits((uint32_t)8 - m_bitcnt);
  ret = peekBits(nBitsToPeek);
  gotoBookmark();
  return ret;
}

void CInBitStream::bookmark (Bool bSet) 
{
  if (bSet) setBookmark();
  else gotoBookmark();
}


void CInBitStream::read_ifstream_buffer (void)
{
  int left, offset, ret;
  if (m_buffer == NULL) {
    m_buffer = (unsigned char *)malloc(8092);
    m_orig_buflen = read(m_pistrm, m_buffer, 8092);
    m_framebits = 0;
    m_bitcnt = 0;
    m_rdptr = m_buffer;
  } else {
    if (m_bookmark == 0) {
      left = m_orig_buflen - (m_framebits / 8);
      offset = m_orig_buflen - left;
      memmove(m_buffer,
	      m_buffer + offset,
	      left);
      ret = read(m_pistrm, m_buffer + left, m_orig_buflen - left);
      m_orig_buflen = left + ret;
      m_framebits = m_bitcnt;
      m_rdptr = m_buffer;
    } else {
      left = m_orig_buflen - (m_bookmark_framebits / 8);
      offset = m_orig_buflen - left;
      memmove(m_buffer,
	      m_buffer + offset,
	      left);
      ret = read(m_pistrm, m_buffer + offset, m_orig_buflen - left);
      m_orig_buflen = left + ret;
      int framebits_past, rdptr_past;

      framebits_past = m_framebits - m_bookmark_framebits;
      rdptr_past = m_rdptr - m_bookmark_rdptr;
      m_framebits = m_bitcnt + framebits_past;
      m_bookmark_framebits = m_bitcnt;
      m_bookmark_rdptr = m_buffer;
      m_rdptr = m_buffer + rdptr_past;
    }
  }
  m_framebits_max = m_orig_buflen * 8;
}

void CInBitStream::set_buffer (unsigned char *bptr, 
			       uint32_t blen) 
{
  m_buffer = bptr;
  m_rdptr = bptr;
  m_bitcnt = 0;
  m_framebits = 0;
  m_orig_buflen = blen;
  m_framebits_max = blen * 8;
  m_bookmark = 0;
}

Void CInBitStream::flush (int nExtraBits) 
{
  if (m_bitcnt == 0) getBits((uint32_t)nExtraBits);
  if (m_bitcnt != 0)
    flushbits(8 - m_bitcnt);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -