mp4gpyld.cpp

来自「symbian 下的helix player源代码」· C++ 代码 · 共 1,691 行 · 第 1/3 页

CPP
1,691
字号
	    {
		pAUFragments[ulIdx]->m_pData += ulAUStart;
	    }
	}
	else
	{
	    // AU Headers are not present - rely on
	    // constant size configuration te determine the
	    // AU offsets
	    ulAUSizeSum = pBuffer->GetSize() - ulAUStart;
	    ulAUSize = m_Config.m_ulConstantSize;

	    if (ulAUSize == 0)
	    {
		ulAUSize = ulAUSizeSum;
	    }

	    if (ulAUSize > 0)
	    {
		if (ulAUSize <= ulAUSizeSum)
		{
		    ulFixedSizeAUCount = ulAUSizeSum / ulAUSize;
		}
		else
		{
		    // this can only happen if we have pre-configured AU sizes,
		    // no AU headers, and this AU has been fragmented.
		    if (ulAUSizeSum != 0)
		    {
			ulFixedSizeAUCount = 1;
		    }
		}

		if (ulFixedSizeAUCount > 0)
		{
		    ulIdx = 0;
		    retVal = HXR_OK;

		    do
		    {
			pAUPacket = new CAUPacket;

			if (!pAUPacket)
			{
			    retVal = HXR_OUTOFMEMORY;
			    break;
			}

			// Buffer
			pAUPacket->m_pBuffer = pBuffer;
			pBuffer->AddRef();

			// Data
			pAUPacket->m_pData = pData + ulAUStart + ulIdx * ulAUSize;

			// AU - size
			pAUPacket->m_ulSize = ulAUSize;

			// AU - index
			pAUPacket->m_ulIdx = ulIdx;

			// CTS
			ulVal = ulIdx * m_TSConverter.ConvertVector(m_ulAUDuration);
			pAUPacket->m_ulCTS = ulStartCTS + ulVal;
			if ((ulVal == 0) && (ulIdx != 0))
			{
			    pAUPacket->m_bMinTime = TRUE;
			}

			// DTS
			pAUPacket->m_ulDTS = pAUPacket->m_ulCTS;

			ulIdx++;
			pAUFragments[ulNumAUFragments++] = pAUPacket;
		    } while (ulIdx < ulFixedSizeAUCount && ulNumAUFragments < ulMaxAUFragments);
		}
	    }
	}
    }

    return retVal;
}


