⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spu_decoder.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
                    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 + -