503 lines
14 KiB
C++
503 lines
14 KiB
C++
/*
|
||
転送管理クラス
|
||
(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);
|
||
}
|