HX_RESULT MP4GPayloadFormat::AggregateAUFragments(CAUPacket** &pAUPackets,
						  ULONG32 &ulNumAUPackets,
						  ULONG32 &ulMaxAUPackets,
						  CAUPacket** pAUFragments,
						  ULONG32 &ulNumAUFragments)
{
    HX_RESULT retVal = HXR_OK;

    FlushAUArray(pAUPackets, ulNumAUPackets);

    if (IsFragmentCollection(pAUFragments, ulNumAUFragments))
    {
	// Compute actual fragment collection size
	ULONG32 ulFragmentyIdx;
	UINT32 ulHeaderSize;
	ULONG32 ulActualCollectionSize = 0;

	for (ulFragmentyIdx = 0;
	     ulFragmentyIdx < ulNumAUFragments;
	     ulFragmentyIdx++)
	{
	    ulHeaderSize = (UINT32) (pAUFragments[ulFragmentyIdx]->m_pData -
				     pAUFragments[ulFragmentyIdx]->m_pBuffer->GetBuffer());
	    ulActualCollectionSize += (pAUFragments[ulFragmentyIdx]->m_pBuffer->GetSize() -
				       ulHeaderSize);
	}

	if (ulActualCollectionSize == pAUFragments[0]->m_ulSize)
	{
	    // All fragments are accounted for - aggregate all
	    IHXBuffer* pBuffer = NULL;
	    CAUPacket* pAUPacket = new CAUPacket;

	    retVal = HXR_OUTOFMEMORY;

	    if (pAUPacket)
	    {
		retVal = HXR_OK;
	    }

	    // Create Buffer
	    if (SUCCEEDED(retVal))
	    {
		retVal = m_pClassFactory->CreateInstance(IID_IHXBuffer,
							 (void**) &pBuffer);
	    }

	    if (SUCCEEDED(retVal))
	    {
		retVal = pBuffer->SetSize(ulActualCollectionSize);
	    }

	    // Aggregate into the Buffer
	    if (SUCCEEDED(retVal))
	    {
		UINT8* pDataWriter = pBuffer->GetBuffer();
		UINT32 ulFragmentSize;

		for (ulFragmentyIdx = 0;
		     ulFragmentyIdx < ulNumAUFragments;
		     ulFragmentyIdx++)
		{
		    ulHeaderSize = (UINT32) (pAUFragments[ulFragmentyIdx]->m_pData -
					     pAUFragments[ulFragmentyIdx]->m_pBuffer->GetBuffer());
		    ulFragmentSize = pAUFragments[ulFragmentyIdx]->m_pBuffer->GetSize() -
				     ulHeaderSize;
		    memcpy(pDataWriter,	    /* Flawfinder: ignore */
			   pAUFragments[ulFragmentyIdx]->m_pData,
			   ulFragmentSize);

		    pDataWriter += ulFragmentSize;
		}
	    }

	    // Populate the aggregated AUPacket
	    if (SUCCEEDED(retVal))
	    {
		// Buffer
		pAUPacket->m_pBuffer = pBuffer;
		pBuffer = NULL;

		// Data
		pAUPacket->m_pData = pAUPacket->m_pBuffer->GetBuffer();

		// AU - size
		pAUPacket->m_ulSize = ulActualCollectionSize;

		// AU - index
		pAUPacket->m_ulIdx = pAUFragments[0]->m_ulIdx;

		// CTS
		pAUPacket->m_ulCTS = pAUFragments[0]->m_ulCTS;
		pAUPacket->m_bMinTime = pAUFragments[0]->m_bMinTime;

		// DTS
		pAUPacket->m_ulDTS = pAUFragments[0]->m_ulDTS;

		// Set to output
		pAUPackets[0] = pAUPacket;
		ulNumAUPackets = 1;
		pAUPacket = NULL;
	    }

	    HX_RELEASE(pBuffer);
	    HX_DELETE(pAUPacket);
	}
	else
	{
	    // Something is missing or is corrupted - discard data
	    retVal = HXR_FAIL;
	}

	// Flush the input fragmants
	FlushAUArray(pAUFragments, ulNumAUFragments);
    }
    else
    {
	// No aggregation necessary
	ulNumAUPackets = ulNumAUFragments;
	memcpy(pAUPackets, pAUFragments, sizeof(CAUPacket*) * ulNumAUFragments); /* Flawfinder: ignore */
	memset(pAUFragments, 0, sizeof(CAUPacket*) * ulNumAUFragments);
	ulNumAUFragments = 0;
    }
    
    return retVal;
}

BOOL MP4GPayloadFormat::IsFragmentCollection(CAUPacket** pAUFragments,
					     ULONG32 ulNumAUFragments)
{
    BOOL bRetVal = FALSE;

    if (ulNumAUFragments > 0)
    {
	// Even if we have only one fragment, this could still be a fragment
	// collection in which all but one fragment were lost
	UINT32 ulHeaderSize = (UINT32) (pAUFragments[0]->m_pData -
				        pAUFragments[0]->m_pBuffer->GetBuffer());

	bRetVal = ((ulHeaderSize + pAUFragments[0]->m_ulSize)
		   > pAUFragments[0]->m_pBuffer->GetSize());
    }

    return bRetVal;
}


HX_RESULT MP4GPayloadFormat::DeinterleaveAUPackets(CAUPacket** pAUPackets,
						   ULONG32 &ulNumAUPackets)
{
    ULONG32 ulIdx;
    HX_RESULT retVal = HXR_OK;

    for (ulIdx = 0; ulIdx < ulNumAUPackets; ulIdx++)
    {
	if (SUCCEEDED(DeinterleaveAUPacket(pAUPackets[ulIdx])))
	{
	    pAUPackets[ulIdx] = NULL;
	}
	else
	{
	    HX_DELETE(pAUPackets[ulIdx]);
	}
    }

    ulNumAUPackets = 0;

    return retVal;
}


