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

📄 pg_api.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
                        if (0xFFFF == PGInfo.CurPesInfo.PacketSize)
                        {
                            PGInfo.CurPesInfo.NeedSegmentBytes = ODS_HEADER_SIZE;
                            PGInfo.CurPesInfo.SegmentIndex = 0;
                        }
                        else
                        {
                            /* else: not full packet and we aren't currently coping multipes so can't be multipes */
                            /* make sure we have room for the packet */
                            PGWaitForSpaceAvail(PGInfo.CurPesInfo.PacketSize);
                            if (PGInfo.CurrentState != PG_STATE_RUNNING)
                            {
                                OS_SemGive(PGInfo.StateLock);
                                return PG_STATUS_ERROR;
                            }
                        }
                    }
                    else
                    {
                        /* we are already copying multipes, we need to look instead for the last in sequence flag,
                        we don't care if the packet is a full 0xffff or not, last_in_sequence will tell us we are done */
                        PGInfo.CurPesInfo.NeedSegmentBytes = ODS_HEADER_SIZE_NO_FRAGMENT;
                        PGInfo.CurPesInfo.SegmentIndex = 0;
                    }

                    /* move ahead */
                    BytesRead += AssembleBytesRead;
                    BytesLeft -= AssembleBytesRead;
                    AssembleBytesRead = 0;
                }
                else if (PG_MORE_DATA == RetCode)
                {
                    DBGPRINT(DBG_ON(DBG_TRACE), ("Need more data\n"));

                    /* need more data to finish pes header */
#ifdef ALLOW_PG_PROFILING
                    if (1 == PGStats.Profiling)
                    {
                        PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
                    }
#endif

                    OS_SemGive(PGInfo.StateLock);
                    return PG_STATUS_SUCCESS;
                }
                else
                {
                    DBGPRINT(DBG_ON(DBG_ERROR), ("pg error adddata\n"));
                    /* error */
                    PGClearAddDataVars();
#ifdef ALLOW_PG_PROFILING
                    if (1 == PGStats.Profiling)
                    {
                        PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
                    }
#endif

                    OS_SemGive(PGInfo.StateLock);
                    return PG_STATUS_ERROR;
                }
            }

            /* we have a multipes segment to handle, get all the bytes of a segment header and buffer
            them, don't continue until we have enough to parse */
            if (PGInfo.CurPesInfo.NeedSegmentBytes)
            {
                RetCode = PGAssembleSegmentData(&Buffer[BytesRead], BytesLeft, &AssembleBytesRead);
                if (PG_STATUS_SUCCESS == RetCode)
                {
                    /* we got the whole segment, make sure it's an object defintion segment */
                    if (OBJECT_DEFINITION != PGInfo.CurPesInfo.SegmentTemp[0])
                    {
                        DBGPRINT(DBG_ON(DBG_TRACE), ("This data is incorrect, the data must be a Object Definition Segment, skip data to sync\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;   // we got data but it wrong, who's error? and we shouldn't stop so no error
                    }
                }
                else if (PG_MORE_DATA == RetCode)
                {
                    /* we need more data */
                    BytesRead -= AssembleBytesRead;
#ifdef ALLOW_PG_PROFILING
                    if (1 == PGStats.Profiling)
                    {
                        PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
                    }
#endif

                    OS_SemGive(PGInfo.StateLock);
                    return PG_STATUS_SUCCESS;
                }

                /*
                    if we get here we have a full segment buffer
                */

                /* grab the sequence descriptor */
                PGInfo.SequenceDesc = PGInfo.CurPesInfo.SegmentTemp[6];

                /* we haven't copied the first of a multipes packet yet */
                if (FIRST_IN_SEQUENCE & PGInfo.SequenceDesc)
                {
                    /*
                        this is the first in a seqence of pes packets
                    */

                    /* if this occurs while we are waiting for a last in sequence,
                    we will lose the previous data which is what we want since
                    there must have been some data corruption anyway... */

                    /* now the size of the object, we need linear space for this */
                    ObjectDataSize = (PGInfo.CurPesInfo.SegmentTemp[7] << 16) |
                                     (PGInfo.CurPesInfo.SegmentTemp[8] << 8)  |
                                      PGInfo.CurPesInfo.SegmentTemp[9];

                    /* copy the whole header - 4 bytes for width and height of ODS */
                    ObjectDataSize += ODS_HEADER_SIZE - 4;

                    /* get space for this data */
                    PGWaitForSpaceAvail(ObjectDataSize);
                    if (PGInfo.CurrentState != PG_STATE_RUNNING)
                    {
                        OS_SemGive(PGInfo.StateLock);
                        return PG_STATUS_ERROR;
                    }

                    /* copy over the segment header data to the PGParseBuffer */
                    memcpy(&PGInfo.PGParseBuffer[PGInfo.PESWritePtr], &Buffer[BytesRead], PGInfo.CurPesInfo.SegmentIndex);
                    PGInfo.PESWriteStart = PGInfo.PESWritePtr;
                    PGInfo.PESWritePtr += PGInfo.CurPesInfo.SegmentIndex;

                    /* we are now copying multipes data */
                    PGInfo.CopyingMultiPES = 1;
                    PGInfo.fGotStartPtr = 1;
                }

                /* say that we read the data */
                PGInfo.CurPesInfo.ESRemaining -= PGInfo.CurPesInfo.SegmentIndex;
                PGInfo.CurPesInfo.SegmentIndex = 0; /* segment header is read */

                /* how much we read from the current packet must be removed from what's left */
                BytesLeft -= AssembleBytesRead;
                BytesRead += AssembleBytesRead;

                /*  now copy out the data in the PES buffer, as much as we can, either the
                    rest of the PES packet or the rest of the AddData buffer */
                LeftToCopy = MIN(PGInfo.CurPesInfo.ESRemaining, BytesLeft);

                /* copy what ES data we can here */
                memcpy(&PGInfo.PGParseBuffer[PGInfo.PESWritePtr], &Buffer[BytesRead], LeftToCopy);
                PGInfo.PESWritePtr += LeftToCopy;   /* push up the write pointer */
                PGInfo.CurPesInfo.ESRemaining -= LeftToCopy; /* remove some byte from esremaining */
                BytesLeft -= LeftToCopy;        /* less bytes left */
                BytesRead += LeftToCopy;        /* more bytes read */

                /* very very edge case that for some reason there was a full
                PES packet 0xffff but the first and last in sequence flags were still set */
                if (0 == PGInfo.CurPesInfo.ESRemaining)
                {
                    if (LAST_IN_SEQUENCE & PGInfo.SequenceDesc)
                    {
                        //DBGPRINT(DBG_ON(DBG_TRACE), ("@@Multi-pes got last in sequence, start 0x%x, size %d\n", PGInfo.PESWriteStart, PGInfo.PESWritePtr - PGInfo.PESWriteStart));
                        /* tell the parser to start decoding a segment */
                        PGAddParseMessage(  PGInfo.PESWriteStart,
                                            PGInfo.PESWritePtr - PGInfo.PESWriteStart,
                                            PGInfo.CurPesInfo.DTS,
                                            PGInfo.CurPesInfo.PTS,
                                            PGInfo.CurPesInfo.PTSDTSFlags,
                                            1);

                        /* not copying a pes packet right now */
                        PGInfo.CopyingPES = 0;
                        PGInfo.CopyingMultiPES = 0;
                        PGInfo.fGotStartPtr = 0;
                    }
                }
                else
                {
                    continue;  /* not done yet */
                }
            }
            else  /* this is the rest of some ES data, could be multipes packets  */
            {
                LeftToCopy = MIN(PGInfo.CurPesInfo.ESRemaining, BytesLeft);

                /* copy a packet, it may or may not be all here */
                memcpy(&PGInfo.PGParseBuffer[PGInfo.PESWritePtr], &Buffer[BytesRead], LeftToCopy);

                /* if we haven't gotten the start ptr yet get it */
                if (0 == PGInfo.fGotStartPtr)
                {
                    /* if we are just continuing a copy we don't reget the write ptr */
                    PGInfo.PESWriteStart = PGInfo.PESWritePtr;  /* data start */
                    PGInfo.fGotStartPtr = 1;
                }

                /* update pointers */
                PGInfo.PESWritePtr += LeftToCopy;               /* bump the write ptr */
                BytesRead += LeftToCopy;                        /* we read this much data */
                BytesLeft -= LeftToCopy;                        /* we read this much data */
                PGInfo.CurPesInfo.ESRemaining -= LeftToCopy;    /* copied ES data */

                /* are we done with the PES packet */
                if (PGInfo.CurPesInfo.ESRemaining)
                {
                    //DBGPRINT(DBG_ON(DBG_TRACE), ("EsRemain is %d, copying pes %d, multipes %d, BytesRead %d BytesLeft %d, PES Size %d, ParsePacketSize %d\n",
                    //    PGInfo.CurPesInfo.ESRemaining, PGInfo.CopyingPES, PGInfo.CopyingMultiPES,
                    //    BytesRead, BytesLeft, PGInfo.CurPesInfo.PacketSize, PGInfo.PESWritePtr - PGInfo.PESWriteStart));
                    continue; /* no we need more */
                }
                else /* yes */
                {
                    if (0 == PGInfo.CopyingMultiPES)
                    {
                        /* tell the parser to start decoding a segment */
                        PGAddParseMessage(  PGInfo.PESWriteStart,
                                            PGInfo.PESWritePtr - PGInfo.PESWriteStart,
                                            PGInfo.CurPesInfo.DTS,
                                            PGInfo.CurPesInfo.PTS,
                                            PGInfo.CurPesInfo.PTSDTSFlags,
                                            0);

                        /* not copying a pes packet right now */
                        PGInfo.CopyingPES = 0;
                        PGInfo.fGotStartPtr = 0;
                    }
                    else
                    {
                        if (LAST_IN_SEQUENCE & PGInfo.SequenceDesc)
                        {
                            /* tell the parser to start decoding a segment */
                            PGAddParseMessage(  PGInfo.PESWriteStart,
                                                PGInfo.PESWritePtr - PGInfo.PESWriteStart,
                                                PGInfo.CurPesInfo.DTS,
                                                PGInfo.CurPesInfo.PTS,
                                                PGInfo.CurPesInfo.PTSDTSFlags,
                                                1);

                            /* not copying a pes packet right now */
                            PGInfo.CopyingPES = 0;
                            PGInfo.CopyingMultiPES = 0;
                            PGInfo.fGotStartPtr = 0;
                        }
                    }
                }
            }
        }  /* copyingpes */

        /*
            2. look for sync
        */
        if (PG_STATUS_SUCCESS != PGScanForStartCode(&Buffer[BytesRead], BytesLeft, &StartCodeOffset))
        {
            /* couldn't get sync on the rest of the packet */
#ifdef ALLOW_PG_PROFILING
            if (1 == PGStats.Profiling)
            {
                PGStats.PGTotalAddDataTicks += OS_GetTicks() - TickStart;
            }
#endif

            OS_SemGive(PGInfo.StateLock);
            return PG_STATUS_SUCCESS;
        }

        /* assemble the PES header, we need 5 bytes to start */
        PGInfo.CurPesInfo.HeaderNeedBytes = 5;
        PGInfo.CopyingPES = 1;
        BytesLeft -= StartCodeOffset;
        BytesRead += StartCodeOffset;
    }

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

    OS_SemGive(PGInfo.StateLock);
    return PG_STATUS_SUCCESS;
}


