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

📄 dr_prefetch.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    char filenameN[24];
    sprintf(filenameN, "%s%u", drfilename, m_idnum);
    fdrout[m_idnum] = open(filenameN, O_CREAT | O_WRONLY | O_TRUNC, 0666);
    if (fdrout[m_idnum] < 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("DROutput::Configure - error opening capture file\n"));
    }
#endif

    return(DR_SUCCESS);

errout:

    destroy();

    return(DR_FAILURE);
}






/**
 * GetStatus - Get the prefetch status
 *
 * @retval none
 *
 * @remarks none.
 */
DR_ERROR DRPrefetch::GetStatus (DR_STATCMD cmd, uint32 *pStatus)
{
    uint32 bf32tmpStatus=0;

    if(pStatus == NULL)
    {
        return(DR_INVALID_PARAM);
    }

    switch(cmd)
    {
    case DR_STATCMD_STATE:
        *pStatus = m_State;        /* note that the state is not semaphore protected - this is just a snapshot */
        break;
    case DR_STATCMD_BUFFERS:
        if ( (m_prefetchStream->FullStatus() == 0) )
        {
            bf32tmpStatus |= DR_STATUS_TRACK_BUFFER_EMPTY;
        }

        /* check play queue */
        if (m_prefetchPlayQueue->FullStatus() > 0)
        {
            bf32tmpStatus |= DR_STATUS_QUEUE_BUFFER;
        }

        *pStatus = bf32tmpStatus;
        break;

    case DR_STATCMD_CONTEXT:
        *pStatus = (uint32)GetContext();
        break;

    case DR_STATCMD_NEXT_CONTEXT:
        *pStatus = (uint32)GetNextContext();
        break;
    case DR_STATCMD_RATE:
        *pStatus = GetPlayRate();
        break;
    case DR_STATCMD_CELL_POSITION:
        *pStatus = (uint32)GetCellPosition();
        break;
    default:
        break;
    }
    return(DR_SUCCESS);
}




/**
 * QueueControl - enable, disable, or clear the play queue
 *
 * @param cmd    - the command (enable, disable, or clear).
 *
 * @retval none
 *
 * @remarks none.
 */
DR_ERROR DRPrefetch::QueueControl (DR_QUEUE_CMD cmd)
{
    PLAYMSG  *pMessage;
    DR_ERROR status     = DR_FAILURE;

    switch(cmd)
    {
    case DR_QUEUE_CMD_ENABLE:
        if(!m_fPlayQueueEnabled)
        {
            OS_SemGive(m_semPlayQueueEnabled);
            m_fPlayQueueEnabled = TRUE;
            status = DR_SUCCESS;
        }
        break;

    case DR_QUEUE_CMD_DISABLE:
        if(m_fPlayQueueEnabled)
        {
            OS_SemTake(m_semPlayQueueEnabled, OS_WAIT_FOREVER);
            m_fPlayQueueEnabled = FALSE;
            status = DR_SUCCESS;
        }
        break;

    case DR_QUEUE_CMD_CLEAR:
        do
        {
            pMessage = (PLAYMSG *)m_prefetchPlayQueue->Remove();
            if (pMessage != NULL)
            {
                DBGPRINT(DBG_ON(DBG_TRACE), ("%s, %d: QueueControl, Removed one from the queue: ulData0 = %lx, ulData1 = %lx, ulData2 = %lx\n",
                    __FILE__, __LINE__, (long)pMessage->play.anon.ulData0, (long)pMessage->play.anon.ulData1, (long)pMessage->play.anon.ulData2));
                m_prefetchPlayQueue->ReleaseMsg(pMessage);
                status = DR_SUCCESS;
            }

        } while (pMessage != NULL);
        break;
    }

    return(status);
}



/**
 * Play - play as specified in the "play" parameter
 *
 * @param blocking  - should we wait for this play to be started before returning?
 * @param play      - the paramters for playback.
 *
 * @retval none
 *
 * @remarks none.
 */
