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

📄 ig_api.cpp

📁 这是DVD中伺服部分的核心代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    if (gWaitForFrame > 0)
    {
        gWaitForFrame--;
    }

    return (IG_STATUS_SUCCESS);
}


/**
 * IGScanForStartCode - 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 IG_STATUS
 */
IG_STATUS IGScanForStartCode(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 (IGInfo.CurPesInfo.StartCodeBuffSize > 0)
    {
        int TempCodeBytesLeft = IGInfo.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(&IGInfo.CurPesInfo.StartCodeBuff[IGInfo.CurPesInfo.StartCodeBuffSize], Buffer, 3);

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

                    /* clear pes header info */
                    memset(&IGInfo.CurPesInfo, 0, sizeof(PES_HDR_INFO));

                    return IG_STATUS_SUCCESS;
                }

                /* bytes left in start code */
                TempCodeBytesLeft--;
                StartCodeBase++;
            }
        }
        else
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("IGScanForStartCode(): UNHANDLED CASE IN IGScanForStartCode\n"));
            /* TODO: edge case
                we got a really small packet after the end of a pes packet, test what can be tested
            */
        }
    }

    /* spin and find the start code in the data */
    while (Index < SearchSize)
    {
        /* we Only accept private stream one data */
        if (PRIVATE_STREAM_1_START_CODE == MAKE_DWORD(&Buffer[Index]))
        {
            *Offset = Index+4;

            /* clear pes header info */
            memset(&IGInfo.CurPesInfo, 0, sizeof(PES_HDR_INFO));

            return IG_STATUS_SUCCESS;
        }

        /* next byte in buffer */
        Index++;
    }

    memcpy(IGInfo.CurPesInfo.StartCodeBuff, &Buffer[Index], Size-Index);
    IGInfo.CurPesInfo.StartCodeBuffSize = (BYTE)(Size-Index);

    return IG_STILL_SCANNING_SC;
}


/**
 * IGReadPESHeader - 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 *PESStart - the start of the PES header data
 * @param PES_HDR_INFO *Info - state information about the header
 *
 * @return IG_STATUS
 */
IG_STATUS IGReadPESHeader(BYTE *PESStart)
{
    IGInfo.CurPesInfo.PacketSize = MAKE_WORD(PESStart);
    IGInfo.CurPesInfo.SegAligned = PESStart[2] & BIT2;  /* is the segment aligned? */
    IGInfo.CurPesInfo.PTSDTSFlags = (PESStart[3] & (BIT6|BIT7)) >> 6;  /* value 2 is PTS_ONLY, value 3 is PTS_DTS */
    IGInfo.CurPesInfo.PesHeaderLen = PESStart[4];  /* length of the pes header */
    IGInfo.CurPesInfo.ESRemaining =  IGInfo.CurPesInfo.PacketSize - IGInfo.CurPesInfo.PesHeaderLen - 3;

    if (IGInfo.CurPesInfo.SegAligned == 0)
    {
        DBGPRINT(DBG_ON(DBG_ERROR), ("IGReadPESHeader(): IG Segment not aligned\n"));
        return IG_STATUS_ERROR;
    }

    if (PTS_ONLY == IGInfo.CurPesInfo.PTSDTSFlags)
    {
        /* get the PTS */
        IGInfo.CurPesInfo.PTS = MAKE_WORD(&PESStart[6]) >> 1;
        IGInfo.CurPesInfo.PTS = IGInfo.CurPesInfo.PTS << 14 | MAKE_WORD(&PESStart[8]) >> 2;
        IGInfo.CurPesInfo.PTS |= ((ULONG)(PESStart[5] & 0xe)) << 28;

        IGInfo.CurPesInfo.DTS = 0;
    }
    else if (PTS_AND_DTS == IGInfo.CurPesInfo.PTSDTSFlags)
    {
        /* get the PTS and DTS */
        IGInfo.CurPesInfo.PTS = MAKE_WORD(&PESStart[6]) >> 1;
        IGInfo.CurPesInfo.PTS = IGInfo.CurPesInfo.PTS << 14 | MAKE_WORD(&PESStart[8]) >> 2;
        IGInfo.CurPesInfo.PTS |= ((ULONG)(PESStart[5] & 0xe)) << 28;

        IGInfo.CurPesInfo.DTS = MAKE_WORD(&PESStart[11]) >> 1;
        IGInfo.CurPesInfo.DTS = IGInfo.CurPesInfo.DTS << 14 | MAKE_WORD(&PESStart[13]) >> 2;
        IGInfo.CurPesInfo.DTS |= ((ULONG)(PESStart[10] & 0xe)) << 28;
    }
    else
    {
        /* no pts or dts till given */
        IGInfo.CurPesInfo.DTS = 0;
        IGInfo.CurPesInfo.PTS = 0;
    }

    IGInfo.CurPesInfo.HeaderComplete = 1;

    return IG_STATUS_SUCCESS;
}


