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

📄 pg_api.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        {
            OS_TimerDelete(PGInfo.PGFlipTimer);
            PGInfo.PGFlipTimer = 0;
        }

        /* release dfb surface */
        if (PGInfo.DFBInfo.PrimarySurface != NULL)
        {
            PGInfo.DFBInfo.PrimarySurface->Release(PGInfo.DFBInfo.PrimarySurface);
        }

        /* release surface manager */
        if (PGInfo.DFBInfo.SurfaceManager != NULL)
        {
            PGInfo.DFBInfo.SurfaceManager->Release(PGInfo.DFBInfo.SurfaceManager);
        }

        PGInfo.CurrentState = PG_STATE_UNINITIALIZED;
    }
    else
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("Return PG_STATUS_NOT_STOPPED on PGDelete\n"));
        return PG_STATUS_NOT_STOPPED;
    }

    return PG_STATUS_SUCCESS;
}

/**
 * PGGetState - Get PG decoder state
 *
 * @param PG_HANDLE handle - handle to the PG module
 *
 * @return PG_STATE
 */
PG_STATE PGGetState(PG_HANDLE handle)
{
    if (handle != (PVOID)PG_HANDLE_VALUE)
    {
        return PG_STATE_UNINITIALIZED;
    }
    else
    {
        return PGInfo.CurrentState;
    }
}

/**
 * PGRun - Enter the run state for the PG Module
 *
 * @param PG_HANDLE handle - handle to the PG module
 *
 * @return PG_STATUS
 */
PG_STATUS PGRun(PG_HANDLE handle)
{
    if (handle != (PVOID)PG_HANDLE_VALUE)
    {
        return PG_STATUS_INVALID_HANDLE;
    }

    if ((PG_STATE_STOPPED == PGInfo.CurrentState) || (PG_STATE_INITIALIZED == PGInfo.CurrentState))
    {
        OS_SemTake(PGInfo.StateLock, OS_WAIT_FOREVER);

        /* we have not yet found a valid epoch or acq point */
        PGInfo.StreamAcquired = 0;
        PGInfo.ParseWait.WaitTime.Enabled = 0;
        PGInfo.ParseWait.WaitTime.WaitPTS = 0;
        PGInfo.RenderWait.WaitTime.Enabled = 0;
        PGInfo.RenderWait.WaitTime.WaitPTS = 0;
        PGInfo.CurPTS             = 0;
        PGInfo.CoordsHalfWidth    = 0;
        PGInfo.CopyingPES         = 0;
        PGInfo.CopyingMultiPES    = 0;
        PGInfo.SequenceDesc       = 0;
        PGInfo.fGotStartPtr       = 0;
        PGInfo.ParseReadPtr       = 0;
        PGInfo.PESWritePtr        = 1;
        PGInfo.PESWriteStart      = 1;
        memset(&PGInfo.CurPesInfo, 0, sizeof(PES_HDR_INFO));

        /* make sure the parse sem is empty */
        OS_SemTake(PGInfo.ParseWait.WaitSem, OS_NO_WAIT);
        OS_SemTake(PGInfo.RenderWait.WaitSem, OS_NO_WAIT);

        PGGraphicsClearScreen();
        OS_TimerSet(PGInfo.PGFlipTimer, 1);
        OS_TaskYield();

        /* clear the stop flag */
        PGInfo.QuitFlags = PG_FLAGS_RUN;
        PGInfo.CurrentState = PG_STATE_RUNNING;

        DBGPRINT(DBG_ON(DBG_TRACE), ("--PGRun()\n"));

        OS_SemGive(PGInfo.StateLock);
        return PG_STATUS_SUCCESS;
    }
    else
    {
        return PG_STATUS_NOT_INITIALIZED;
    }
}

/**
 * PGRun - Enter the stop state for the PG Module
 *
 * @param PG_HANDLE handle - handle to the PG module
 *
 * @return PG_STATUS
 */
