📄 spu_decoder.cpp
字号:
pSPU->ulFieldOffset[1] = ulTemp;
fUpdateBmp = TRUE;
fDecodeBitmap = TRUE;
}
pbPtr += 4;
pSPU->RLE8Bit = 0;
break;
case SET_DSPXA2:
#if DBG_ON(DBG_VERBOSE)
DbgPrint(("SPUDecoderDecodeSPU() -- SET_DSPXA2\n"));
#endif
/* set offset of fields */
ulTemp = MAKE_DWORD(&pbPtr[0]);
if (ulTemp != pSPU->ulFieldOffset[0])
{
pSPU->ulFieldOffset[0] = ulTemp;
fUpdateBmp = TRUE;
fDecodeBitmap = TRUE;
}
ulTemp = MAKE_DWORD(&pbPtr[4]);
if (ulTemp != pSPU->ulFieldOffset[1])
{
pSPU->ulFieldOffset[1] = ulTemp;
fUpdateBmp = TRUE;
fDecodeBitmap = TRUE;
}
pbPtr += 8;
/* don't change pSPU->RLE8Bit, this can be used for either mode */
break;
case CHG_COLCON: /* change color/contrast */
/* get the size of the pixel control data and subtract 2.
* The count includes the two bytes we just read */
#if DBG_ON(DBG_VERBOSE)
DbgPrint(("SPUDecoderDecodeSPU() -- CHG_COLCON\n"));
#endif
ulTemp = MAKE_WORD(&pbPtr[0]) - 2;
pbPtr += 2;
/* use the spudec to process the data */
SPURenderSetPixelControlData(pSPU, pbPtr, ulTemp);
pbPtr += ulTemp;
/* need to refesh our bitmap now */
fUpdateBmp = TRUE;
pSPU->RLE8Bit = 0;
break;
case CHG_COLCON2:
#if DBG_ON(DBG_VERBOSE)
DbgPrint(("SPUDecoderDecodeSPU() -- CHG_COLCON2\n"));
#endif
/* get the size of the pixel control data and subtract 2.
* The count includes the two bytes we just read */
ulTemp = MAKE_WORD(&pbPtr[0]) - 2;
pbPtr += 2;
/* use the spudec to process the data */
SPURenderSetPixelControlData8bit(pSPU, pbPtr, ulTemp);
pbPtr += ulTemp;
/* need to refesh our bitmap now */
fUpdateBmp = TRUE;
pSPU->RLE8Bit = 1;
break;
default:
DbgPrint(("SPUDecoderDecodeSPU() -- ERROR: COMMAND UNKNOWN - %i\n", bCommand));
break;
}
}/* while (1) */
/* send FSTA_DSP, STA_DSP, and STP_DSP send commands to renderer */
if ( (bSendCmd == FSTA_DSP) || (bSendCmd == STA_DSP) )
{
/* if we're too late then skip rendering so we can catch up
* TODO... make the timeout duration a configurable option of the subpic decoder
* instead using the hard coded timeout below */
if ( ( time90k_CurrSTC < ( time90k_StartPTS + (3003 * 4) ) ) || (ulLastOffset == ulNextOffset) )
{
/* if the bitmap needs refreshed do it now */
if (fUpdateBmp == TRUE)
{
/* if the spu needs RLE decoded do it now */
if (TRUE == fDecodeBitmap)
{
fDecodeBitmap = FALSE;
if (0 == pSPU->RLE8Bit)
{
if (SPURenderRLEDecodePxd(pSPU) != SPU_SUCCESS)
{
/* give critical section */
OS_SemGive(pSPU->critical_section);
return (SPU_ERR_DECODE_FAIL);
}
}
else
{
if (SPURenderRLEDecodePxd8Bit(pSPU) != SPU_SUCCESS)
{
/* give critical section */
OS_SemGive(pSPU->critical_section);
return (SPU_ERR_DECODE_FAIL);
}
}
}
/* clear the flag */
fUpdateBmp = FALSE;
}
SPUDecoderProcessData(pSPU, bSendCmd);
}
#if DBG_ON(DBG_TRACE)
else
{
DbgPrint(("SPUDecoderDecodeSPU() -- SKIPPING SPU\n"));
}
#endif
}
else if (bSendCmd == STP_DSP)
{
#if DBG_ON(DBG_VERBOSE)
DbgPrint(("SPUDecoderDecodeSPU() -- Erase\n"));
#endif
SPUDecoderProcessData(pSPU, bSendCmd);
/* set fHighlightEnabled false here */
pSPU->fHighlightEnabled = FALSE;
}
/* give critical section */
OS_SemGive(pSPU->critical_section);
OS_TaskYield();
} while ( (ulNextOffset > ulLastOffset) && (pbPtr < pbSPUEndPtr) );
return (SPU_SUCCESS);
}
/**
* Reads new subpictures from the input cStream into a local buffer.
*
* @param hSPDecoder = The subpic decoder handle
*/
SPU_ERR SPUDecoderGetNextSPU(SPU_DECODER *pSPU)
{
cSPUStreamMessage *pSPMessage;
ULONG ulSPUSize;
ULONG ulOffset;
ULONG ulTemp;
/* Get a new message pointing to a new payload */
pSPMessage = (cSPUStreamMessage*)pSPU->pStreamDecode->Read(OS_WAIT_FOREVER);
if (NULL == pSPMessage)
{
goto err_out;
}
/* check for an info packet */
if (pSPMessage->fInfoPayload == TRUE)
{
/* ignore info packets */
goto err_out;
}
/* make sure we have a payload */
TCH_PAYLOAD(pSPMessage->payload);
if (pSPU->ulState == SPU_STATE_FLUSHING)
{
DBGPRINT(DBG_ON(DBG_TRACE), ("SPDecoderGetSPU: No payload due to flush\n"));
goto err_out;
}
restart:
/* reset back to beginning of buffer */
ulOffset = 0;
ulSPUSize = 0;
/* make sure we have a payload */
if (NULL != pSPMessage->payload)
{
/* copy this info to our spu data buffer */
memcpy(&(pSPU->pbSpuBuffer[ulOffset]), pSPMessage->payload->get_rd_ptr(), pSPMessage->payload->get_size());
ulOffset += pSPMessage->payload->get_size();
/* can now release this payload */
delete pSPMessage->payload;
pSPMessage->payload = NULL;
/* get the pts
* NOTE: The first packet should always be timestamped. If it's not treat it as an error */
if (TRUE == pSPMessage->IsTimeStamped)
{
pSPU->ulPTS = pSPMessage->TimeStamp;
ulTemp = MAKE_WORD(&pSPU->pbSpuBuffer[0]);
/* if prehead == 0 */
if (0 == ulTemp)
{
ulSPUSize = MAKE_DWORD(&pSPU->pbSpuBuffer[2]);
}
else
{
ulSPUSize = ulTemp;
}
/* if notification of message done is requested give it now */
if (pSPMessage->semMsgDone)
{
OS_SemGive(pSPMessage->semMsgDone);
}
/* release the message */
pSPU->pStreamDecode->ReleaseMsg(pSPMessage);
pSPMessage = NULL;
}
else
{
DbgPrint(("SPDecoderGetSPU: Error - Expected Time Stamped Packet\n"));
goto err_out;
}
/* if this is not the entire payload then get the rest */
while (ulOffset < ulSPUSize)
{
/* get the next message */
pSPMessage = (cSPUStreamMessage*)pSPU->pStreamDecode->Read(OS_WAIT_FOREVER);
if (pSPU->ulState == SPU_STATE_FLUSHING)
{
goto err_out;
}
if (NULL != pSPMessage)
{
/* make sure we have a payload */
if (NULL != pSPMessage->payload)
{
TCH_PAYLOAD(pSPMessage->payload);
/* ignore info packets */
if (pSPMessage->fInfoPayload != TRUE)
{
/* Only the first packet should be timestamped.
* If this packet is timestamped then treat it as an error */
if ( (TRUE == pSPMessage->IsTimeStamped) || (TRUE == pSPMessage->DiscontinuityAtBeginning) )
{
/* drop what we have so far and start over with this new message */
DbgPrint(("SPDecoderGetSPU: Data Discontinuity, Restarting...\n"));
goto restart;
}
/* Copy the rest of SPU to the first payload */
memcpy(&(pSPU->pbSpuBuffer[ulOffset]), pSPMessage->payload->get_rd_ptr(),
pSPMessage->payload->get_size());
ulOffset += pSPMessage->payload->get_size();
}
/* delete the new payload */
delete (pSPMessage->payload);
pSPMessage->payload = NULL;
}
/* if notification of message done is requested give it now */
if (pSPMessage->semMsgDone)
{
OS_SemGive(pSPMessage->semMsgDone);
}
/* release the message */
pSPU->pStreamDecode->ReleaseMsg(pSPMessage);
pSPMessage = NULL;
}
}
}
else
{
goto err_out;
}
return (SPU_SUCCESS);
err_out:
if (NULL != pSPMessage)
{
if (NULL != pSPMessage->payload)
{
delete (pSPMessage->payload);
pSPMessage->payload = NULL;
}
/* if notification of message done is requested give it now */
if (pSPMessage->semMsgDone)
{
OS_SemGive(pSPMessage->semMsgDone);
}
/* release the message */
pSPU->pStreamDecode->ReleaseMsg(pSPMessage);
}
return (SPU_FAILURE);
}
SPU_ERR SPUDecoderProcessData(SPU_DECODER *pSPU, BYTE bCommand)
{
switch (bCommand)
{
case FSTA_DSP: /* Force */
/* check if subpics are disabled */
if (FALSE == pSPU->fDisabled)
{
SPURenderDraw(pSPU);
pSPU->fInserted = SP_INSERTED_AND_SHOWING;
}
else
{
pSPU->fInserted = SP_INSERTED_NOT_SHOWING;
}
pSPU->fIsForcedSP = TRUE;
pSPU->ulLastBmpX = pSPU->ulBmpX;
pSPU->ulLastBmpY = pSPU->ulBmpY;
pSPU->ulLastBmpW = pSPU->ulBmpW;
pSPU->ulLastBmpH = pSPU->ulBmpH;
break;
case STA_DSP: /* Show */
/* sub pic is not forced */
pSPU->fIsForcedSP = FALSE;
if ( (pSPU->fShowing == TRUE) && (pSPU->fDisabled == FALSE) )
{
SPURenderDraw(pSPU);
pSPU->fInserted = SP_INSERTED_AND_SHOWING;
}
else
{
pSPU->fInserted = SP_INSERTED_NOT_SHOWING;
}
pSPU->ulLastBmpX = pSPU->ulBmpX;
pSPU->ulLastBmpY = pSPU->ulBmpY;
pSPU->ulLastBmpW = pSPU->ulBmpW;
pSPU->ulLastBmpH = pSPU->ulBmpH;
break;
case STP_DSP: /* Stop */
if (pSPU->fInserted == SP_INSERTED_AND_SHOWING)
{
/* hide subpic */
SPURenderErase(pSPU);
}
pSPU->fInserted = SP_NOT_INSERTED;
pSPU->ulLastBmpX = 0;
pSPU->ulLastBmpY = 0;
pSPU->ulLastBmpW = 0;
pSPU->ulLastBmpH = 0;
pSPU->fIsForcedSP = FALSE;
break;
default:
DbgPrint(("ERROR: RENDERER - Unknown command %i\n", bCommand));
break;
}
return (SPU_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -