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

📄 pbc_avpres.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    /* check for valid handle */
    if (hPBC == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("pbcAvPresPlay: NULL handle!\n"));
        return (PLAYCTRL_NULL_POINTER);
    }

    /* Halt the DR play queue so the DR status can't change */
    DRQueueControl(hPBC->hDR, DR_STREAM_MAIN, DR_QUEUE_CMD_DISABLE);

    /* find out context of the dr's current play */
    DRGetStatus(hPBC->hDR, DR_STREAM_MAIN, DR_STATCMD_CONTEXT, (uint32 *)&pPIContext);

    /* make sure the playlist hasn't changed */
    PbcRegGetPSR(PLAYCTRL_PSR_PLAYLIST, &uiPlaylistID);
    uiPlaylistID &= 0x0000ffff;
    if (pPIContext->uiPlaylistID != uiPlaylistID)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("%s: WRONG PLAYLIST!\n", __FUNCTION__));
        status = PLAYCTRL_FAILURE;
        goto errout;
    }

    DBGPRINT(DBG_ON(DBG_TRACE), ("current speed:  %i   ---   new speed: %i\n",
        ((hPBC->fReverse) ? -1 : 1) * hPBC->ulPlayRate, ((fReverse) ? -1 : 1) * ulNewSpeed));

    /* If there's a change - do it. */
    if ( (ulNewSpeed != hPBC->ulPlayRate) || (ulNewSpeed == 1) || (hPBC->fReverse != fReverse) )
    {
        PE_ISTREAMCTRL_PLAYRATE  PlayRate;
        PE_ISTREAMCTRL_PLAYRATE  OldPlayRate;
        PE_ISTREAMCTRL_DIRECTION PlayDirection;
        uint16                   uiNextPlayitemID         = INVALID_PLAYITEM;
        UBYTE                    ubNextRandomShuffleIndex = 0xff;
        TIME45k                  time45k_PTS;
        APPINFOPLAYLIST_TABLE    *pAppInfoPL              = NULL;
        BOOLEAN                  fSendNext                = TRUE;
        PBC_WHICH_CONTEXT        pwContext;
        VDVD_CONNECT_COND        connection               = VDVD_CONNECTION_6;
        BOOLEAN                  fStopCalled              = FALSE;

        /* rate changed: clear the old playitems out of the queue
         *   if something was removed, re-use that context */
        if (DR_SUCCESS == DRQueueControl(hPBC->hDR, DR_STREAM_MAIN, DR_QUEUE_CMD_CLEAR))
        {
            pwContext = PBC_CURRENT;
        }
        else
        {
            pwContext = PBC_NEXT;
        }

        /* Get the Desired PE PlayRate configuration */
        PlayDirection = (!fReverse) ? PE_ISTREAMCTRL_DIRECTION_FORWARD: PE_ISTREAMCTRL_DIRECTION_BACKWARD;
        PEiStreamCtrlConfigPlayRateParam(hPBC->hPE, ulNewSpeed, PlayDirection, &PlayRate);

        /* Get the Current PE PlayRate configuration */
        PEiStreamCtrlGetRate(hPBC->hPE, &OldPlayRate);

        /* Get playlist info */
        if (MPLSGetAppInfo(&pAppInfoPL) != MPLS_SUCCESS)
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("pbcAvPresPlay: Failed to get playlist info!\n"));
            status = PLAYCTRL_FAILURE;
            goto errout;
        }

        /* If playlist is random/shuffle playback type, then restore random/shuffle status */
        if ( (pAppInfoPL->PlayList_playback_type == MPLS_RANDOM_PLAYLIST) ||
            (pAppInfoPL->PlayList_playback_type == MPLS_SHUFFLE_PLAYLIST) )
        {
            ubNextRandomShuffleIndex = PbcPLCtrlGetRandomShuffleIndex(hPBC);
        }

        /* if the rate change requires a change to the DR */
        if ( (OldPlayRate.discontiguous == 1) || (PlayRate.discontiguous == 1) )
        {
            fSendNext = FALSE;

            DBGPRINT(DBG_ON(DBG_TRACE), ("%s:%u - DR change required\n", __FUNCTION__, __LINE__));

            /* C->D (same dir)  */  /* @todo - this is a temporary change to simplify the trickmode cases ...
                                               if this goes back in, will need to not set hPBC->fReverse here
                                               (instead happens in BegStream)*/
            if (0) //( (0 == OldPlayRate.discontiguous) && (1 == PlayRate.discontiguous) && ( hPBC->fReverse == fReverse ) )
            {
                /* find clean transition point */
                if (DRBDROMStopAtPoint(hPBC->hDR, FALSE, (ULONG *)&time45k_PTS, (PVOID *)&pPIContext) != DR_FAILURE)
                {
                    /* if we successfully found a change point in the current playitem,
                     * RE-SEND THE CURRENT playitem with the new speed, and starting at the change point */
                    DBGPRINT(DBG_ON(DBG_TRACE), ("successfuly found a speed change point in the clip\n"));
                    uiNextPlayitemID = pPIContext->uiPlayitemID;

                }
                else
                {
                    /* if we don't successfully find a change point in the current playitem,
                     * SEND THE NEXT play item, with the correct speed and with the play item's
                     * listed start and end times. */
                    DBGPRINT(DBG_ON(DBG_TRACE), ("DID NOT find a speed change point in the clip\n"));
                    fSendNext = TRUE;
                }
                DBGPRINT(DBG_ON(DBG_VERBOSE), ("next play item id number: %u\n", uiNextPlayitemID));
            }
            /*  D->C  ||  D->D  ||  C->D (opp dir)  */
            else
            {
                uint32  uiPlayitemID;
                TIME45k time45k_STC;
                /* pause the decoder */
                if (PEiStreamCtrlPause(hPBC->hPE) != PE_SUCCESS)
                {
                    DBGPRINT(DBG_ON(DBG_ERROR), ("%s:%u - FAILED to pause the decoder\n", __FUNCTION__, __LINE__));
                    status = PLAYCTRL_FAILURE;
                    goto errout;
                }

                /* stop feeding */
                DRStop(hPBC->hDR);

                /* get pts from decoder and use it to update location (guarantee we're exactly at the pause point) */
                if (PEiStreamCtrlGetVidPTS(hPBC->hPE, &time45k_PTS, &time45k_STC) != PE_SUCCESS)
                {
                    DBGPRINT(DBG_ON(DBG_ERROR), ("%s:%u - FAILED to get Video PTS\n", __FUNCTION__, __LINE__));
                    status = PLAYCTRL_FAILURE;
                    goto errout;
                }
                PbcPLCtrlUpdateLocation(hPBC, time45k_PTS);

                OS_SemTake(hPBC->semRegisterMutex, OS_WAIT_FOREVER);

                /* Get the playitem, and presentation time register values */
                PbcRegGetPSR(PLAYCTRL_PSR_PLAYITEM,  &uiPlayitemID);
                uiNextPlayitemID = (uint16)(uiPlayitemID & 0x0000ffff);
                PbcRegGetPSR(PLAYCTRL_PSR_PRES_TIME, &time45k_PTS);

                OS_SemGive(hPBC->semRegisterMutex);

                PEiStreamCtrlStopStream(hPBC->hPE, INPUT_MAIN, TRUE);
                fStopCalled = TRUE;
                connection = VDVD_CONNECTION_ABORT;
            }
        }

        /* C->C  case skips the above block */

        /* the *next* playitem to be played is the one we're going to send */
        if (fSendNext)
        {
            /* send the *next* playitem to the DR (replace what was cleared) */
            uiNextPlayitemID = PbcPLCtrlGetNextPlayitem(hPBC, pPIContext->uiPlayitemID);

            /* Get pointer to the playitem from the movie playlist database */
            if (uiNextPlayitemID != INVALID_PLAYITEM)
            {
                if (MPLSGetPlayItem(uiNextPlayitemID, &pPlayItem) != MPLS_SUCCESS)
                {
                    DbgAssert(0);
                }
                time45k_PTS = (!fReverse) ? pPlayItem->IN_time : pPlayItem->OUT_time;
            }

            /* If playlist is random/shuffle playback type, then restore random/shuffle status */
            if ( (pAppInfoPL->PlayList_playback_type == MPLS_RANDOM_PLAYLIST) ||
                (pAppInfoPL->PlayList_playback_type == MPLS_SHUFFLE_PLAYLIST) )
            {
                ubNextRandomShuffleIndex += (fReverse ? -1 : 1);
            }
            connection = VDVD_CONNECTION_UNDEF;
        }
        else
        {
            /* fixes a bug:  the previous begOfStream is waiting and will be accepted
             *               once the next playitem begins.  If we're calling another DRPlay()
             *               we need to clear this flag because it will be re-set by this
             *               DRPlay()s BegOfStream.
             */
            hPBC->newpi.abort  = TRUE;

            if (PLAYCTRL_FAILURE == pbcEngineSendMessage(PBCENGINE_MSGTYPE_ABORT_COMPLETE, hPBC, 0, 0, 0, 0, 0, NULL))
            {
                /* @todo: handle this very bad case (though it *should* never happen) */
                DBGPRINT(DBG_ON(DBG_ERROR), ("PbcAvPres: PBCENGINE_MSGTYPE_ABORT_COMPLETE: pbcEngineSendMessage FAILED.  FIX ME!!\n"));
            }
        }

        /* set the pe rate */
        PEiStreamCtrlSetRate(hPBC->hPE, &PlayRate);

        /* restart the pe if necessary */
        if (fStopCalled)
        {
            PEiStreamCtrlPrefill(hPBC->hPE, INPUT_MAIN, PE_ASYNC);
        }

        if (MPLSGetPlayItem(pPIContext->uiPlayitemID, &pPlayItem) != MPLS_SUCCESS)
        {
            DbgAssert(0);
        }

        if (!pPlayItem->PlayItem_random_access_flag)
        {
            pPIContext->PlayRate = PlayRate;
        }

        if ( (OldPlayRate.discontiguous == 1) && (0 == PlayRate.discontiguous) )
        {
            uint32 uiPGTextStn;
            uint32 uiIGStn;

            DBGPRINT(DBG_ON(DBG_TRACE), ("%s:%u - Reconfigure Demuxes\n", __FUNCTION__, __LINE__));

            PbcRegGetPSR(PLAYCTRL_PSR_PG_AND_ST_STN, &uiPGTextStn);
            uiPGTextStn &= 0x00000fff;

            /* Configure PG and Text ST */
            if (PbcPLCtrlConfigPGandTextST(hPBC, uiPlaylistID, pPIContext->uiPlayitemID, uiPGTextStn) != PLAYCTRL_SUCCESS)
            {
                DBGPRINT(DBG_ON(DBG_ERROR), ("%s: PbcPLCtrlConfigPGandTextST() FAILED!\n", __FUNCTION__));
            }

            PbcRegGetPSR(PLAYCTRL_PSR_IG_STN, &uiIGStn);
            uiIGStn     &= 0x000000ff;

            if ( (pPlayItem->STN_table.number_of_IG_stream_entries > 0)               &&
                 (pPlayItem->STN_table.IG_stream[uiIGStn - 1].stream_entry.type == 1)  )
            {
                /* Configure IG */
                if (PbcPLCtrlConfigIG(hPBC, uiPlaylistID, pPIContext->uiPlayitemID, uiIGStn) != PLAYCTRL_SUCCESS)
                {
                    DBGPRINT(DBG_ON(DBG_ERROR), ("%s:: PbcPLCtrlConfigIG() FAILED!\n", __FUNCTION__));
                }
            }
        }
        else if ( (OldPlayRate.discontiguous == 0) && (1 == PlayRate.discontiguous) )
        {
            uint32 uiIGStn;
            PbcRegGetPSR(PLAYCTRL_PSR_IG_STN, &uiIGStn);
            uiIGStn     &= 0x000000ff;

            DBGPRINT(DBG_ON(DBG_TRACE), ("%s:%u - Remove Demuxes\n", __FUNCTION__, __LINE__));

            PEiStreamCtrlDemuxRemovePG(hPBC->hPE);

            if ( (pPlayItem->STN_table.number_of_IG_stream_entries > 0)               &&
                 (pPlayItem->STN_table.IG_stream[uiIGStn - 1].stream_entry.type == 1)  )
            {
                /* Get new value of stream number registers */
                PEiStreamCtrlDemuxRemoveIG(hPBC->hPE);
            }
        }

        /* and Send the DR playitem */
        if (uiNextPlayitemID != INVALID_PLAYITEM)
        {
            ULONG ulSendSpeed = ulNewSpeed;

            DBGPRINT(DBG_ON(DBG_TRACE), ("%s:%u - Send New DR Play Command\n", __FUNCTION__, __LINE__));

            if (ulSendSpeed == 0)
            {
                /* We don't really want the BegStream code to know it's at "paused" speed.
                   Instead, we want it to know that the data is being sent in normal speed */
                ulSendSpeed = 1000;
            }

            PbcPLCtrlPlayPlayitem(hPBC, pPIContext->uiPlayitemID, uiNextPlayitemID, time45k_PTS,
                fReverse, ulSendSpeed, ubNextRandomShuffleIndex, FALSE, pwContext, connection, FALSE);
        }
    }
    else
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("speed didn't change - nothing needed to happen\n"));
    }


    if (status == PLAYCTRL_SUCCESS)
    {
        /* Set the play rate and direction */
        hPBC->ulPlayRate        = ulNewSpeed;
        hPBC->fReverse          = fReverse;
        hPBC->tState            = (ulNewSpeed == 1) ? PLAYCTRL_STATE_PAUSE : PLAYCTRL_STATE_PLAY;
    }