PG_STATUS PGStop(PG_HANDLE handle)
{
    if (handle != (PVOID)PG_HANDLE_VALUE)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PGStop Invalid handle value\n"));
        return PG_STATUS_INVALID_HANDLE;
    }

    if (PG_STATE_RUNNING == PGInfo.CurrentState)
    {
        /* state we are stopped so we kick out of tasks */
        PGInfo.CurrentState = PG_STATE_STOPPED;
        PGInfo.QuitFlags = PG_FLAGS_STOP;

        /* take a lock */
        OS_SemTake(PGInfo.StateLock, OS_WAIT_FOREVER);

        DBGPRINT(DBG_ON(DBG_TRACE), ("--PGStop()\n"));

        /* clear the frame buffer here and clear all the object lists */
        PGFlush();

#ifdef ALLOW_PG_PROFILING
        ULONG TickRate = OS_GetTickRate();
        if (1 == PGStats.Profiling)
        {
            ULONG PixelsPerSec = 0;
            ULONG PixelsRemain = 0;

            if ((PGStats.PGTotalRLETicks/TickRate) != 0)
            {
                PixelsPerSec = PGStats.PGPixelsDecoded/(PGStats.PGTotalRLETicks/TickRate);
                PixelsRemain = PGStats.PGPixelsDecoded%(PGStats.PGTotalRLETicks/TickRate);
            }

            DBGPRINT(DBG_ON(DBG_ERROR), ("PGFlipTime: %u.%u\nPGBlitTime: %u.%u\nPGCreateSurface: %u.%u\nPGRLETime: %u.%u\n"
            "PGAddDataTime: %u.%u\nPGTotalFrameDrops: %u\nPGTotalRLEFailures: %u\nPGTotalParseMsgDrops: %u\nPGPixelDecodeRate: %u.%u\n\n",
                PGStats.PGTotalFlipTicks/TickRate, PGStats.PGTotalFlipTicks%TickRate,
                PGStats.PGTotalBlitTicks/TickRate, PGStats.PGTotalBlitTicks%TickRate,
                PGStats.PGTotalCreateSurfaceTicks/TickRate, PGStats.PGTotalCreateSurfaceTicks%TickRate,
                PGStats.PGTotalRLETicks/TickRate, PGStats.PGTotalRLETicks%TickRate,
                PGStats.PGTotalAddDataTicks/TickRate, PGStats.PGTotalAddDataTicks%TickRate,
                PGStats.PGTotalFrameDrops,
                PGStats.PGTotalRLEFailures,
                PGStats.PGTotalParseMsgDrops,
                PixelsPerSec,
                PixelsRemain));
        }
#endif

        OS_SemGive(PGInfo.StateLock);
    }
    else if (PG_STATE_INITIALIZED == PGInfo.CurrentState)
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("PGStop: PG was initialized\n"));
        /* we should already be stopped */
        OS_SemTake(PGInfo.StateLock, OS_WAIT_FOREVER);
        PGInfo.CurrentState = PG_STATE_STOPPED;
        OS_SemGive(PGInfo.StateLock);
    }
    else if (PG_STATE_STOPPED == PGInfo.CurrentState)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PGStop: PG was already stopped\n"));
        return PG_STATUS_SUCCESS;
    }
    else
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PGStop: PG state was %d\n", PGInfo.CurrentState));
        return PG_STATUS_ERROR;
    }

    return PG_STATUS_SUCCESS;
}

/**
 * PGShowHide - tell the PG module to show or hide its graphics
 *
 * @param PG_HANDLE handle - handle to the PG module
 * @param PG_SHOW_HIDE value - value representing shown or hidden graphics
 *
 * @return PG_STATUS
 */
PG_STATUS PGShowHide(PG_HANDLE handle, PG_SHOW_HIDE value)
{
    if (handle != (PVOID)PG_HANDLE_VALUE)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("Return PG_STATUS_INVALID_HANDLE from PGShowHide\n"));
        return PG_STATUS_INVALID_HANDLE;
    }

    DBGPRINT(DBG_ON(DBG_TRACE), ("ShowHide got %d, PGInfo.ShowGraphics is %d\n", value, PGInfo.ShowGraphics));

    switch(value)
    {
        case PG_SHOW_GRAPHICS:

            /* only do something if the ShowGraphics value will be changing */
            if (PG_HIDE_GRAPHICS == PGInfo.ShowGraphics)
            {
                PGInfo.ShowGraphics = value;

                /* if we have a PCS */
                OS_SemTake(PGInfo.RenderLock, OS_WAIT_FOREVER);

                if (PGInfo.RenderPCS)
                {
                    OS_SemTake(PGInfo.BlitLock, OS_WAIT_FOREVER);
                    RenderPCS(PGInfo.RenderPCS);
                    OS_SemGive(PGInfo.BlitLock);

                    OS_TimerSet(PGInfo.PGFlipTimer, 1);
                    OS_TaskYield();
                }

                OS_SemGive(PGInfo.RenderLock);
            }
            break;

        case PG_HIDE_GRAPHICS:

            OS_SemTake(PGInfo.RenderLock, OS_WAIT_FOREVER);
            /* only do something if the ShowGraphics value will be changing */
            if (PG_SHOW_GRAPHICS == PGInfo.ShowGraphics)
            {
                if (PGInfo.RenderPCS)
                {
                    /* if we are told to hide pg but there is a composition
                       with forced on showing we must re-render */
                    if (PGInfo.RenderPCS->fPCSHasForced)
                    {
                        OS_SemTake(PGInfo.BlitLock, OS_WAIT_FOREVER);
                        RenderPCS(PGInfo.RenderPCS);
                        OS_SemGive(PGInfo.BlitLock);

                        OS_TimerSet(PGInfo.PGFlipTimer, 1);
                        OS_TaskYield();
                    }
                    else
                    {
                        /* clear the pg display */
                        PGGraphicsClearBuffer(NULL, 0);

                        OS_TimerSet(PGInfo.PGFlipTimer, 1);
                        OS_TaskYield();
                    }
                }

                PGInfo.ShowGraphics = value;
            }
            OS_SemGive(PGInfo.RenderLock);
            break;

        default:
            DBGPRINT(DBG_ON(DBG_ERROR), ("PGShowHide(): Invalid value to function\n"));
            break;
    }

    return PG_STATUS_SUCCESS;
}