HX_RESULT MP4GPayloadFormat::DeinterleaveAUPacket(CAUPacket* pAUPacket)
{
    ULONG32 ulCount = m_DeinterleaveQueue.GetCount();

    if (ulCount == 0)
    {
	m_DeinterleaveQueue.AddTail(pAUPacket);
    }
    else
    {
	CAUPacket* pListAUPacket;
	LISTPOSITION lPos = m_DeinterleaveQueue.GetTailPosition();
	LISTPOSITION lInsertPos = lPos;
	ULONG32 ulPrevIdx = 0xFFFFFFFF;
	pListAUPacket = (CAUPacket*) m_DeinterleaveQueue.GetAt(lPos);

	do
	{
	    if (!MayAUPacketPrecede(pAUPacket, pListAUPacket))
	    {
		m_DeinterleaveQueue.InsertAfter(lInsertPos, pAUPacket);
		break;
	    }

	    ulCount--;
	    if (ulCount == 0)
	    {
		CAUPacket lastReapedAUPacket;

		lastReapedAUPacket.m_ulDTS = m_ulLastReapedDTS;
		lastReapedAUPacket.m_ulIdx = m_ulLastReapedIdx;
		lastReapedAUPacket.m_bMinTime = m_bLastReapedMinTime;

		if (m_bLastReapedSet &&
		    MayAUPacketPrecede(&lastReapedAUPacket, pAUPacket))
		{
		    m_DeinterleaveQueue.InsertBefore(lPos, pAUPacket);
		}
		else
		{
		    m_DeinterleaveQueue.InsertAfter(lInsertPos, pAUPacket);
		}
		break;
	    }

	    pListAUPacket = (CAUPacket*) m_DeinterleaveQueue.GetAtPrev(lPos);

	    if (MayAUPacketPrecede(pListAUPacket, pAUPacket))
	    {
		lInsertPos = lPos;
	    }
	} while (TRUE);
    }

    return HXR_OK;
}


HX_RESULT MP4GPayloadFormat::ReapMediaPacket(ULONG32 ulLastPacketTime)
{
    CAUPacket* pAUPacket;
    CMediaPacket* pMediaPacket;
    HX_RESULT retVal = HXR_NO_DATA;

    if (!m_DeinterleaveQueue.IsEmpty())
    {
	BOOL bTryAgain;
	BOOL bUnknownTime;

	if ((!m_bEarliestDeintTimeKnown) && (!m_bFlushed))
	{
	    m_bEarliestDeintTimeKnown = FindEarliestKnownDeintTime(m_ulEarliestDeintTimeKnown);
	}

	do
	{
	    bTryAgain = FALSE;

	    pAUPacket = (CAUPacket*) m_DeinterleaveQueue.GetHead();

	    if ((m_bEarliestDeintTimeKnown &&
		 (!TestTimeGreater(m_ulEarliestDeintTimeKnown, m_ulLastPacketTime)))
		||
		(m_bLastReapedSet &&
		 (IndexDiff(pAUPacket->m_ulIdx, m_ulLastReapedIdx) == 1))
		||
		m_bFlushed)
	    {
		ULONG32 ulFlags = MDPCKT_USES_IHXBUFFER_FLAG;

		pAUPacket = (CAUPacket*) m_DeinterleaveQueue.GetHead();

		bUnknownTime = pAUPacket->m_bMinTime;

		if (bUnknownTime)
		{
		    ulFlags |= MDPCKT_HAS_UKNOWN_TIME_FLAG;
		}
		else
		{
		    m_bEarliestDeintTimeKnown = FALSE;
		}

		if (m_bLastReapedSet)
		{
		    if (IndexDiff(pAUPacket->m_ulIdx, m_ulLastReapedIdx) != 1)
		    {
			ulFlags |= MDPCKT_FOLLOWS_LOSS_FLAG;
		    }
		}

		m_bLastReapedMinTime = pAUPacket->m_bMinTime;
		m_ulLastReapedDTS = pAUPacket->m_ulCTS;
		m_ulLastReapedIdx = pAUPacket->m_ulIdx;
		m_bLastReapedSet = TRUE;

		pMediaPacket = new CMediaPacket(pAUPacket->m_pBuffer,
						pAUPacket->m_pData,
						pAUPacket->m_ulSize,
						pAUPacket->m_ulSize,
						pAUPacket->m_ulCTS,
						ulFlags,
						NULL);

		retVal = HXR_OUTOFMEMORY;
		if (pMediaPacket)
		{
		    m_DeinterleaveQueue.RemoveHead();
		    delete pAUPacket;
		    m_OutputQueue.AddTail(pMediaPacket);
		    bTryAgain = TRUE;
		    retVal = HXR_OK;
		}
	    }
	    else if ((!m_bEarliestDeintTimeKnown) && (!m_bFlushed))
	    {
		m_bEarliestDeintTimeKnown = FindEarliestKnownDeintTime(m_ulEarliestDeintTimeKnown);
		bTryAgain = m_bEarliestDeintTimeKnown;
	    }
	} while (bTryAgain &&
		 (!m_DeinterleaveQueue.IsEmpty()));
    }

    return retVal;
}


STDMETHODIMP
MP4GPayloadFormat::Flush()
{
    m_bFlushed = TRUE;

    return HXR_OK;
}