/**
 * PGSetColorSpace - set the color space for PG to 601 or 709
 *
 * @param IG_HANDLE handle - handle to the PG module
 * @param int ColorSpace - number indicating colorspace
 *
 * @return IG_STATUS
 */
PG_STATUS PGSetColorSpace(PG_HANDLE handle, int ColorSpace)
{
    if (handle != (PVOID)PG_HANDLE_VALUE)
    {
        return (PG_STATUS_INVALID_HANDLE);
    }

    /* store the color space */
    if (ColorSpace == 0)
    {
        PGInfo.ColorSpace = REC_601;
    }
    else
    {
        PGInfo.ColorSpace = REC_709;
    }

    return PG_STATUS_SUCCESS;
}

/**
 * PGUpdateTimeStamp - Queue a message to the PGParse task for it to decode segment data
 *
 * @param PG_HANDLE handle - handle to the PG module
 * @param ULONG PTS - The current Presentation Time Stamp
 * @param ULONG SCR - The current System Clock Reference
 *
 * @return PG_STATUS
 */
PG_STATUS PGUpdateTimeStamp(PG_HANDLE handle, ULONG PTS, ULONG SCR)
{
    if (handle != (PVOID)PG_HANDLE_VALUE)
    {
        return PG_STATUS_INVALID_HANDLE;
    }

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

    if (PTS == 0xFFFFFFFF)
    {
        //DbgPrint(("PGUpdateTimeStamp: Invalid PTS\n"));
        return PG_STATUS_ERROR;
    }

    PGInfo.CurPTS = PTS;

    /* Renderer waiting? */
    if (PGInfo.RenderWait.WaitTime.Enabled)
    {
        if (PGInfo.CurPTS >= PGInfo.RenderWait.WaitTime.WaitPTS)
        {
            OS_SemGive(PGInfo.RenderWait.WaitSem);
        }
    }

    /* Parser waiting? */
    if (PGInfo.ParseWait.WaitTime.Enabled)
    {
        if (PGInfo.CurPTS >= PGInfo.ParseWait.WaitTime.WaitPTS)
        {
            //DBGPRINT(DBG_ON(DBG_TRACE), ("PGUpdateTimeStamp Kick ParseWait() 0x%x\n", PGInfo.CurPTS));
            OS_SemGive(PGInfo.ParseWait.WaitSem);
        }
    }

    return PG_STATUS_SUCCESS;
}


/**
 * PGScanForStartCode - scan the buffer given for a start code, if a start code overlaps
 *                  the buffer we save the last few bytes of the previous so we can find it
 *
 * @param BYTE *Buffer - Data buffer to search
 * @param ULONG Size - Size of the Buffer in bytes
 * @param ULONG *Offset - Offset index into the Buffer where data is found, this is always the first
 *                        byte after the start code
 *
 *
 * @return PG_STATUS
 */
PG_STATUS PGScanForStartCode(BYTE *Buffer, ULONG Size, ULONG *Offset)
{
    int Index=0;
    int SearchSize = Size-SIZE_START_CODE+1;

    /* scan for the 4 byte pes header private stream 1 and return the index into the buffer where
    it was found, if it was across two buffer boundries then mark the EndOfCode flag as 1 and
    return in the Offset the byte right after the start code
    */

    /* if we were in the middle of scanning for start codes lets finish */
    if (PGInfo.CurPesInfo.StartCodeBuffSize > 0)
    {
        int TempCodeBytesLeft = PGInfo.CurPesInfo.StartCodeBuffSize;
        int StartCodeBase = 0;

        /* we have a 6 byte copy buffer for start codes, copy x bytes from the param Buffer
        into a logical ending place in the gTempStartCode buffer and create and test
        a start code, if it's good, mark the EndOfCode flag and return the Offset
        as the byte after the start code */

        if (Size >= (SIZE_START_CODE-1))
        {
            /* copy a few bytes from the front of the new buffer to the temp buffer and look
            for a start code */
            memcpy(&PGInfo.CurPesInfo.StartCodeBuff[PGInfo.CurPesInfo.StartCodeBuffSize], Buffer, 3);

            for (int i=PGInfo.CurPesInfo.StartCodeBuffSize; i > 0; i--)
            {
                /* a start code across buffer boundries ? */
                if (PRIVATE_STREAM_1_START_CODE == MAKE_DWORD(&PGInfo.CurPesInfo.StartCodeBuff[StartCodeBase]))
                {
                    DBGPRINT(DBG_ON(DBG_TRACE), ("Found start code across boundry\n"));
                    *Offset = SIZE_START_CODE-TempCodeBytesLeft;

⌨️ 快捷键说明

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