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

📄 pg_parse.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    PGInfo.ParserPCS->VideoDesc.Height = MAKE_WORD(SegmentIndex+2);
    PGInfo.ParserPCS->VideoDesc.FrameRate = ((*(SegmentIndex+4)) & 0xF0) >> 4;
    SegmentIndex += SIZE_VIDEO_DESCRIPTOR;

    if (PGInfo.RLEHalfWidth == 1)
    {
        if ((PGInfo.ParserPCS->VideoDesc.Width == 1920) && (PGInfo.ParserPCS->VideoDesc.Height == 1080))
        {
            DBGPRINT(DBG_ON(DBG_TRACE), ("PG - CoordsHalfWidth TRUE\n"));
            PGInfo.CoordsHalfWidth = 1;
        }
        else
        {
            DBGPRINT(DBG_ON(DBG_TRACE), ("PG - CoordsHalfWidth FALSE\n"));
            PGInfo.CoordsHalfWidth = 0;
        }
    }
    else
    {
        PGInfo.CoordsHalfWidth = 0;
    }

    /* read in the composition descriptor */
    PGInfo.ParserPCS->CompDesc.CompositionNumber = MAKE_WORD(SegmentIndex);
    PGInfo.ParserPCS->CompDesc.CompositionState = ((*(SegmentIndex+2)) & 0xC0) >> 6;
    SegmentIndex += SIZE_COMPOSITION_DESCRIPTOR;

    /* account for epoch start, continue or acq points, if we haven't gotten one yet
     * and this is our first then it's ok to decode again */

    /* if the stream is not acquired yet, see if we got a ACQ Point or Epoch Start */
    if (0 == PGInfo.StreamAcquired)
    {
        if ((PGInfo.ParserPCS->CompDesc.CompositionState == COMP_STATE_ACQUISITION_POINT) ||
            (PGInfo.ParserPCS->CompDesc.CompositionState == COMP_STATE_EPOCH_START) ||
            (PGInfo.ParserPCS->CompDesc.CompositionState == COMP_STATE_EPOCH_CONT))
        {
            /* we got a valid acquisition point now */
            DBGPRINT(DBG_ON(DBG_TRACE), ("Stream Acquired\n"));
            PGInfo.StreamAcquired = 1;
        }
        else
        {
            /* this PCS may reference old data, do NOT keep it */
            DBGPRINT(DBG_ON(DBG_TRACE), ("Discard PCS\n"));
            OS_MemFree(PGInfo.ParserPCS);
            PGInfo.ParserPCS = NULL;
            return PG_STATUS_SUCCESS;
        }
    }

    /* if this is a new epoch, clear the screen and object buffers */
    if (COMP_STATE_EPOCH_START == PGInfo.ParserPCS->CompDesc.CompositionState)
    {
        BYTE ScreenUpdate = 0;

        /* NOTE:
           BD SPEC section 8.8.3.1.5, On the DTS of Epoch Start we clear all buffers and
           the Graphics plane, including what is on screen.

           DON'T CHANGE this without a spec change.
        */

        /* free the objects and palettes */
        OS_SemTake(PGInfo.RenderLock, OS_WAIT_FOREVER);

        PGGraphicsClearBuffer(&ScreenUpdate, 0);
        if (ScreenUpdate)
        {
            OS_TimerSet(PGInfo.PGFlipTimer, 1);
            OS_TaskYield();
        }
        if (PGInfo.RenderPCS)
        {
            ReleasePCS(PGInfo.RenderPCS);
            PGInfo.RenderPCS = NULL;
        }
        PGFreeObjects();

        OS_SemGive(PGInfo.RenderLock);
    }

    /* load the palette update flag */
    PGInfo.ParserPCS->PaletteUpdateFlag = ((*SegmentIndex) & BIT7) >> 7;

    /* get the palette id ref */
    PGInfo.ParserPCS->PaletteIDRef = *(SegmentIndex+1);

    /* get the number of composition objects */
    PGInfo.ParserPCS->NumCompositionObjects = *(SegmentIndex+2);
    SegmentIndex+=3;

    if (PGInfo.ParserPCS->NumCompositionObjects > 0)
    {
        /* malloc some space for the composition objects */
        PGInfo.ParserPCS->CompObjs =
            (COMPOSITION_OBJECT *)OS_MemAlloc(PGInfo.ParserPCS->NumCompositionObjects * sizeof(COMPOSITION_OBJECT));

        if (PGInfo.ParserPCS->CompObjs == NULL)
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("couldn't malloc space for pcs->comp_objs\n"));
            OS_MemFree(PGInfo.ParserPCS);
            PGInfo.ParserPCS = NULL;
            return PG_STATUS_ERROR;
        }

        /* load up the composition objects */
        PGLoadPCSCompObjs(SegmentIndex, PGInfo.ParserPCS, &MovesBytes);
    }

    /* the PTS the packet came in on is it's render time, note it should be rendered by this time */
    if ((PTS_ONLY == PTS_DTS_Flags) || (PTS_AND_DTS == PTS_DTS_Flags))
    {
        /* subtract 1 frame time from the pts, the flip should occur during this frame time */
        PGInfo.ParserPCS->PTSDisplayTime = PTS;
    }
    else
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("\nERROR, there is no PTS time given to the PCS from PES header\n"));
        PGInfo.ParserPCS->PTSDisplayTime = PGInfo.CurPTS; // render now
    }

    return (PG_STATUS_SUCCESS);
}


/**
 * PGLoadPCSCompObjs - decodes data from the PGParseBuffer into our object lists
 *
 * @param BYTE *DataStart - pointer to the composition object data
 * @param PCS *pcs - the Presentation Compostion Object we are working one
 * @param ULONG *MovedBytes - return the number of bytes read in this ptr to caller
 *
 * @return PG_STATUS
 */
PG_STATUS PGLoadPCSCompObjs(BYTE *DataStart, PRESENTATION_COMPOSITION_SEGMENT *Pcs, ULONG *MovedBytes)
{
    BYTE *ObjIndex = DataStart;

    /* load all the composition objects */
    for (int i=0; i<Pcs->NumCompositionObjects; i++)
    {
        Pcs->CompObjs[i].ObjectIDRef = MAKE_WORD(ObjIndex);
        Pcs->CompObjs[i].WindowIDRef = *(ObjIndex+2);
        Pcs->CompObjs[i].CroppedFlag = ((*(ObjIndex+3)) & BIT7) >> 7;
        Pcs->CompObjs[i].ForcedOnFlag = ((*(ObjIndex+3)) & BIT6) >> 6;
        Pcs->CompObjs[i].XPosition = MAKE_WORD(ObjIndex+4);
        Pcs->CompObjs[i].YPosition = MAKE_WORD(ObjIndex+6);

        /* if the image is cropped we will have a flag here */
        if (Pcs->CompObjs[i].CroppedFlag)
        {
            /* load the cropping rectangle */
            Pcs->CompObjs[i].Rect.X = MAKE_WORD(ObjIndex+8);
            Pcs->CompObjs[i].Rect.Y = MAKE_WORD(ObjIndex+10);
            Pcs->CompObjs[i].Rect.Width = MAKE_WORD(ObjIndex+12);
            Pcs->CompObjs[i].Rect.Height = MAKE_WORD(ObjIndex+14);

            /* move the size of a comp obj with a cropping rect (stream size not stored struct size) */
            ObjIndex += SIZE_COMPOSITION_OBJECT;
        }
        else
        {
            /* move the size of a comp obj without a cropping rect (stream size not stored struct size) */
            ObjIndex += SIZE_COMPOSITION_OBJECT - SIZE_CROPPING_RECTANGLE;
        }

        /* set the PCS forced flag so we know this PCS contains a forced composition */
        if (Pcs->CompObjs[i].ForcedOnFlag)
        {
            Pcs->fPCSHasForced = 1;
        }

        /* checks for Composition Object Validity */
        if (Pcs->CompObjs[i].ObjectIDRef > PG_MAX_ODS)
        {
            DbgPrint(("Invalid Composition Object, referencing ObjectId %d\n", Pcs->CompObjs[i].ObjectIDRef));
            break;
        }

        if (Pcs->CompObjs[i].WindowIDRef > MAX_WINDOWS)
        {
            DbgPrint(("Invalid Composition Object, referencing WindowId %d\n", Pcs->CompObjs[i].WindowIDRef));
            break;
        }
    }

    *MovedBytes = ObjIndex - DataStart;

    return PG_STATUS_SUCCESS;
}


/**
 * PGLoadPalette - load a palette into the palettes array
 *
 * @param BYTE *DataStart - pointer to the start of the palette
 * @param ULONG DataLength - size of DataStart in bytes
 *
 * @return PG_STATUS
 */
PG_STATUS PGLoadPalette(BYTE *DataStart, ULONG DataLength)
{
    /* use the segment length to determine the number of colors */
    BYTE *PalPtr = DataStart+2;
    PALETTE *CurPal = NULL;
    int PaletteNumber = *(DataStart);
    int NumEntries;
    BYTE fClearPalette=0;

    if (PGInfo.CurrentState != PG_STATE_RUNNING)
    {
        return PG_STATUS_SUCCESS;
    }

    /* make sure this palette number doesn't overrun memory */
    if (PaletteNumber >= PG_MAX_PALETTES)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("Invalid palette index, palette not parsed\n"));
        return PG_STATUS_ERROR;
    }

    /* select the proper palette in the arrays */
    CurPal = &PGPalettes[PaletteNumber];

    /* load pg palette with this */
    CurPal->PaletteVersion = *(DataStart+1);

    /* calculate the number of entries, if the diviosion rounds data incorrectly the palette is
    wrong anyway and we will miss some entries at the end */
    NumEntries = (DataLength-2) / SIZE_PALETTE_ENTRY;

    /* check that the palette entries are all filled up */
    if (((DataLength-2) % SIZE_PALETTE_ENTRY) != 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("Palette entries not complete\n"));
        return PG_STATUS_SUCCESS;
    }

    if (PGInfo.ParserPCS)
    {
        if (COMP_STATE_NORMAL == PGInfo.ParserPCS->CompDesc.CompositionState)
        {
            fClearPalette = 0;
        }
        else
        {
            fClearPalette = 1;
        }
    }

    /* create the dfb palette */
    if (PGGraphicsSetPaletteColors(PaletteNumber, PalPtr, NumEntries, fClearPalette, PGInfo.ColorSpace) != PG_STATUS_SUCCESS)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("Failed to set palette colors in DFB Palette\n"));
        return PG_STATUS_ERROR;
    }

    return PG_STATUS_SUCCESS;
}


/**
 * PGLoadObject - load a object into the PGObjList
 *
 * @param BYTE *DataStart - pointer to the start of the object
 * @param ULONG DataLength - size of DataStart in bytes
 *
 * @return PG_STATUS
 */
PG_STATUS PGLoadObject(BYTE *DataStart, ULONG DataLength)
{
    int ObjectID = MAKE_WORD(DataStart);
    int VersionNumber = *(DataStart + 2);
    int OutputSize;
    BYTE DoUpdate = 0;
    BYTE *ObjStart = DataStart;
    void *ImgData;
    OBJECT_DEFINITION_SEGMENT *CurObj;
    PG_STATUS status;
#ifdef ALLOW_PG_PROFILING
    ULONG TickStart = 0;
#endif

    if (PGInfo.CurrentState != PG_STATE_RUNNING)
    {
        return PG_STATUS_SUCCESS;
    }

    if (ObjectID >= PG_MAX_ODS)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("PGLoadObject: ObjectID to large %d\n", ObjectID));
        return PG_STATUS_ERROR;
    }

    /* the current object for easy access */
    CurObj = &PGObjList[ObjectID];

    /* if the object is in use, check it's version number to see if we need an update */
    if (CurObj->InUse)
    {
        if (CurObj->VersionNumber < VersionNumber)
        {
            DBGPRINT(DBG_ON(DBG_TRACE), ("PGLoadObject: Update object new=%d, current=%d\n", VersionNumber, CurObj->VersionNumber));
            DoUpdate = 1;
        }
        else
        {
            DBGPRINT(DBG_ON(DBG_TRACE), ("PG: PGLoadObject image has same or lower version number\n"));
            return PG_STATUS_SUCCESS;
        }
    }

    /*
        load the object definition segment
    */

    /* read the object id */
    CurObj->VersionNumber = VersionNumber;
    ObjStart+=3;

    /* get sequence flags, these won't be accurate for mulitPES segments */
    CurObj->SeqDesc.FirstInSequenceFlag = ((*ObjStart) & BIT7) >> 7;
    CurObj->SeqDesc.LastInSequenceFlag = ((*ObjStart) & BIT6) >> 6;
    ObjStart++;

    /* read the object data fragment */
    CurObj->ObjData.DataLength = (*ObjStart) << 16 | ((*(ObjStart+1)) << 8) | (*(ObjStart+2));
    CurObj->ObjData.Width = MAKE_WORD(ObjStart+3);  /* could add paranoia check here on do_update */
    CurObj->ObjData.Height = MAKE_WORD(ObjStart+5); /* could add paranoia check here on do_update */
    ObjStart+=7;

    /* how big is the image? */
    OutputSize = CurObj->ObjData.Width * CurObj->ObjData.Height;

    /* is the output size bigger then the video size, if so error */
    if (OutputSize > 1920*1080)
    {
        CurObj->VersionNumber = 0;
        DBGPRINT(DBG_ON(DBG_ERROR), ("The Image Size is too large\n"));
        return PG_STATUS_ERROR;
    }

    /* make sure we have the correct amount of data, (the DataLength - header = correct Object Data length)*/
    if ((DataLength - 7) != CurObj->ObjData.DataLength)
    {
        DbgPrint(("PGLoadObject does not have the correct amount of data, Datalength-7 = %d Datalength = %d\n",
            DataLength-7, CurObj->ObjData.DataLength));
        CurObj->VersionNumber = 0;
        return PG_STATUS_ERROR;
    }

⌨️ 快捷键说明

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