void MP4GPayloadFormat::FlushQueues(void)
{
    FlushInputQueue(FLUSH_ALL_PACKETS);
    FlushDeinterleaveQueue(FLUSH_ALL_PACKETS);
    FlushOutputQueue(FLUSH_ALL_PACKETS);
}

void MP4GPayloadFormat::FlushInputQueue(ULONG32 ulCount)
{
    IHXPacket* pDeadPacket;

    while ((ulCount > 0) && (!m_InputQueue.IsEmpty()))
    {
	pDeadPacket = (IHXPacket*) m_InputQueue.RemoveHead();
	HX_RELEASE(pDeadPacket);
	if (ulCount != FLUSH_ALL_PACKETS)
	{
	    ulCount--;
	}
    }
}

void MP4GPayloadFormat::FlushDeinterleaveQueue(ULONG32 ulCount)
{
    CAUPacket* pDeadPacket;

    while ((ulCount > 0) && (!m_DeinterleaveQueue.IsEmpty()))
    {
	pDeadPacket = (CAUPacket*) m_DeinterleaveQueue.RemoveHead();
	HX_DELETE(pDeadPacket);
	if (ulCount != FLUSH_ALL_PACKETS)
	{
	    ulCount--;
	}
    }

    m_bEarliestDeintTimeKnown = FALSE;
    m_bLastReapedSet = FALSE;
}

void MP4GPayloadFormat::FlushOutputQueue(ULONG32 ulCount)
{
    CMediaPacket* pDeadPacket;

    while ((ulCount > 0) && (!m_OutputQueue.IsEmpty()))
    {
	pDeadPacket = (CMediaPacket*) m_OutputQueue.RemoveHead();
	HX_DELETE(pDeadPacket);
	if (ulCount != FLUSH_ALL_PACKETS)
	{
	    ulCount--;
	}
    }
}

BOOL MP4GPayloadFormat::FindEarliestKnownDeintTime(ULONG32 &ulEarliestKnownDeintTime)
{
    ULONG32 ulCount;
    LISTPOSITION lPos;
    CAUPacket* pPacket;

    ulCount = m_DeinterleaveQueue.GetCount();

    if (ulCount > 0)
    {
	lPos = m_DeinterleaveQueue.GetHeadPosition();
	pPacket = (CAUPacket*) m_DeinterleaveQueue.GetHead();

	do
	{
	    if (!pPacket->m_bMinTime)
	    {
		ulEarliestKnownDeintTime = pPacket->m_ulCTS;
		return TRUE;
	    }

	    ulCount--;

	    if (ulCount == 0)
	    {
		break;
	    }

	    pPacket = (CAUPacket*) m_DeinterleaveQueue.GetAtNext(lPos);
	} while (TRUE);
    }

    return FALSE;
}

void MP4GPayloadFormat::FlushArrays(void)
{
    FlushPacketArray(m_pPacketFragments, m_ulNumPacketFragments);
    FlushAUArray(m_pAUFragments, m_ulNumAUFragments);
    FlushAUArray(m_pAUPackets, m_ulNumAUPackets);
}


ULONG32 MP4GPayloadFormat::GetPacketTime(IHXPacket* pPacket)
{
    ULONG32 ulTime;

    HX_ASSERT(pPacket);

    if (m_bUsesRTPPackets)
    {
	ulTime = ((IHXRTPPacket*) pPacket)->GetRTPTime();
    }
    else
    {
	ulTime = pPacket->GetTime();
    }

    ulTime = m_TSConverter.Convert(ulTime);

    return ulTime;
}


ULONG32 MP4GPayloadFormat::SignBitField(ULONG32 ulVal, ULONG32 ulNumBits)
{
    if (ulNumBits > 0)
    {
	if (ulVal >> (ulNumBits - 1))
	{
	    ulVal = (0xFFFFFFFF & ulVal);
	}
    }
    else
    {
	ulVal = 0;
    }

    return ulVal;
}


BOOL MP4GPayloadFormat::TestIndexGreater(ULONG32 ulIdx1, ULONG32 ulIdx2)
{
    return (ulIdx1 > ulIdx2);
}


BOOL MP4GPayloadFormat::TestTimeGreater(ULONG32 ulTime1, ULONG32 ulTime2)
{
    return (((LONG32) (ulTime1 - ulTime2)) > 0);
}

LONG32 MP4GPayloadFormat::IndexDiff(ULONG32 ulIdx1, ULONG32 ulIdx2)
{
    return SignBitField(ulIdx1 - ulIdx2, m_Config.m_ulIndexLength);
}

⌨️ 快捷键说明

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