/* 転送管理クラス (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); }