void DRPrefetch::Play(PLAYCMD play, BOOLEAN fBlockonPlay)
{
    PLAYMSG  *pMessage    = NULL;

    /* get a prefetchPlayQueue Message */
    pMessage = (PLAYMSG*)m_prefetchPlayQueue->GetMsg((ULONG)OS_WAIT_FOREVER);

    pMessage->ulSemID    = (fBlockonPlay == TRUE) ? m_semPlayBlock : 0;
    pMessage->play       = play;

    m_prefetchPlayQueue->Write((PVOID)pMessage, OS_WAIT_FOREVER);

    if (fBlockonPlay)
    {
        OS_SemTake(m_semPlayBlock, OS_WAIT_FOREVER);
    }
}



/**
 * Abort - Abort playback
 *
 * @retval BOOLEAN - was the playqueue enabled prior to Aborting
 *
 * @remarks none.
 */
BOOLEAN DRPrefetch::Abort(void)
{
    PLAYMSG  *pMessage    = NULL;
    BOOLEAN fPlayQueueWasEnabled;

    /* Abort Current Play */
    m_fAbort = TRUE;

    /* Save the Current State (so we can restore it later) */
    fPlayQueueWasEnabled = m_fPlayQueueEnabled;

    /* Wait for the Abort command to finish */
    QueueControl(DR_QUEUE_CMD_DISABLE);

    /* kick the prefetch thread so it won't wait */
    pMessage = (PLAYMSG*)m_prefetchPlayQueue->GetMsg((ULONG)OS_NO_WAIT);
    if (pMessage != NULL)
    {
        m_prefetchPlayQueue->Write((PVOID)pMessage, OS_NO_WAIT);
    }

    while (m_State != DRPRE_STATE_IDLE)
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("%s, %d - idnum %u:  waiting for stop\n", __FUNCTION__, __LINE__, m_idnum));
        OS_TaskDelay(OS_GetTicksPerSecond()/5);
    }

    /* be sure the queue is cleared */
    QueueControl(DR_QUEUE_CMD_CLEAR);

    /* Reset Flag */
    m_fAbort = FALSE;

    return(fPlayQueueWasEnabled);
}



/**
 * Flush - Flush buffers
 *
 * @retval BOOLEAN - succeessful completion?
 *
 * @remarks none.
 */
BOOLEAN DRPrefetch::Flush(BOOLEAN fGracefully, ULONG ulFlushLevel, ULONG ulClipNum, ULONG *spnIn, PVOID *pvContext)
{
    DROUTPUTMESSAGE *pStreamMessage = NULL;
    BOOLEAN fSuccess = TRUE;

    DbgAssert( (fGracefully && (spnIn != NULL) && (pvContext != NULL) ) || (!fGracefully) );

    DBGPRINT(DBG_ON(DBG_TRACE), ("%s, %d - idnum %u:  flush prefetch stream\n", __FUNCTION__, __LINE__, m_idnum));
    DBGPRINT(DBG_ON(DBG_TRACE), ("stream level before flush: %u\n", m_prefetchStream->FullStatus()));

    do
    {
        pStreamMessage = (DROUTPUTMESSAGE *)m_prefetchStream->Remove();
        if (pStreamMessage != NULL)
        {
            if (fGracefully)
            {
                if ( (pStreamMessage->LocalContext == 0)  ||  (((LocalContext*)(pStreamMessage->LocalContext))->ulClipNum != ulClipNum))
                {
                    m_prefetchStream->Write(pStreamMessage);
                    fSuccess = FALSE;
                    break;
                }
                *spnIn      = ((LocalContext*)(pStreamMessage->LocalContext))->spnOfPayload;
                *pvContext  = ((LocalContext*)(pStreamMessage->LocalContext))->pvContext;
            }

            if (pStreamMessage->payload != NULL)
            {
                delete (pStreamMessage->payload);
                pStreamMessage->payload = NULL;
            }
            m_prefetchStream->ReleaseMsg(pStreamMessage);
        }
    } while ( (m_prefetchStream->FullStatus() > ulFlushLevel) && (pStreamMessage != NULL) );

    DBGPRINT(DBG_ON(DBG_TRACE), ("stream level after flush: %u\n", m_prefetchStream->FullStatus()));
    return(fSuccess);
}



