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

📄 dr_prefetch_dvd.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                        /* Have we reached the end of the current VOBU?
                         * NOTE: we play up and including this sector so increment after check */
                        if (ulCurrentSector++ == ulVobuEndAddr)
                        {
                            if (fSeqEndDetected == TRUE)
                            {
                                /* the seq end flag is indicated at the beginning of the vobu
                                 * so we need to wait until we've actually read the vobu before
                                 * we send the sequence end flag */
                                if (m_dsi_packet.dsi_gi.vobu_2ndref_ea == 0)
                                {
                                    /* if there is no 2ndref then this is an I-Frame only */
                                    streamMessage.SequenceEnd = 0x03;
                                }
                                else
                                {
                                    streamMessage.SequenceEnd = 0x01;
                                }
                                streamMessage.DiscontinuityAtEnd = TRUE;
                            }

                            /* determine the next sector */
                            ulNextSector = drGetNextSectorAddr(&m_dsi_packet, playcmd.dvd.ulStart, playcmd.dvd.ulEnd, ulVobuEndAddr, m_ulNavPackLBN);


                            /* if we are in a discontinuous read mode and this was the last sector
                             * then stop here and send it to the decoder */
                            if (m_read_until_ref != DR_NORMAL_PLAYBACK)
                            {
                                /* we are skipping data so mark the discontinuity
                                 * and send this off to the PE */
                                streamMessage.DiscontinuityAtEnd = TRUE;
                            }

                            /*
                             * throw away the rest of the sectors
                             * We will start reading from the new address calculated above.
                             * Since we want to include the current sector add one to the current count.
                             */
                            ulCurrentSector = ulNextSector;
                            ulSectorsToRead = i + 1;
                            break;
                        }
                    }

                    OS_SemGive(m_semAngleChg);
                }
                else       /* lbn playback */
                {
                    ulCurrentSector += ulSectorsToRead;
                }
            }
            else
            {
                /* ERROR RECOVERY */
                DbgPrint(("\nLoaderSectorReadAV Error, sector = %lx\n\n", (long)ulCurrentSector));

                /* if a event callback is registered then send an error notification */
                if (m_event != NULL)
                {
                    m_event(m_pContext, DR_EVENT_ERROR, NULL);
                }

                /* The dvd nav handles error recovery in VOBU or CELL mode */
                if (playcmd.dvd.playType == DR_TYPE_LBN)
                {
                    ulCurrentSector += ulSectorsToRead;
                    ulSectorsToRead  = 0;
                }
                else
                {
                    /* so we don't report errors reading the same sector again */
                    m_fAbort = TRUE;
                }
                fReadOk = FALSE;
            }

            /* Update the write pointer */
            if (TRUE == fReadOk)
            {
                pStreamPayload->add_data(ulSectorsToRead * DVD_SECTOR_SIZE);
            }

            /* make sure we kick out if we hit the end */
            if (ulCurrentSector > playcmd.dvd.ulEnd)
            {
                ulCurrentSector = SRI_END_OF_CELL;
                break;
            }

            ulLoopBuf += ulSectorsToRead;

            if (ulCurrentSector == SRI_END_OF_CELL)
            {
                break;
            }

            if (streamMessage.DiscontinuityAtEnd == TRUE)
            {
                break;
            }

            /* if a flush is requested just drop everything */
            if (m_fAbort == TRUE)
            {
                break;
            }
        }

        /* force the EndOfStream flag */
        if ((ulCurrentSector > playcmd.dvd.ulEnd)  ||  /* playing fwd reached end of sectors */
            (ulCurrentSector < playcmd.dvd.ulStart))    /* playing rev reached beg of sectors */
        {
            streamMessage.EndOfStream = TRUE;
        }

        streamMessage.StreamContext = playcmd.dvd.pvContext;

        /* send navpack id with the message */
        streamMessage.ulVobuCC     = m_ulVobuCC;
        streamMessage.fIsVobuStill = playcmd.dvd.fIsVobuStill;

        /* transfer the payload to the PE */
        drSendStream(streamMessage, pStreamPayload);

        delete pStreamPayload;
        pStreamPayload = NULL;

        if (streamMessage.SequenceEnd != FALSE)
        {
            /* reset flags */
            streamMessage.SequenceEnd          = FALSE;
            fSeqEndDetected                    = FALSE;
        }

        /* reset flags */
        streamMessage.DiscontinuityAtBeginning = FALSE;
        streamMessage.DiscontinuityAtEnd       = FALSE;
        streamMessage.EndOfStream              = FALSE;
        streamMessage.BegOfStream              = FALSE;

        /* for rewind */
        if ( (m_skip_vobu > DR_FWDI_NEXT) && (ulCurrentSector < playcmd.dvd.ulStart) )
        {
            break;
        }

    } while (ulCurrentSector <= playcmd.dvd.ulEnd);
    return(DR_SUCCESS);
}

/**
 * drGetTitleKey - get the title key for the current sector
 *
 * @param ulSector   - the current sector
 *
 * @retval none
 *
 * @remarks none.
 */