/**
 * IGWaitForSpaceAvail - see if there is linear space in the IGParseBuffer for Size bytes of data
 *
 * @param ULONG Size - number of bytes we need to be contiguous
 *
 * @return IG_STATUS
 */
IG_STATUS IGWaitForSpaceAvail(ULONG Size)
{
    /* check the current write pointer, if we are going to wrap then wrap */
    if ((IGInfo.PESWritePtr + Size) >= SIZE_IG_CODED_DATA_BUFFER)
    {
        DBGPRINT(DBG_ON(DBG_TRACE), ("Wrap rp=%d wp=%d size =%d\n", IGInfo.ParseReadPtr, IGInfo.PESWritePtr, Size));

        if (IGInfo.ParseReadPtr < IGInfo.PESWritePtr)
        {
            /* on wrap we would walk past read ptr, wait for read pointer to wrap */
            while ((IGInfo.ParseReadPtr <= (Size+1)) && (IGInfo.CurrentState == IG_STATE_RUNNING))
            {
                OS_TaskYield();
            }
        }
        else if (IGInfo.ParseReadPtr > IGInfo.PESWritePtr)
        {
            ULONG RP = IGInfo.ParseReadPtr;

            /* on wrap we would walk past read ptr, wait for read pointer to wrap */
            if ((IGInfo.PESWritePtr + Size) > IGInfo.ParseReadPtr)
            {
                /* wait for read pointer to wrap around here */
                while ((IGInfo.ParseReadPtr >= RP) && (IGInfo.CurrentState == IG_STATE_RUNNING))
                {
                    OS_TaskYield();
                }

                /* on wrap we would walk past read ptr, wait for read pointer to wrap */
                while ((IGInfo.ParseReadPtr <= (Size+1)) && (IGInfo.CurrentState == IG_STATE_RUNNING))
                {
                    OS_TaskYield();
                }
            }
        }
        else
        {
            DBGPRINT(DBG_ON(DBG_ERROR), ("IGWaitForSpaceAvail: buffer empty\n"));
        }

        /* wrap the write pointer */
        IGInfo.PESWritePtr = 1;
    }

    if (IGInfo.PESWritePtr < IGInfo.ParseReadPtr)
    {
        /* crossing over read boundry */
        if ((IGInfo.PESWritePtr + Size) >= IGInfo.ParseReadPtr)
        {
            /* wait for space in the parse buffer */
            while (((IGInfo.PESWritePtr + Size) >= IGInfo.ParseReadPtr) && (IGInfo.CurrentState == IG_STATE_RUNNING))
            {
                OS_TaskYield();

                /* if the read pointer gets lower than the write pointer, it must have wrapped */
                if (IGInfo.ParseReadPtr < IGInfo.PESWritePtr)
                {
                    /* spin wait for the read pointer to allow at least Size bytes in the buffer */
                    while ((IGInfo.ParseReadPtr < Size) && (IGInfo.CurrentState == IG_STATE_RUNNING))
                    {
                        OS_TaskYield();
                    }
                    break;
                }
            }
        }
    }

    //DBGPRINT(DBG_ON(DBG_VERBOSE), ("read %d write %d size %d\n", IGInfo.ParseReadPtr, IGInfo.PESWritePtr, Size));

    return IG_STATUS_SUCCESS;
}


/**
 * IGAssemblePesHeader - Try to read in a whole PES header worth of dat into our pes header parse buffer
 *
 * @param BYTE *Buffer - the data buffer with pes data
 * @param ULONG Size - the size of Buffer in bytes
 * @param USHORT *BytesRead - how many bytes we read from the buffer
 *
 * @return IG_STATUS
 */