errout:

    DRQueueControl(hPBC->hDR, DR_STREAM_MAIN, DR_QUEUE_CMD_ENABLE);
    return (status);
}



/**
 * PbcAvPresAudioChange -- Change presentation of audio to specified audio stream
 *
 * @param
 *      hPBC -- handle to playback control engine private data
 *      data1 -- audio stream number
 *      data2 -- not used
 *      data3 -- not used
 *
 * @retval
 *      PLAYCTRL_STATUS
 */
PLAYCTRL_STATUS PbcAvPresAudioChange(PBC_HANDLE *hPBC, ULONG data1, ULONG data2, ULONG data3)
{
    uint32          uiPlayItemID        = 0;
    PLAYITEM        *pPlayItem          = NULL;
    uint32          uiAudioStnCurrent;
    uint32          uiAudioStnNew;
    uint32          uiAudioStnNext;
    PLAYCTRL_STATUS status              = PLAYCTRL_SUCCESS;

    DBGPRINT(DBG_ON(DBG_TRACE), ("PbcAvPresAudioChange: audio stream = %d\n", data1));

    /* check for valid handle */
    if (hPBC == NULL)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PbcAvPresAudioChange: NULL handle!\n"));
        return (PLAYCTRL_NULL_POINTER);
    }

    /* if we're currently stopped then just update the PSR */
    if (hPBC->tState == PLAYCTRL_STATE_STOP)
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("PbcAvPrePbcAvPresAudioChange: JUST UPDATE PSR\n"));

        /* update the current audio selection */
        OS_SemTake(hPBC->semRegisterMutex, OS_WAIT_FOREVER);
        PbcRegGetPSR(PLAYCTRL_PSR_AUDIO_STN, &uiAudioStnCurrent);
        uiAudioStnCurrent &= 0xffffff00;
        uiAudioStnCurrent |= (data1 & 0x000000ff);
        PbcRegSetPSR(PLAYCTRL_PSR_AUDIO_STN, uiAudioStnCurrent);
        OS_SemGive(hPBC->semRegisterMutex);

        DBGPRINT(DBG_ON(DBG_TRACE), ("PbcAvPresAudioChange: PSR = 0x%lx\n", uiAudioStnCurrent));

        /* send event, notifying application of subtitle change */
        if (hPBC->pCallback != NULL)
        {
            uint32 tmp_data1 = data1;
            hPBC->pCallback(hPBC->pvCallbackContext, PLAYCTRL_EVENT_AUDIOCHANGE, &tmp_data1);
        }

⌨️ 快捷键说明

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