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

📄 umc_avi_splitter.cpp

📁 audio-video-codecs.rar语音编解码器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            // ascend from avi_ or avix
            m_AviChunkReader.Ascend();
            // look for AVIX list type at next loop
            bExtension = true;
        }
    }
    else
    {
        for (i = 0; i < m_AviHdr.uiStreams; i++)
        {
            if (AVI_FOURCC_auds == m_pTrack[i].m_StreamHeader.fccType ||
                AVI_FOURCC_vids == m_pTrack[i].m_StreamHeader.fccType ||
                AVI_FOURCC_iavs == m_pTrack[i].m_StreamHeader.fccType ||
                AVI_FOURCC_ivas == m_pTrack[i].m_StreamHeader.fccType)
                InitIndexUsingNewAVIIndex(i, m_pTrack[i].m_pIndex, m_pTrack[i].m_uiIndexSize);
        }
    }

    return UMC_OK;
}

Status AVISplitter::InitIndexUsingOldAVIIndex(Ipp8u *pIndexBuffer, Ipp32s nIndexSize,
    Ipp64u nMoviChunkStartAddr, Ipp64u /*nMoviChunkEndAddr*/)
{
    const Ipp32s BYTES_PER_ENTRY = 16;
    Ipp32s nTotalEntry = nIndexSize/BYTES_PER_ENTRY;
    Ipp32s i;

    // members of avi index entry
    Ipp32u nChunkID = 0;
    Ipp32u nFlag = 0;
    Ipp32u nOffset = 0;
    Ipp32u nLength = 0;

    // do a quick check if the content contains VBR audio
    if (!m_bCheckVBRAudio)
    {
        m_bCheckVBRAudio = true;

        bool bAudioPresent = false;
        for (i = 0; i < (Ipp32s)m_AviHdr.uiStreams && !bAudioPresent; i++)
            if (AVI_FOURCC_auds == m_pTrack[i].m_StreamHeader.fccType)
                bAudioPresent = true;

        if (bAudioPresent)
        {
            Ipp8u *pTemp = pIndexBuffer;
            Ipp32s iAudioSampleChecked = 0;
            // check up to 100 audio samples in the first fragment to determine VBR or CBR audio
            const Ipp32s MAX_AUDIO_SAMPLE_TO_CHECK = 100;
            for (i = 0; i < nTotalEntry; i++)
            {
                nChunkID = *(Ipp32u*)pTemp;
                Ipp32u uiTrackNum = GetTrackId(nChunkID);

                // 16 bytes per entry
                nLength = *(Ipp32u*)(pTemp + 12);
                pTemp += BYTES_PER_ENTRY;

                if (uiTrackNum > m_AviHdr.uiStreams || !IsAudio(nChunkID))
                    continue;

                if (nLength < ((WaveFormatEx *)m_pTrack[uiTrackNum].m_pStreamFormat)->nBlockAlign)
                {
                    m_bIsVBRAudio = true;
                    break;
                }
                iAudioSampleChecked++;
                if (iAudioSampleChecked > MAX_AUDIO_SAMPLE_TO_CHECK)
                {
                    // Limit reached, stop checking. Assuming it is CBR audio.
                    break;
                }
            }
        }
    }

    Ipp32u uiTrackNum = 0;
    Ipp64f *pTimeStamp = new Ipp64f[m_AviHdr.uiStreams];
    bool bIsVideoTrack = true;
    bool bAbsoluteOffset = true;
    Ipp32u *pSize = new Ipp32u[m_AviHdr.uiStreams];
    TrackIndex *pTrackIndex;
    IndexFragment *pFrag = new IndexFragment[m_AviHdr.uiStreams];
    IndexEntry *pEntry;
    Ipp32u *pCounter = new Ipp32u[m_AviHdr.uiStreams];
    bool *pIsFirstFrame = new bool[m_AviHdr.uiStreams];

    for (i = 0; i < (Ipp32s)m_AviHdr.uiStreams; i++)
    {
        pTimeStamp[i] = 0.0;
        pSize[i] = 0;
        pCounter[i] = 0;
        pIsFirstFrame[i] = true;
    }

    for (i = 0; i < nTotalEntry; i++)
    {
        nChunkID = *(Ipp32u *)pIndexBuffer;
        pIndexBuffer += 4;
        uiTrackNum = GetTrackId(nChunkID);
        if (uiTrackNum >= m_AviHdr.uiStreams)
        {
            pIndexBuffer += 12;
            continue;
        }

        // initialize these variables based on track index
        bIsVideoTrack = !IsAudio(nChunkID);

        pTrackIndex = &m_pTrackIndex[uiTrackNum];

        nFlag = *(Ipp32u *)pIndexBuffer;
        pIndexBuffer += 4;
        // offset includes 8 bytes of chunk header
        nOffset = *(Ipp32u *)pIndexBuffer;
        pIndexBuffer += 4;

        // length does not include 8 bytes of chunk header
        nLength = *(Ipp32u *)pIndexBuffer;
        pIndexBuffer += 4;

        if (i == 0)
        {
            bAbsoluteOffset = nOffset > nMoviChunkStartAddr;
        }

        if ((Ipp32s)pCounter[uiTrackNum] >= pFrag[uiTrackNum].iNOfEntries)
        { // fragment is full
            if (pFrag[uiTrackNum].iNOfEntries > 0 && pFrag[uiTrackNum].pEntryArray)
                pTrackIndex->Add(pFrag[uiTrackNum]);

            // estimated total samples, will be adjusted at the end
            pFrag[uiTrackNum].iNOfEntries = (nTotalEntry - i) / m_AviHdr.uiStreams + 1;
            if (pFrag[uiTrackNum].iNOfEntries < 100)
                pFrag[uiTrackNum].iNOfEntries = 100;

            pCounter[uiTrackNum] = 0;
            pFrag[uiTrackNum].pEntryArray = new IndexEntry[pFrag[uiTrackNum].iNOfEntries];
            if (NULL == pFrag[uiTrackNum].pEntryArray)
                return UMC_ERR_ALLOC;
        }

        pTimeStamp[uiTrackNum] += GetSampleDuration(bIsVideoTrack, m_bIsVBRAudio,
            (Ipp64f)(m_pTrack[uiTrackNum].m_StreamHeader.uiScale) / m_pTrack[uiTrackNum].m_StreamHeader.uiRate,
            ((WaveFormatEx *)m_pTrack[uiTrackNum].m_pStreamFormat)->nBlockAlign,
            nLength);

        pEntry = &pFrag[uiTrackNum].pEntryArray[pCounter[uiTrackNum]];
        pEntry->uiSize = pSize[uiTrackNum] = nLength;
        if (nLength > m_pTrack[uiTrackNum].m_uiMaxSampleSize)
            m_pTrack[uiTrackNum].m_uiMaxSampleSize = nLength;

        pEntry->dDts = -1.0;
        if (pIsFirstFrame[uiTrackNum])
        {
            // Start time, usually it is zero, but it can specify a delay time for
            // a stream that does not start concurrently with the file.
            pIsFirstFrame[uiTrackNum] = false;
            pEntry->dPts = m_pTrack[uiTrackNum].m_StreamHeader.uiStart *
                  (Ipp64f)(m_pTrack[uiTrackNum].m_StreamHeader.uiScale) /
                           m_pTrack[uiTrackNum].m_StreamHeader.uiRate;
        }
        else
        {
            pEntry->dPts = pTimeStamp[uiTrackNum];
        }

        // check index flag
        if (nFlag & AVIIF_KEYFRAME)
            pEntry->uiFlags = I_PICTURE;

        if ((nFlag & AVIIF_FIRSTPART) || (nFlag & AVIIF_LASTPART))
        {
            vm_debug_trace(VM_DEBUG_ERROR, __VM_STRING("WARNING: AVI index has FIRSTPART or LASTPART flag set!\n"));
        }

        if (nFlag & AVIIF_NO_TIME)
        {
            vm_debug_trace(VM_DEBUG_ERROR, __VM_STRING("WARNING: AVI index has NO_TIME flag set!\n"));
        }

        pEntry->stPosition = nOffset + 8; // 8 bytes of chunk header
        if (!bAbsoluteOffset)
            pEntry->stPosition += (size_t)nMoviChunkStartAddr;

        pCounter[uiTrackNum]++;
    }

    for (i = 0; i < (Ipp32s)m_AviHdr.uiStreams; i++)
    {
        if (pCounter[i] > 0)
        {
            pFrag[i].iNOfEntries = pCounter[i];
            m_pTrackIndex[i].Add(pFrag[i]);
        }
    }

    delete[] pTimeStamp;
    delete[] pSize;
    delete[] pCounter;
    delete[] pFrag;
    delete[] pIsFirstFrame;
    return UMC_OK;
}