DR_ERROR DRPrefetch_DVD::drGetTitleKey(ULONG ulSector)
{
    cPayload            *pStreamPayload = NULL;
    DROUTPUTMESSAGE     streamMessage;
    DR_ERROR            status          = DR_FAILURE;


    streamMessage.fInfoPayload = TRUE;


    /* Get a payload buffer to work with */
    pStreamPayload = drGetPayload();
    if (NULL != pStreamPayload)
    {
        BYTE        *pbData;
        INFOPAYLOAD *infoPayload;

        infoPayload = (INFOPAYLOAD*)pStreamPayload->get_base_ptr();

        infoPayload->bType  = INFOTYPE_CRYPTKEY;
        pbData              = infoPayload->data_packet.data;

        /* Scan for the first sector with a title key.
         * Give up if not found in first 16 sectors */
        for (int i=0; i<16; i++)
        {
            if (LoaderSectorRead(m_loader, ulSector, pbData, 1) != LOADER_SUCCESS)
            {
                /* ERROR RECOVERY */
                DbgPrint(("\nLoaderSectorRead Error while retrieving title key, sector = %lx\n\n", (long)ulSector));

                /* if a event callback is registered then send an error notification */
                if (m_event != NULL)
                {
                    m_event(m_pContext, DR_EVENT_ERROR, NULL);
                }
                status = DR_FAILURE;
                break;
            }
            else
            {
                /* determine if sector is encrypted */
                if (MAKE_DWORD(pbData) == 0x000001BA)
                {
                    if ( (((BYTE*)(KSEG1(pbData)))[20] & 0x30) &&
                        ( ((BYTE*)(KSEG1(pbData)))[17] != 0xbd) )
                    {
                        DBGPRINT(DBG_ON(DBG_TRACE), ("DRCommandProc() -- DR_TITLE_KEY sector = %lx\n", (long)ulSector));
                        status = DR_SUCCESS;
                        break;
                    }
                }
                ulSector++;
            }
            if (m_fAbort == TRUE)
            {
                break;
            }
        }

        if (DR_SUCCESS == status)
        {
            BYTE bDataSize;

            /* bDataSize is used in case we need to pass encrypted or unencrypted keys or something else entirely */
            if (CSSGetTitleKey(m_loader, ulSector, &pbData[0], &bDataSize) == CSS_FAILURE)
            {
                /* return an error */
                DbgPrint(("  ERROR, CANNOT GET TITLE KEY\n"));
                status = DR_FAILURE;
            }
            else
            {
                /* we've got the title key, send it to the PE */
                infoPayload->data_packet.size = (ULONG)bDataSize;

                /* send navpack id with the message */
                streamMessage.ulVobuCC     = m_ulVobuCC;
                streamMessage.fIsVobuStill = FALSE;

                /* transfer the payload to the PE */
                if (drSendStream(streamMessage, pStreamPayload) != DR_SUCCESS)
                {
                    /* return an error */
                    status = DR_FAILURE;
                }
            }
        }
        else
        {
            DbgPrint(("DRCommandProc: DR_TITLE_KEY -- COULD NOT FIND TITLE KEY!!!\n"));
        }

        /* delete the payload */
        delete pStreamPayload;
    }

    /* Done getting title key, transition to IDLE */
    DBGPRINT(DBG_ON(DBG_TRACE), ("DRCommandProc: DR_TITLE_KEY -- Done getting title key\n"));

    return (status);
}



/**
 * drParseDSI - parse the DSI packet
 *
 * @param dsi_packet   - output: the dsi packet as a struct
 * @param buf          - the buffer containing the dsi packet information
 *
 * @retval none
 *
 * @remarks none.
 */
const UCHAR DSI_STRT[] = {0x00, 0x00, 0x01, 0xBF, 0x03, 0xFA, 0x01};
inline DR_ERROR drParseDSI(dsipkt_struct &dsi_packet, UCHAR *buf)
{
    USHORT n;
    USHORT i;

    //DbgAssert(dsi_packet != NULL);
    DbgAssert(buf != NULL);

    /* check that we have proper header else bomb */
    for (n = 0; n < 7; n++)
    {
        if (buf[n] != DSI_STRT[n])
        {
            return (DR_FAILURE);
        }
    }

    /* parse the DSI_GI for a total of 32 bytes */
    n = 7;

    /* get NV_PCK_SCR */
    dsi_packet.dsi_gi.nv_pck_scr = MAKE_DWORD(&buf[n]);
    n += 4;

    /* get NV_PCK_LBN */
    dsi_packet.dsi_gi.nv_pck_lbn = MAKE_DWORD(&buf[n]);
    n += 4;

    /* get VOBU_EA */
    dsi_packet.dsi_gi.vobu_ea = MAKE_DWORD(&buf[n]);
    n += 4;

    /* get VOBU_1STREF_EA */
    dsi_packet.dsi_gi.vobu_1stref_ea = MAKE_DWORD(&buf[n]);
    n += 4;

    /* get VOBU_2NDREF_EA */
    dsi_packet.dsi_gi.vobu_2ndref_ea = MAKE_DWORD(&buf[n]);
    n += 4;

    /* get VOBU_3RDREF_EA */
    dsi_packet.dsi_gi.vobu_3rdref_ea = MAKE_DWORD(&buf[n]);
    n += 4;

    /* get VOBU_VOB_IDN */
    dsi_packet.dsi_gi.vobu_vob_idn = MAKE_WORD(&buf[n]);
    n += 3;     /* reserved byte follows VOBU_VOB_IDN */

    /* get VOBU_C_IDN */
    dsi_packet.dsi_gi.vobu_c_idn = buf[n];
    n += 1;

    /* dump Cell Elapse Time on the floor */
    n += 4;

    /* next parse the SML_PBI for a total of 148 bytes */

    /* starting with VOBU_SML_CAT */
    dsi_packet.sml_pbi.vobu_sml_cat = MAKE_WORD(&buf[n]);
    n += 2;     /* skip reserved byte */

    /* get ILVU_EA */
    dsi_packet.sml_pbi.ilvu_ea = MAKE_DWORD(&buf[n]);
    n += 4;

    /* get NXT_ILVU_SA */
    dsi_packet.sml_pbi.nxt_ilvu_sa = MAKE_DWORD(&buf[n]);
    n += 4;

    /* get NXT_ILVU_SZ */

⌨️ 快捷键说明

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