/**
 * Stop - empty the play queue, stop the prefetch thread, and flush the prefetch stream
 *
 * @param reset    - flag to reset the playback parameters?  (unly currently used for DVD)
 *
 * @retval none
 *
 * @remarks none.
 */
void DRPrefetch::Stop (BOOLEAN reset)
{
    BOOLEAN fPlayQueueWasEnabled;

    /* Abort() also clears and disables the queue */
    fPlayQueueWasEnabled = Abort();

    Flush(FALSE, 0, 0, NULL, NULL);

    if (reset)
    {
        ResetParams();
    }
    DBGPRINT(DBG_ON(DBG_TRACE), ("%s, %d - idnum %u:  Stop Command Completed\n", __FUNCTION__, __LINE__, m_idnum));

    if(fPlayQueueWasEnabled == TRUE)
    {
        QueueControl(DR_QUEUE_CMD_ENABLE);
    }
}




/**
 * PrefetchThread - The Prefetch Thread.  Reads play commands and executes them, putting data into the prefetch stream
 *
 * @retval none
 *
 * @remarks none.
 */
ULONG DRPrefetch::PrefetchThread(void)
{
    PLAYMSG *pInputMessage;
    PLAYCMD playCmd;
    ULONG   ulSemID;

    while(!m_fKill)
    {
        /* we're starting out (or just finished) - we're idle */
        m_State = DRPRE_STATE_IDLE;
        OS_SemTake(m_semPlayQueueEnabled, OS_WAIT_FOREVER);

        pInputMessage = NULL;

        if (!m_fKill && !m_fAbort)
        {
            pInputMessage = (PLAYMSG*)m_prefetchPlayQueue->Read(OS_WAIT_1S / 10);

            if ( (NULL != pInputMessage) && (m_fKill == FALSE) )
            {
                /* we've read - so we're running */
                m_State = DRPRE_STATE_RUNNING;

                /* copy the info and release the message*/
                playCmd     = pInputMessage->play;
                ulSemID     = pInputMessage->ulSemID;

                m_prefetchPlayQueue->ReleaseMsg(pInputMessage);
                pInputMessage = NULL;

                /* If the prefetch Play() command was configured as a blocking call, this releases it */
                if (ulSemID != 0)
                {
                    OS_SemGive(ulSemID);
                }

                /* If buffer is empty, send buffer empty event */
                if (m_prefetchPlayQueue->FullStatus() == 0)
                {
                    if (m_event != NULL)
                    {
                        m_event(m_pContext, DR_EVENT_COMMAND_BUFFER_EMPTY, NULL);
                    }
                }

                /* Do the data retrieval requested by playCmd */
                if (DR_SUCCESS != dataRetrieve(playCmd))
                {
                    DBGPRINT(DBG_ON(DBG_TRACE), ("PrefetchThread() -- Error in Data Retrieve\n"));
                }
            }
            else
            {
                OS_TaskDelay(OS_WAIT_1S / 25);
                DBGPRINT(DBG_ON(DBG_VERBOSE), ("PrefetchThread():%u - ticked off!\n", m_idnum));
            }
        }
        /* give the sem here in case it isn't given inside of dataRetrieve (we're aborting or ticking off) */
        OS_SemGive(m_semPlayQueueEnabled);
        if (!m_fKill)
        {
            OS_TaskDelay(OS_WAIT_1S / 50);
        }
    }
    m_State = DRPRE_STATE_IDLE;
    OS_TaskExit();
    return(0);
}






⌨️ 快捷键说明

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