Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

502 lines
14 KiB

/*
転送管理クラス
(NP2) Sachiko Yasukawa
*/
#include "stdafx.h"
#include "includes.h"
#include "classlib.h"
#ifdef TEST
IMBoardListItem *pbuffers1[20];
IMBoardListItem *pbuffers2[20];
#endif
#define ISSETDMABUFFER (m_LinerAdd == NULL) ? FALSE : ((m_PhysAdd == NULL) ? FALSE : ((m_DMABufferSize == 0) ? FALSE : TRUE))
#define ISENDTRANSFERINIT (m_pStreamObject == NULL) ? FALSE : TRUE
BOOL CTransfer::Init( void )
{
m_pStreamObject = NULL;
m_DMABufferSize = 0;
m_pTopEventList = NULL;
m_pLastEventList = NULL;
m_pTopQueuedMPEGBuffer = NULL;
m_pLastQueuedMPEGBuffer = NULL;
m_pNextTransferMPEGBuffer = NULL;
m_TopPagePoint = 1;
m_LastPagePoint = 1;
//デバッグ用
BufCount = 0;
StreamCount = 0;
return TRUE;
};
//デストラクタ もし作ったバッファが残っていたら解放する
CTransfer::~CTransfer()
{
CTransferStreamList *pDeleteStreamList;
for( ;m_pStreamObject; ){
pDeleteStreamList = m_pStreamObject;
m_pStreamObject = (CTransferStreamList *)m_pStreamObject->GetNext();
delete pDeleteStreamList;
//デバッグ用
StreamCount--;
}
ASSERT(StreamCount == 0);
// DBG_PRINTF(("CLASSLIB:StreamCount = %d\n", StreamCount));
}
//イベントオブジェクトをセットする。
BOOL CTransfer::SetSink(IMPEGBoardEvent *pEvent)
{
ASSERT(pEvent);
// 受け取ったイベントオブジェクトのNextを初期化
pEvent->SetNext( NULL );
//きっと一個しかないよ。
//イベントリストに追加する
if(m_pTopEventList == NULL)
m_pTopEventList = m_pLastEventList = (IMBoardListItem *)pEvent;//ここはキャストし直し
else{
m_pLastEventList->SetNext((IMBoardListItem *)pEvent);//ここはキャストし直し
m_pLastEventList = (IMBoardListItem *)pEvent;//ここはキャストし直し
}
return TRUE;
}
//イベントオブジェクトを削除する。Add by Nakamura
BOOL CTransfer::UnSetSink(IMPEGBoardEvent *pEvent)
{
ASSERT(pEvent);
//イベントリストから削除する。
// イベントリストが存在しない場合は、エラー
if(m_pTopEventList == NULL || m_pLastEventList == NULL )
return FALSE;
// 1つしか登録されていない場合
if( m_pTopEventList == pEvent && m_pLastEventList == pEvent )
{
m_pTopEventList = m_pLastEventList = NULL;
return TRUE;
};
// 2つ以上登録されていて、先頭のオブジェクトを削除使用とする場合
if( m_pTopEventList == pEvent && m_pLastEventList != pEvent )
{
m_pTopEventList = m_pTopEventList->GetNext();
return TRUE;
};
// 2つ以上登録されていて、2つ目以降を削除しようとしている場合
IMBoardListItem *pTmpEvent;
for( pTmpEvent = m_pTopEventList; pTmpEvent != NULL; pTmpEvent = pTmpEvent->GetNext() )
{
// リスト上の削除対象イベントオブジェクトと同じか?
if( pTmpEvent->GetNext() == pEvent )
{
// 削除しようとしているオブジェクトが、最後である場合
if( pTmpEvent->GetNext() == m_pLastEventList )
m_pLastEventList = pTmpEvent;
// リストの張りなおし
pTmpEvent->SetNext( pTmpEvent->GetNext()->GetNext() );
return TRUE;
};
};
DBG_PRINTF(("CLASSLIB: CALLED CTransfer::UnSetSinkError!!!\n"));
DBG_BREAK();
return FALSE;
}
//DMABufferを設定する。
BOOL CTransfer::SetDMABuffer(DWORD size, BYTE* LinerAdd, BYTE *PhysAdd)
{
ASSERT(LinerAdd);
ASSERT(PhysAdd);
/*
if(!ISENDTRANSFERINIT)
return MBC_NOTINITIALIZE;
m_LinerAdd = LinerAdd;
m_PhysAdd = PhysAdd;
m_DMABufferSize = size;
*/
return TRUE;
}
//Queueに入ってないものをいれる。
BOOL CTransfer::EnQueue( IMPEGBuffer *pBuffer )
{
ASSERT( pBuffer != NULL );
pBuffer->SetNext( NULL );
//転送すべきバッファに追加
if(m_pTopQueuedMPEGBuffer == NULL){
m_pTopQueuedMPEGBuffer = m_pLastQueuedMPEGBuffer = m_pNextTransferMPEGBuffer = pBuffer;
m_TopPagePoint = 1;
m_LastPagePoint = 1;
// DBG_PRINTF(("CLASSLIB: m_pTopQueuedTOPMPEGBuffer = 0x%X\n", (DWORD)m_pTopQueuedMPEGBuffer));
// DBG_PRINTF(("CLASSLIB: m_pLastQueuedTOPMPEGBuffer = 0x%X\n", (DWORD)m_pLastQueuedMPEGBuffer));
// DBG_PRINTF(("CLASSLIB: PageSize = %d\n", pBuffer->GetPageNum()));
}
else{
m_pLastQueuedMPEGBuffer->SetNext(pBuffer);
m_pLastQueuedMPEGBuffer = pBuffer;
if( m_pNextTransferMPEGBuffer == NULL )
{
m_pNextTransferMPEGBuffer = m_pLastQueuedMPEGBuffer;
m_LastPagePoint = 1;
};
// DBG_PRINTF(("CLASSLIB: m_pTopQueuedTOPMPEGBuffer = 0x%X\n", (DWORD)m_pTopQueuedMPEGBuffer));
// DBG_PRINTF(("CLASSLIB: m_pLastQueuedTOPMPEGBuffer = 0x%X\n", (DWORD)m_pLastQueuedMPEGBuffer));
// DBG_PRINTF(("CLASSLIB: PageSize = %d\n", pBuffer->GetPageNum()));
}
// DBG_PRINTF(("CLASSLIB: CALLED CTransfer::EnQueue\n"));
if(!ISENDTRANSFERINIT){
DBG_PRINTF(("CLASSLIB:CTRANSFER::ENQUEUE:NOT INTIALIZE CTRANSFER\n"));
DBG_BREAK();
return FALSE;
}
return TRUE;
}
//Queueからとりだして転送する
BOOL CTransfer::DeQueue()
{
DWORD PageNum;
CBaseStream *pStream;
CTransferStreamList *pStreamList;
IHALStreamControl *pHALStream;
DWORD pLinear, pPhys, Flag;
int BufSize;
// DBG_PRINTF(("CLASSLIB: CALLED CTransfer::DeQueue\n"));
if(!ISENDTRANSFERINIT){
DBG_PRINTF(("CLASSLIB:CTRANSFER::DEQUEUE:NOT INTIALIZE CTRANSFER\n"));
DBG_BREAK();
return FALSE;
}
//pStream = m_pStreamObject->GetBaseStrem();
//DMAバッファをつかう場合の処理
if(ISSETDMABUFFER){
}
//DMAバッファを使わない場合の処理
else{
for(pStreamList = m_pStreamObject; pStreamList; pStreamList = (CTransferStreamList *)pStreamList->GetNext()){
pStream = pStreamList->GetBaseStream();
ASSERT(pStream);
pHALStream = pStream->GetHALStreamControl();
ASSERT(pHALStream);
DWORD QueueNum;
HALRESULT st;
DWORD Count;
//変換されてリストに入ってるバッファを実際にデータ転送
if((st = pHALStream->GetAvailableQueue( &QueueNum )) != HAL_SUCCESS){
_RPT0(_CRT_WARN, "CAN'T GETAVAILABLEQUEUE\n");
DBG_PRINTF(("CLASSLIB:CTransfer::DeQueue:CAN'T GETAVAILABLEQUEUE\n"));
DBG_BREAK();
return FALSE;
}
for(Count = 0; Count < QueueNum ; Count++){
IMPEGBuffer *pBuffer = NULL;
if( GetNextTransferPoint( &pBuffer, &PageNum ) == FALSE )
return TRUE;
if(!pBuffer->GetPagePointer(PageNum, &pLinear, &pPhys)){
return FALSE;
}
//CClassLibBufferを作るためにサイズを取得
BufSize = pBuffer->GetPageSize(PageNum);
//CClassLibBufferを作るためにflagを取得
if(PageNum == 1)
Flag = pBuffer->GetBufferFlag();
else
Flag = 0; //ここはコーディングし直す
//新しいバッファ管理クラスを作る
CClassLibBuffer *pBuf = m_Mem.Alloc(pBuffer, pStream, PageNum, BufSize, pPhys, pLinear, Flag);//データを設定
if(!pBuf){
_RPTF0(_CRT_WARN, "CAN'T New");
DBG_PRINTF(("CLASSLIB:CTRANSFER::ENQUEUE:CAN'T NEW\n"));
DBG_BREAK();
return FALSE;
}
//デバッグ用
BufCount++;
// DBG_PRINTF(("CLASSLIB: Dequeue: Senddata(%d) pBuffer = 0x%X IMPEGBuff=0x%x\n", BufCount, (DWORD)pBuf,pBuffer ));
if((st = pHALStream->SendData(pBuf)) != HAL_SUCCESS){
_RPT0(_CRT_WARN, "CAN'T SENDDATA TO HAL\n");
DBG_PRINTF(("CLASSLIB:CTransfer::DeQueue:CAN'T SENDDATA TO HAL\n"));
DBG_BREAK();
return FALSE;
}
}
}
}
return TRUE;
}
//Transferオブジェクトにストリームを追加する。
BOOL CTransfer::AddStreamObject(IBaseStream *INewStreamObject)
{
//CBaseStream *pBSt1, *pBSt2;
CTransferStreamList *pNewTransferStreamList, *pStreamList;
ASSERT(INewStreamObject);
//378742 PNPBOOT: tosdvd03 leaks 1 page of memory on unload.
// pNewTransferStreamList = new CTransferStreamList((CBaseStream *)INewStreamObject);
m_pNewTransferStreamList.Init( (CBaseStream *)INewStreamObject );
pNewTransferStreamList = &m_pNewTransferStreamList;
//
if(!pNewTransferStreamList){
DBG_PRINTF(("CLASSLIB:CTRANSFER::AddStreamObject:CAN'T NEW\n"));
DBG_BREAK();
return FALSE;
}
//デバッグ用
StreamCount++;
//まだ一つもストリームが追加されていない。
if(m_pStreamObject == NULL){
m_pStreamObject = pNewTransferStreamList;
//pBSt1 = m_pStreamObject->GetBaseStream();
//pHALStream = m_pBSt1->GetHALStreamControl();
m_pIHAL = m_pStreamObject->GetBaseStream()->GetClassLibHAL();
m_EndOfTransferEvent.SetEventType(ClassLibEvent_SendData);
m_EndOfTransferEvent.SetTransfer(this);
m_pIHAL->SetSinkClassLib((IMPEGBoardEvent *)/*(CClassLibEvent *)*/&m_EndOfTransferEvent);
}
//新しいストリームを追加
else{
//pBSt1 = pNewTransferStreamList;
for(pStreamList = m_pStreamObject; pStreamList->GetNext() != NULL; pStreamList = (CTransferStreamList *)pStreamList->GetNext());
pStreamList->SetNext((IMBoardListItem *)pNewTransferStreamList);
}
return TRUE;
}
//Transferオブジェクトからストリームを解放する。
BOOL CTransfer::ReleaseStreamObject(IBaseStream *IStreamObject)
{
CTransferStreamList *pStreamList, *pNextStreamList;
CBaseStream *pBaseStream;
ASSERT(IStreamObject);
//解放すべきストリームがないのでエラー
if(m_pStreamObject == NULL){
_RPTF0(_CRT_WARN, "CTransfer:THERE IS NO STREAM WHICH SHOULD BE RELEASED\n");
DBG_PRINTF(("CLASSLIB:CTRANSFER::ReleaseStreamObject:THERE IS NO STREAM WHICH SHOULD BE RELEASED\n"));
DBG_BREAK();
return FALSE;
}
else{
for(pStreamList = m_pStreamObject; ; pStreamList = (CTransferStreamList *)pStreamList->GetNext()){
if((pNextStreamList = (CTransferStreamList *)pStreamList->GetNext()) == NULL){
_RPTF0(_CRT_WARN, "CTransfer:THERE IS SUCH A STREAM WHICH SHOULD BE RELEASED\n");
DBG_PRINTF(("CLASSLIB:CTRANSFER::ReleaseStreamObject:THERE IS SUCH A STREAM WHICH SHOULD BE RELEASED\n"));
DBG_BREAK();
return FALSE;
}
if((pBaseStream = (CBaseStream *)pNextStreamList->GetBaseStream()) == (CBaseStream *)IStreamObject){
break;
}
ASSERT(pBaseStream);
}
pStreamList->SetNext(pNextStreamList->GetNext());
//378742 PNPBOOT: tosdvd03 leaks 1 page of memory on unload.
// delete pNextStreamList;
//
//デバッグ用
StreamCount--;
}
return TRUE;
}
//Queueをフラッシュする。
void CTransfer::Flush()
{
CTransferStreamList *pStreamList;
CBaseStream *pBaseStream;
IMPEGBoardEvent *pEvent;
DBG_PRINTF(("CLASSLIB:Before flash BufCount = %d\n", BufCount));
m_Mem.Flush();
BufCount=0;
for(pStreamList = m_pStreamObject; pStreamList; pStreamList = (CTransferStreamList *)pStreamList->GetNext()){
pBaseStream = pStreamList->GetBaseStream();
DWORD PageNum;
ASSERT(pBaseStream);
IMPEGBuffer *pBuffer = NULL;
BOOL NeedAdvice = FALSE;
// StreamがQueueに持っているバッファをすべて、転送中にマークする。
while( TRUE )
{
if( GetNextTransferPoint( &pBuffer, &PageNum ) == FALSE )
break;
}
while( HasQueuedBuffer() == TRUE )
{
NeedAdvice = FreeTopTransferPoint(&pBuffer);
if( NeedAdvice == TRUE )
{
for(pEvent = (IMPEGBoardEvent *)m_pTopEventList; pEvent != NULL;pEvent = (IMPEGBoardEvent *)((IMBoardListItem *)pEvent)->GetNext())
{
if((/*(CClassLibEvent *)*/pEvent)->GetEventType() == ClassLibEvent_SendData){
//MPEGBufferの先頭をひとつうしろにずらす
//Wrapperにもう使い終わったことを知らせる
pEvent->Advice(pBuffer);
}
}
};
}
}
DBG_PRINTF(("CLASSLIB:After flush BufCount = %d\n", BufCount));
ASSERT( BufCount == 0 );
}
//データ転送終了の処理
BOOL CTransfer::EndOfTransfer(CClassLibBuffer *pBuffer)
{
IMPEGBoardEvent *pEvent;
CBaseStream *pStream;
CTransferStreamList *pStreamList;
// DBG_PRINTF(("CLASSLIB: EndOfTransfer(%d) pBuffer = 0x%X\n", BufCount, (DWORD)pBuffer));
// DBG_PRINTF(("CLASSLIB: pBuffer->GetIMPEGBuffer() = 0x%X\n", (DWORD)pBuffer->GetIMPEGBuffer()));
ASSERT(pBuffer);
pStream = pBuffer->GetStream();
ASSERT(pStream);
IMPEGBuffer *pFree = NULL;
if( FreeTopTransferPoint(&pFree) == TRUE )
{
// DBG_PRINTF(("CLASSLIB: Free IMPEGBuffer() = 0x%X\n", (DWORD)pFree ));
ASSERT( pFree == pBuffer->GetIMPEGBuffer() );
//Wrapperから渡されたバッファの最後のページならバッファー開放
for(pEvent = (IMPEGBoardEvent *)m_pTopEventList; pEvent != NULL;pEvent = (IMPEGBoardEvent *)((IMBoardListItem *)pEvent)->GetNext()){
if(pEvent->GetEventType() == ClassLibEvent_SendData){
//Wrapperにもう使い終わったことを知らせる
// DBG_PRINTF(("CLASSLIB: EndOfTransfer Advice Buffer = 0x%X\n", pBuffer->GetIMPEGBuffer() ));
pEvent->Advice(pBuffer->GetIMPEGBuffer());
}
}
}
//リストからはずしたCClassLibBufferを解放
m_Mem.Free(pBuffer);
//デバッグ用
BufCount--;
ASSERT(BufCount>=0);
//STOP状態のときにHALに対してSendDataしない
for(pStreamList = m_pStreamObject; pStreamList; pStreamList = (CTransferStreamList *)pStreamList->GetNext()){
pStream = pStreamList->GetBaseStream();
ASSERT(pStream);
if(pStream->GetState() == Stop)
return TRUE;
}
if(DeQueue() == FALSE){
DBG_PRINTF(("CLASSLIB:CTRANSFER::EndOfTransfer:CAN'T DEQUEUE\n"));
DBG_BREAK();
return FALSE;
}
return TRUE;
}
BOOL CTransfer::HasQueuedBuffer( void )
{
if( m_pTopQueuedMPEGBuffer == NULL )
return FALSE;
return TRUE;
};
BOOL CTransfer::GetNextTransferPoint( IMPEGBuffer **Point, DWORD *Page )
{
if( m_pNextTransferMPEGBuffer == NULL )
{
*Point = NULL;
*Page = 0;
return FALSE;
};
*Point = m_pNextTransferMPEGBuffer;
*Page = m_LastPagePoint;
if( m_pNextTransferMPEGBuffer->GetPageNum() == m_LastPagePoint )
{
m_pNextTransferMPEGBuffer = (IMPEGBuffer *)m_pNextTransferMPEGBuffer->GetNext();
m_LastPagePoint = 1;
return TRUE;
};
m_LastPagePoint ++;
return TRUE;
};
BOOL CTransfer::FreeTopTransferPoint( IMPEGBuffer **Free )
{
ASSERT( m_pTopQueuedMPEGBuffer != NULL );
if( m_pTopQueuedMPEGBuffer == NULL
|| ( m_pTopQueuedMPEGBuffer == m_pNextTransferMPEGBuffer && m_LastPagePoint == m_TopPagePoint ) )
{
*Free = NULL;
return FALSE;
};
if( m_TopPagePoint == m_pTopQueuedMPEGBuffer->GetPageNum() )
{
*Free = m_pTopQueuedMPEGBuffer;
m_pTopQueuedMPEGBuffer = (IMPEGBuffer *)m_pTopQueuedMPEGBuffer->GetNext();
m_TopPagePoint = 1;
return TRUE; // Need Advice
};
*Free = NULL;
m_TopPagePoint ++;
return FALSE; // Not Need Advice
};
//HALによんでもらいたい
void CClassLibEvent::Advice(PVOID pBuffer)
{
ASSERT(m_pTransfer);
m_pTransfer->EndOfTransfer((CClassLibBuffer *)pBuffer);
}