IG_STATUS IGAssemblePesHeader(BYTE *Buffer, ULONG Size, USHORT *ReadBytes)
{
    ULONG BytesRead = 0;
    ULONG BytesLeft = Size;

    /*
    NOTE: to start off PES header parsing we Require 5 bytes of data to start, until we get
    that much we just copy into the temp buffer.  Once that data is available we can
    read out the size of the PES header, then we request the rest of the bytes to complete the
    header
    */

    while (IGInfo.CurPesInfo.HeaderNeedBytes)
    {
        /* try to get the number of bytes requested */
        if (IGInfo.CurPesInfo.HeaderNeedBytes <= BytesLeft)
        {
            //DBGPRINT(DBG_ON(DBG_TRACE), ("copying needed bytes %d\n", IGInfo.CurPesInfo.HeaderNeedBytes));
            memcpy(&IGInfo.CurPesInfo.PesHdrBuff[IGInfo.CurPesInfo.PesHdrIndex], &Buffer[BytesRead], IGInfo.CurPesInfo.HeaderNeedBytes);
            IGInfo.CurPesInfo.PesHdrIndex += IGInfo.CurPesInfo.HeaderNeedBytes; /* buffer index up */
            BytesLeft -= IGInfo.CurPesInfo.HeaderNeedBytes;  /* less bytes left */
            BytesRead += IGInfo.CurPesInfo.HeaderNeedBytes;  /* more bytes read */
        }
        else
        {
            /* buffer is too small, copy what we can and mark down the HeaderNeedBytes field */
            DBGPRINT(DBG_ON(DBG_TRACE), ("IGAssemblePesHeader(): buffer too small copy %d of %d\n", IGInfo.CurPesInfo.HeaderNeedBytes, IGInfo.CurPesInfo.PesHeaderLen));
            memcpy(&IGInfo.CurPesInfo.PesHdrBuff[IGInfo.CurPesInfo.PesHdrIndex], &Buffer[BytesRead], BytesLeft);
            IGInfo.CurPesInfo.PesHdrIndex += (USHORT)(BytesLeft);
            IGInfo.CurPesInfo.HeaderNeedBytes -= (BYTE)(BytesLeft);
            *ReadBytes = (USHORT)(BytesRead);
            return IG_MORE_DATA;
        }

        /* now analyze the data, do we have just 5 bytes? */
        if (IGInfo.CurPesInfo.PesHdrIndex == 5)
        {
            /* we need the rest of the pes header length */
            IGInfo.CurPesInfo.HeaderNeedBytes = IGInfo.CurPesInfo.PesHdrBuff[4];  /* this is the pes header length */
            IGInfo.CurPesInfo.PesHeaderLen = IGInfo.CurPesInfo.PesHdrBuff[4];
        }
        else
        {
            /* we have more, is it the whole pes packet? */
            if ((5 + IGInfo.CurPesInfo.PesHeaderLen) == IGInfo.CurPesInfo.PesHdrIndex)
            {
                /* we have the whole header */
                IGInfo.CurPesInfo.HeaderNeedBytes = 0;
                *ReadBytes = (USHORT)(BytesRead);
                return IG_STATUS_SUCCESS;
            }
            else
            {
                DBGPRINT(DBG_ON(DBG_TRACE), ("IGAssemblePesHeader(): we need more, header len is %d\n", IGInfo.CurPesInfo.PesHeaderLen));
                /* no we need more */
                continue;
            }
        }
    }

    DBGPRINT(DBG_ON(DBG_ERROR), ("IGAssemblePesHeader(): Exited Assemble PES header incorrectly\n"));

    return IG_STATUS_ERROR;
}


/**
 * IGAssembleSegmentData - Try to get the requested amount of segment bytes in the buffer
 *
 * @param BYTE *Buffer - the data buffer with pes data
 * @param ULONG Size - the size of Buffer in bytes
 * @param USHORT *BytesRead - how many bytes we read from the buffer
 *
 * @return IG_STATUS
 */
IG_STATUS IGAssembleSegmentData(BYTE *Buffer, ULONG Size, USHORT *ReadBytes)
{
    /* try to get the requested number of bytes for the segment header, if we can't get
    all the data return IG_MORE_DATA after copying what we can and updating pointers */
    if (IGInfo.CurPesInfo.NeedSegmentBytes <= Size)
    {
        /* get the number of bytes requested */
        memcpy(&(IGInfo.CurPesInfo.SegmentTemp[IGInfo.CurPesInfo.SegmentIndex]), Buffer, IGInfo.CurPesInfo.NeedSegmentBytes);
        IGInfo.CurPesInfo.SegmentIndex += IGInfo.CurPesInfo.NeedSegmentBytes; /* buffer index up */
        *ReadBytes = IGInfo.CurPesInfo.NeedSegmentBytes;
        IGInfo.CurPesInfo.NeedSegmentBytes = 0;  /* we read all that was requested */
        return IG_STATUS_SUCCESS;
    }
    else
    {
        /* buffer is too small, copy what we can and mark down the HeaderNeedBytes field */
        DBGPRINT(DBG_ON(DBG_TRACE), ("IGAssembleSegmentData(): Segment data buffer too small copy %d bytes\n", Size));
        memcpy(&IGInfo.CurPesInfo.SegmentTemp[IGInfo.CurPesInfo.SegmentIndex], &Buffer[0], Size);
        IGInfo.CurPesInfo.SegmentIndex += (BYTE)(Size);
        IGInfo.CurPesInfo.NeedSegmentBytes -= (BYTE)(Size);
        *ReadBytes = (USHORT)(Size);

        return IG_MORE_DATA;
    }
}


/**
 * IGAddParseMessage - Queue a message to the IGParse task for it to decode segment data
 *
 * @param BYTE *BufferStart - pointer to the segment data
 * @param ULONG BufferLength - the size of BufferStart in bytes
 *
 * @return IG_STATUS
 */
IG_STA

⌨️ 快捷键说明

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