/**
 * PGAddData - adds data to the PG module, once this call ends the data given can
 *              be free'd.  Note we don't just copy the data, we inspect the PES headers
 *              a bit to pull out ES data and drop it in the parse buffer.  Then fire
 *              a message to the PGParse task so it can parse the new data.
 *
 * @param PG_HANDLE handle - handle to the PG module
 * @param BYTE *Buffer - data buffer to add to module
 * @param ULONG Size - size of Buffer in bytes
 *
 * @return PG_STATUS - PG_STATUS_SUCCESS if data copied successfully
 *                   - PG_STATUS_NOT_RUNNING if we are not in the Run State
 */
PG_STATUS PGAddData(PG_HANDLE handle, BYTE *Buffer, ULONG Size)
{
    ULONG BytesRead=0;
    ULONG RetCode;
    ULONG LeftToCopy;
    USHORT AssembleBytesRead=0;
    ULONG ObjectDataSize;
    ULONG BytesLeft;
    ULONG StartCodeOffset;
#ifdef ALLOW_PG_PROFILING
    ULONG TickStart = 0;
#endif

    DBGPRINT(DBG_ON(DBG_TRACE), ("--PGAddData 0x%p, size=%d\n", Buffer, Size));

#ifdef ALLOW_PG_PROFILING
    if (1 == PGStats.Profiling)
    {
        TickStart = OS_GetTicks();
    }
#endif

    /* take the state lock so we can't be stopped while in this call */
    OS_SemTake(PGInfo.StateLock, OS_WAIT_FOREVER);

    /* this routine should copy the data given into our PG parse buffer */

    /* this routine will just copy data to the buffer looking for full PES
    packets, when it receives full PES packets it will signal the pg parser
    task to go and use the data, if there is a storm of data we should be able to
    copy to our buffer and signal the PG parser one at a time when it has finished
    with the data, to do that we should just mark each point in the buffer that
    contains the start of a PES packet and put it in a list, the pg parser
    should be able to just read from that list (or queue) and run with the data,

    NOTE: WATCH for data wrap arounds, IE DON'T STORE data in a non contiguous fashion
    in the buffer, make sure there is enough room to work with it in place without wrapping
    the copies

    NOTE 2: the data is dword filled memory the size given to this call is
    NOT the size of the valid data but the size of the chunk, we will need to parse
    PES headers and track whats needed in order to get the correct amount of data */

    if (handle != (PVOID)PG_HANDLE_VALUE)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("Return PG_STATUS_INVALID_HANDLE from AddData\n"));

#ifdef ALLOW_PG_PROFILING
        if (1 == PGStats.Profiling)
        {
            PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
        }
#endif

        OS_SemGive(PGInfo.StateLock);
        return PG_STATUS_INVALID_HANDLE;
    }

    if (PG_STATE_RUNNING != PGInfo.CurrentState)
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("Return PG_STATUS_NOT_RUNNING from add data\n"));

#ifdef ALLOW_PG_PROFILING
        if (1 == PGStats.Profiling)
        {
            PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
        }
#endif

        OS_SemGive(PGInfo.StateLock);
        return PG_STATUS_NOT_RUNNING;
    }

    /* loop
    {
        1. finish current pes packet (if any)
        2. look for sync
    }*/

    /* this is how much is left in the packet */
    BytesLeft = Size;

    /* loop over the whole buffer */
    while (BytesLeft > 0)
    {
        if (PGInfo.QuitFlags == PG_FLAGS_STOP)
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("\n\n !!PGAddData Called while in Stop State\n"));
#ifdef ALLOW_PG_PROFILING
            if (1 == PGStats.Profiling)
            {
                PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
            }
#endif

            OS_SemGive(PGInfo.StateLock);
            return PG_STATUS_ERROR;
        }

        /*
            1. finish current pes packet (if any)
        */
        if (PGInfo.CopyingPES)
        {
            /* header not complete */
            if (0 == PGInfo.CurPesInfo.HeaderComplete)
            {
                /* if we ran out of data we will wait till the next adddata to finish the header */
                RetCode = PGAssemblePesHeader(&Buffer[BytesRead], BytesLeft, &AssembleBytesRead);
                if (PG_STATUS_SUCCESS == RetCode)
                {
                    /* packet assembled, read the pes header */
                    if (PG_STATUS_SUCCESS != PGReadPESHeader(PGInfo.CurPesInfo.PesHdrBuff))
                    {
                        /* something is wrong with this pes header, don't try to figure it out
                        drop data and hope we catch up */
                        DBGPRINT(DBG_ON(DBG_ERROR), ("\n Error in pes header\n"));

                        /* clear the pes header */
                        PGClearAddDataVars();
#ifdef ALLOW_PG_PROFILING
                        if (1 == PGStats.Profiling)
                        {
                            PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
                        }
#endif

                        OS_SemGive(PGInfo.StateLock);
                        return PG_STATUS_SUCCESS;
                    }

                    /* are we copying a multipes segment already */
                    if (0 == PGInfo.CopyingMultiPES)
                    {
                        /* is this packet full (multipes)? */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -