www.pudn.com > mediator15src.zip > StateManager.cpp


/* 
 * StateManager.cpp 
 * Copyright (C) 2002 Arno Hornberger  
 * Original Version Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com 
 * 
 * This file is part of MPEG Mediator, a free MPEG stream converter. 
 * 
 * MPEG Mediator is free software; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version. 
 * 
 * MPEG Mediator is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */ 
 
#include "StateManager.h" 
 
bool CStateManager::GetFromMemoryBlock(PBYTE block) 
{ 
  TStateHeader *hdr; 
	PBYTE tmp; 
 
  if (!block) 
    return false; 
 
  hdr = (TStateHeader *)block; 
  if (hdr->Mark != AVI_BLOCK_MARK) 
    return false; 
 
	tmp = new BYTE[hdr->blockSize]; 
	if (!tmp) 
		return false; 
	 
//  if (hdr->blockSize >= MAX_BLOCK_SIZE) 
//    return false; 
 
  if (m_pBuf) 
    delete []m_pBuf; 
 
  m_pBuf = tmp; 
  memcpy(m_pBuf, block, hdr->blockSize); 
 
  return true; 
} 
 
bool CStateManager::GetStatePos(DWORD fccHandler, int *pos) 
{ 
  PBYTE pBlock = m_pBuf; 
 
	// fccCode 
	// statesize (excluding fccCode and statesize itself) 
	// statedata 
	// fccCode 
	// .... 
 
  if (!m_pBuf) 
    return false; 
 
  // state data starts after header and WFX 
  int dataToCheck = GetBlockSize() - GetWfxSize() - GetHeaderSize(); 
  pBlock += GetHeaderSize() + GetWfxSize(); 
  *pos = -1; 
 
  while (dataToCheck >= 8) 
  { 
    if (*((DWORD *)pBlock) == fccHandler) 
    { 
      *pos = GetBlockSize() - dataToCheck; 
      break; 
    } 
    // skip fccHandler 
    pBlock += 4; 
    int stateSize = *((int *)pBlock); 
    // skip stateSize 
    pBlock += 4; 
    // skip state 
    pBlock += stateSize; 
    dataToCheck -= stateSize; 
  } 
   
  return *pos > 0; 
} 
 
bool CStateManager::GetState(DWORD fccHandler, PBYTE *pBlock, int *blockSize) 
{ 
  int statePos; 
 
  if (GetStatePos(fccHandler, &statePos)) 
  { 
    // statePos marks to the fccHandler 
    // skip the fccHandler and size 
    *blockSize = *(int *)(m_pBuf + statePos + 4); 
    statePos += 8; 
    // Get the state size 
    *pBlock = m_pBuf + statePos; 
    return true; 
  } 
  else 
    return false; 
} 
 
bool CStateManager::SetToMemoryBlock(PBYTE block) 
{ 
	if (!block || !m_pBuf) 
		return false; 
   
  memcpy(block, m_pBuf, GetBlockSize()); 
  return true; 
} 
 
bool CStateManager::SetWfx(WAVEFORMATEX *wfx, int wfxSize) 
{ 
	int statesize; 
   
	if (!m_pBuf) 
    Reset(); 
 
	statesize = GetBlockSize() - GetHeaderSize() - GetWfxSize();  
 
  PBYTE newBlock = new BYTE[GetBlockSize() - GetWfxSize() + wfxSize]; 
 
	memcpy(newBlock, m_pBuf, GetHeaderSize()); 
 
  if (wfxSize)  
    memcpy(newBlock + GetHeaderSize(), wfx, wfxSize); 
 
	// copy state data for each codec 
  memcpy(newBlock + GetHeaderSize() + wfxSize, 
				 m_pBuf + GetHeaderSize() + GetWfxSize(), 
				 statesize); 
	 
  delete []m_pBuf; 
  m_pBuf = newBlock; 
 
  SetBlockSize(statesize + GetHeaderSize() + wfxSize); 
  SetWfxSize(wfxSize); 
 
  return true; 
} 
 
void CStateManager::Reset() 
{ 
  if (m_pBuf) 
    delete []m_pBuf; 
 
  m_pBuf = new BYTE[sizeof(TStateHeader)]; 
  ((TStateHeader *)m_pBuf)->Mark = AVI_BLOCK_MARK; 
  ((TStateHeader *)m_pBuf)->blockSize = GetHeaderSize(); 
  ((TStateHeader *)m_pBuf)->wfxSize = 0; 
  ((TStateHeader *)m_pBuf)->fccHandler = 0; 
  ((TStateHeader *)m_pBuf)->lQuality = 100; 
  ((TStateHeader *)m_pBuf)->lKeyRate = 0; 
  ((TStateHeader *)m_pBuf)->lDataRate = 0; 
  ((TStateHeader *)m_pBuf)->hadid = 0; 
  ((TStateHeader *)m_pBuf)->HQAudioCompression = true; 
} 
 
bool CStateManager::SetState(DWORD fccHandler, PBYTE block, int blockSize) 
{ 
  int statePos; 
 
  if (!m_pBuf) 
    Reset(); 
 
  if (m_pBuf) 
  { 
    if (GetStatePos(fccHandler, &statePos)) 
    { 
      // we have a state for this format. Delete it. 
      // statePos marks to the fccHandler 
      // Get the state size 
      int stateSize = *((int *)(m_pBuf + statePos + 4)); 
 
			// prepare a new memory block 
      PBYTE newBlock = new BYTE[GetBlockSize() - stateSize - 8]; 
 
      // copy all states up to the one we want to delete 
      memcpy(newBlock, m_pBuf, statePos); 
			memcpy(newBlock + statePos, m_pBuf + statePos + stateSize + 8, 
						 GetBlockSize() - statePos - stateSize - 8); 
       
      delete []m_pBuf; 
      m_pBuf = newBlock; 
 
      SetBlockSize(GetBlockSize() - stateSize - 8); 
    } 
 
    PBYTE newBlock = new BYTE[GetBlockSize() + blockSize + 8]; 
    memcpy(newBlock, m_pBuf, GetBlockSize()); 
 
    // create new state 
    *(DWORD *)(newBlock + GetBlockSize()) = fccHandler; 
    *(int *)(newBlock + GetBlockSize() + 4) = blockSize; 
 
    // copy new state 
    memcpy(newBlock + GetBlockSize() + 8, block, blockSize); 
 
    // swap blocks 
    // delete actual 
    delete []m_pBuf; 
    m_pBuf = newBlock; 
     
    SetBlockSize(GetBlockSize() + blockSize + 8); 
     
    return true; 
  } 
  else 
    return false; 
}