Status AVISplitter::InitIndexUsingNewAVIIndex(Ipp32u nTrackNum, Ipp8u *pIndexBuffer, Ipp32s nIndexSize)
{
    Status umcRes = UMC_OK;
    Ipp8u *buf = pIndexBuffer;

    Ipp16u wLongsPerEntry = *(Ipp16u *)buf;
    wLongsPerEntry = BIG_ENDIAN_SWAP16(wLongsPerEntry);
    buf += 2;

    buf += 1; // skip bIndexSubType

    Ipp8u bIndexType = *(Ipp8u *)buf;
    buf += 1;

    Ipp32u nEntriesInUse = *(Ipp32u *)buf;
    nEntriesInUse = BIG_ENDIAN_SWAP32(nEntriesInUse);
    buf += 4;

    buf += 4; // skip dwChunkId

    Ipp64u qwBaseOffset = 0;
    if (bIndexType == AVI_INDEX_OF_CHUNKS || bIndexType == AVI_INDEX_OF_SUB_2FIELD)
    {
        // low half of qwBaseOffset
        ((Ipp32u *)&qwBaseOffset)[0] = *(Ipp32u *)buf;
        buf += 4;

        // high half of qwBaseOffset
        ((Ipp32u *)&qwBaseOffset)[1] = *(Ipp32u *)buf;
        qwBaseOffset = BIG_ENDIAN_SWAP64(qwBaseOffset);
        buf += 4;

        buf += 4; // reserved

        if (wLongsPerEntry == 0)
            wLongsPerEntry = (bIndexType == AVI_INDEX_OF_CHUNKS) ? 2 : 3;
    }
    else if (bIndexType == AVI_INDEX_OF_INDEXES)
    {
        buf += 12; // reserved (3 Ipp32u)
        if (wLongsPerEntry == 0)
            wLongsPerEntry = 4;
    }

    if (wLongsPerEntry == 0)
        return UMC_ERR_FAILED;

    nIndexSize -= (buf - pIndexBuffer);
    nEntriesInUse = IPP_MIN(nEntriesInUse, Ipp32u(nIndexSize / (wLongsPerEntry * 4)));

    // super index
    if (bIndexType == AVI_INDEX_OF_INDEXES)
    {
        Ipp32u i;
        for (i = 0; i < nEntriesInUse; i++)
        {
            Ipp64u qwOffset = *(Ipp64u *)buf;
            qwOffset = BIG_ENDIAN_SWAP64(qwOffset);
            buf += 8;

            // size of index chunk at this offset
            Ipp32u dwSize = *(Ipp32u *)buf;
            dwSize = BIG_ENDIAN_SWAP32(dwSize);
            buf += 4;
            buf += 4; // ignore dwDuration

            Ipp8u *pIndexBuffer = ippsMalloc_8u(dwSize);
            if (pIndexBuffer == NULL)
                return UMC_ERR_ALLOC;

            Status umcRes = m_AviChunkReader.GetData(qwOffset, pIndexBuffer, dwSize);
            if (umcRes == UMC_OK)
            {
                // skip standard chunk header - 8 bytes
                umcRes = InitIndexUsingNewAVIIndex(nTrackNum, pIndexBuffer + 8, dwSize - 8);
            }

            ippsFree(pIndexBuffer);
        }
    }
    else
    {
        // standard index
        umcRes = InitIndexUsingStandardIndex(nTrackNum, buf, nEntriesInUse, qwBaseOffset, wLongsPerEntry);
    }

    return umcRes;
}

Status AVISplitter::InitIndexUsingStandardIndex(
    Ipp32u nTrackNum,
    Ipp8u *pIndexBuffer,
    Ipp32u nEntriesInUse,
    Ipp64u qwBaseOffset,
    Ipp16u wLongsPerEntry)
{
    // AVI standard index chunk or AVI field index chunk
    TrackIndex *pIndex = &m_pTrackIndex[nTrackNum];
    IndexFragment frag;
    IndexEntry entry;
    Ipp32u i;

    frag.iNOfEntries = nEntriesInUse;
    frag.pEntryArray = new IndexEntry[nEntriesInUse];
    if (NULL == frag.pEntryArray)
        return UMC_ERR_ALLOC;

    memset(frag.pEntryArray, 0, nEntriesInUse * sizeof(IndexEntry));

    bool bIsAudioTrack = (AVI_FOURCC_auds == m_pTrack[nTrackNum].m_StreamHeader.fccType);
    Ipp32s nBlockAlign = !bIsAudioTrack ? 0 : ((WaveFormatEx *)m_pTrack[nTrackNum].m_pStreamFormat)->nBlockAlign;
    Ipp64f dFrameDuration = (Ipp64f)(m_pTrack[nTrackNum].m_StreamHeader.uiScale) / m_pTrack[nTrackNum].m_StreamHeader.uiRate;

    // if we have already checked VBR or CBR audio in the first standard index,
    // don't bother to do another check.
    if (bIsAudioTrack && !m_bCheckVBRAudio)
    {
        m_bCheckVBRAudio = true;
        Ipp8u *pTemp = pIndexBuffer;
        Ipp32u dwSize = 0;
        for (i = 0; i < nEntriesInUse; i++)
        {
            dwSize = (*(Ipp32u*)(pTemp + 4));
            dwSize = BIG_ENDIAN_SWAP32(dwSize);
            dwSize &= 0x7FFFFFFF;

            // move buffer to next entry
            pTemp += wLongsPerEntry * 4;
            if ((Ipp32s)dwSize < nBlockAlign)
            {
                // VBR if sample size is less than block aglin.
                // same other applications check if nBlockAlign is 1152 or 576.
                m_bIsVBRAudio = true;
                break;
            }
        }
    }

    Ipp32u dwOffset = 0;
    Ipp32u dwSize = 0;
    Ipp64f dTimeStamp = 0;
    if (UMC_OK == pIndex->Last(entry))
    {
        dTimeStamp = entry.GetTimeStamp();
        dTimeStamp += GetSampleDuration(!bIsAudioTrack, m_bIsVBRAudio, dFrameDuration, nBlockAlign, entry.uiSize);
    }

    for (i = 0; i < nEntriesInUse; i++)
    {
        dwOffset = *(Ipp32u *)pIndexBuffer;
        dwOffset = BIG_ENDIAN_SWAP32(dwOffset);
        dwSize = *(Ipp32u *)(pIndexBuffer + 4);
        dwSize = BIG_ENDIAN_SWAP32(dwSize);

        // move to next index entry
        pIndexBuffer += wLongsPerEntry * 4;

        frag.pEntryArray[i].stPosition = (size_t)(qwBaseOffset + dwOffset);
        // bit 31 is Key frame flag
        frag.pEntryArray[i].uiSize = dwSize & 0x7FFFFFFF;
        if (frag.pEntryArray[i].uiSize > m_pTrack[nTrackNum].m_uiMaxSampleSize)
            m_pTrack[nTrackNum].m_uiMaxSampleSize = frag.pEntryArray[i].uiSize;

        // bit 31 is set if this is NOT a key frame
        if (((dwSize & 0x8FFFFFFF) >> 31) == 0)
            frag.pEntryArray[i].uiFlags = I_PICTURE;

        // first sample overall
        frag.pEntryArray[i].dDts = -1.0;
        if (i == 0 && UMC_OK != pIndex->First(entry))
        {
            // Start time, usually it is zero, but it can specify a delay time for
            // a stream that does not start concurrently with the file.
            frag.pEntryArray[i].dPts = m_pTrack[nTrackNum].m_StreamHeader.uiStart * dFrameDuration;
        }
        else
        {
            frag.pEntryArray[i].dPts = dTimeStamp;
        }

        dTimeStamp += GetSampleDuration(!bIsAudioTrack, m_bIsVBRAudio, dFrameDuration, nBlockAlign, frag.pEntryArray[i].uiSize);
    }

    return pIndex->Add(frag);
}

⌨️ 快捷键说明

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