mp4vpyld.cpp

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

CPP
1,393
字号
		retVal = m_pClassFactory->CreateInstance(CLSID_IHXBuffer,
							 (void**) &pNewBuffer);
	    }

	    // Set Buffer
	    if (SUCCEEDED(retVal))
	    {
		retVal = pNewBuffer->Set(pRemainingData, ulFragmentSize);
	    }

	    // Set the new packet
	    if (SUCCEEDED(retVal))
	    {
		if (SUCCEEDED(retVal))
		{
		    if (m_bUsesRTPPackets)
		    {
			retVal = ((IHXRTPPacket*) pNewPacket)->SetRTP(
			    pNewBuffer,
			    pRTPPacket->GetTime(),
			    pRTPPacket->GetRTPTime(),
			    pRTPPacket->GetStreamNumber(),
			    pRTPPacket->GetASMFlags(),
			    (ulRemainingSize > m_ulMaxPacketDataSize) ?
				0 : pRTPPacket->GetASMRuleNumber());
		    }
		    else
		    {
			retVal = ((IHXRTPPacket*) pNewPacket)->Set(
			    pNewBuffer,
			    pPacket->GetTime(),
			    pPacket->GetStreamNumber(),
			    pPacket->GetASMFlags(),
			    (ulRemainingSize > m_ulMaxPacketDataSize) ?
				0 : pPacket->GetASMRuleNumber());
		    }
		}
	    }

	    pRemainingData += ulFragmentSize;
	    ulRemainingSize -= ulFragmentSize;
	    if (ulRemainingSize < ulFragmentSize)
	    {
		ulFragmentSize = ulRemainingSize;
	    }

	    if (SUCCEEDED(retVal))
	    {
		pNewPacket->AddRef();
		m_OutputPackets.AddTail(pNewPacket);
	    }

	    HX_RELEASE(pNewBuffer);
	    HX_RELEASE(pNewPacket);
	} while (SUCCEEDED(retVal) && (ulRemainingSize > 0));

	HX_RELEASE(pRTPPacket);
    }
    else
    {
	pPacket->AddRef();
	m_OutputPackets.AddTail(pPacket);
    }

    HX_RELEASE(pPacketBuffer);

    return retVal;
}


HX_RESULT MP4VPayloadFormat::GetRawPacketizerPacket(IHXPacket* &pOutPacket)
{
    IHXPacket* pPacket;
    IHXPacket* pAfterPacket = NULL;
    IHXRTPPacket* pRTPPacket = NULL;
    UINT16 uASMRuleNumber;
    BOOL bMarker = TRUE;
    BOOL bNewPictureStart = TRUE;
    HX_RESULT retVal = HXR_INCOMPLETE;

    if ((m_InputPackets.GetCount() > 1) ||
	m_bFlushed)
    {
	retVal = HXR_OK;
	pPacket = (IHXPacket*) m_InputPackets.RemoveHead();

	if (!m_bPictureStarted)
	{
	    m_bPictureStarted = IsPictureStart(pPacket);
	}

	if (m_bFirstPacket)
	{
	    m_bFirstPacket = FALSE;
	}

	// Determine marker usage
	if (m_InputPackets.GetCount() > 0)
	{
	    pAfterPacket = (IHXPacket*) m_InputPackets.GetHead();
	}

	if (pAfterPacket)
	{
	    bNewPictureStart = IsPictureStart(pAfterPacket);

	    bMarker = ((GetPacketTime(pPacket) != GetPacketTime(pAfterPacket)) ||
		       (bNewPictureStart && m_bPictureStarted));

	    if (bMarker)
	    {
		m_bPictureStarted = bNewPictureStart;
	    }
	}
	else
	{
	    bMarker = m_bFlushed;
	}


	uASMRuleNumber = bMarker ? 1 : 0;

	// If rule number must change, create new packet
	if (uASMRuleNumber != pPacket->GetASMRuleNumber())
	{
	    IHXPacket* pNewPacket = NULL;

	    if (m_bUsesRTPPackets)
	    {
		retVal = m_pClassFactory->CreateInstance(CLSID_IHXRTPPacket,
							 (void**) &pNewPacket);

		if (SUCCEEDED(retVal))
		{
		    retVal = pPacket->QueryInterface(IID_IHXRTPPacket,
						     (void**) &pRTPPacket);
		}
	    }
	    else
	    {
		retVal = m_pClassFactory->CreateInstance(CLSID_IHXPacket,
							 (void**) &pNewPacket);
	    }

	    if (SUCCEEDED(retVal))
	    {
		IHXBuffer* pBuffer = pPacket->GetBuffer();

		if (m_bUsesRTPPackets)
		{
		    retVal = ((IHXRTPPacket*) pNewPacket)->SetRTP(
			pBuffer,
			pRTPPacket->GetTime(),
			pRTPPacket->GetRTPTime(),
			pRTPPacket->GetStreamNumber(),
			pRTPPacket->GetASMFlags(),
			uASMRuleNumber);
		}
		else
		{
		    retVal = ((IHXRTPPacket*) pNewPacket)->Set(
			pBuffer,
			pPacket->GetTime(),
			pPacket->GetStreamNumber(),
			pPacket->GetASMFlags(),
			uASMRuleNumber);
		}

		HX_RELEASE(pBuffer);
	    }

	    pPacket->Release();
	    pPacket = NULL;

	    if (SUCCEEDED(retVal))
	    {
		pPacket = pNewPacket;
		pNewPacket = NULL;
	    }

	    HX_RELEASE(pNewPacket);
	    HX_RELEASE(pRTPPacket);
	}

	if (SUCCEEDED(retVal))
	{
	    pOutPacket = pPacket;
	}
    }

    return retVal;
}

HX_RESULT MP4VPayloadFormat::GetAssemblerPacket(IHXPacket* &pOutPacket)
{
    HX_RESULT retVal = HXR_NOTIMPL;

    return retVal;
}

void MP4VPayloadFormat::FlushPackets(ULONG32 ulCount)
{
    IHXPacket* pDeadPacket;

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

ULONG32 MP4VPayloadFormat::CountValidPackets(ULONG32 ulCount)
{
    IHXPacket* pPacket;
    LISTPOSITION listPos;
    ULONG32 ulValidCount = 0;

    listPos = m_InputPackets.GetHeadPosition();

    while ((ulCount > 0) && (listPos != NULL))
    {
	pPacket = (IHXPacket*) m_InputPackets.GetNext(listPos);
	HX_ASSERT(pPacket);
	if (!pPacket->IsLost())
	{
	    ulValidCount++;
	}

	ulCount--;
    }

    return ulValidCount;
}

ULONG32 MP4VPayloadFormat::SumPacketSizes(ULONG32 ulCount)
{
    IHXPacket* pPacket;
    IHXBuffer* pBuffer;
    LISTPOSITION listPos;
    ULONG32 ulSize = 0;

    listPos = m_InputPackets.GetHeadPosition();

    while ((ulCount > 0) && (listPos != NULL))
    {
	pPacket = (IHXPacket*) m_InputPackets.GetNext(listPos);
	HX_ASSERT(pPacket);
	if (!pPacket->IsLost())
	{
	    pBuffer = pPacket->GetBuffer();

	    if (pBuffer)
	    {
		ulSize += pBuffer->GetSize();
		pBuffer->Release();
	    }
	}

	ulCount--;
    }

    return ulSize;
}

HX_RESULT MP4VPayloadFormat::CreateHXCodecPacket(UINT32* &pHXCodecDataOut)
{
    HX_RESULT retVal = HXR_INCOMPLETE;

    if (m_ulFrameCount > 0)
    {
	// Compute frame size and count segments
	ULONG32 ulFrameSize = 0;
	ULONG32 ulSegmentCount = 0;
	ULONG32 ulSegmentSize;
	ULONG32 ulFrameTime = 0;
	ULONG32 ulValidSegmentCount = 0;
	IHXPacket* pPacket;
	IHXBuffer* pBuffer = NULL;
	LISTPOSITION listPos;
	ULONG32 ulIdx;
	BOOL bIsLost;
	BOOL bPictureStarted = FALSE;
	BOOL bNewPictureStart;
	HXCODEC_DATA* pHXCodecData = NULL;
	HXCODEC_SEGMENTINFO* pHXCodecSegmentInfo;
	ULONG32* pData = NULL;

	retVal = HXR_OK;

	// Gather Frame Information - until valid frame detected
	do
	{
	    listPos = m_InputPackets.GetHeadPosition();
            if( listPos == NULL )
            {
                return HXR_OUTOFMEMORY;
            }

	    do
	    {
		if (ulSegmentCount >= MAX_FRAME_SEGMENTS)
		{
		    HX_ASSERT(pPacket);

		    FlushPackets(ulSegmentCount - NUM_OVERLAP_SEGMENTS);

		    ulSegmentCount = NUM_OVERLAP_SEGMENTS;
		    ulFrameSize = SumPacketSizes(NUM_OVERLAP_SEGMENTS);
		    ulValidSegmentCount = CountValidPackets(NUM_OVERLAP_SEGMENTS);
		}

		pPacket = (IHXPacket*) m_InputPackets.GetNext(listPos);

		if (!pPacket->IsLost())
		{
		    bNewPictureStart = IsPictureStart(pPacket);

		    if (ulValidSegmentCount > 0)
		    {
			if ((GetPacketTime(pPacket) != ulFrameTime) ||
			    (bPictureStarted && bNewPictureStart))
			{
			    break;
			}
		    }
		    else
		    {
			ulFrameTime = GetPacketTime(pPacket);
		    }

		    if (!bPictureStarted)
		    {
			bPictureStarted = bNewPictureStart;
		    }

		    ulValidSegmentCount++;

		    pBuffer = pPacket->GetBuffer();
		}

		if (pBuffer)
		{
		    ulFrameSize += pBuffer->GetSize();
		    pBuffer->Release();
		    pBuffer = NULL;
		}

		ulSegmentCount++;
	    } while (pPacket->GetASMRuleNumber() != 1);

	    m_ulFrameCount--;
	} while ((ulValidSegmentCount == 0) &&
		 (m_ulFrameCount > 0));

	if (ulValidSegmentCount == 0)
	{
	    retVal = HXR_INCOMPLETE;
	}

	// Allocate codec data header
	if (retVal == HXR_OK)
	{
	    HX_ASSERT(ulSegmentCount != 0);
	    HX_ASSERT(ulValidSegmentCount != 0);

#ifdef _APPEND_VOL_HEADER
	    if (m_bFirstFrame)
	    {
		ulFrameSize += m_ulVOLHeaderSize;
	    }
#endif	// _APPEND_VOL_HEADER

	    pData = new ULONG32[(sizeof(HXCODEC_DATA) +
			         sizeof(HXCODEC_SEGMENTINFO) *
			         (ulSegmentCount - 1)) / 4 + 1];

	    retVal = HXR_OUTOFMEMORY;
	    if (pData)
	    {
		retVal = HXR_OK;
	    }
	}

	// Init. codec data header
	if (retVal == HXR_OK)
	{
	    pHXCodecData = (HXCODEC_DATA*) pData;

	    pHXCodecData->dataLength = ulFrameSize;
	    pHXCodecData->timestamp = ulFrameTime;
	    pHXCodecData->sequenceNum = m_uSeqNumber;
	    pHXCodecData->flags = 0;
	    pHXCodecData->lastPacket = FALSE;
	    pHXCodecData->numSegments = ulSegmentCount;
	    pHXCodecData->data = NULL;

	    if ((ulFrameSize > 0)
#ifndef _OVERALLOC_CODEC_DATA
		&&
		(
		 (ulValidSegmentCount > 1) ||
		 (m_pAllocator == NULL)
#ifdef _APPEND_VOL_HEADER
		 || m_bFirstFrame
#endif	// _APPEND_VOL_HEADER
	        )
#endif	// _OVERALLOC_CODEC_DATA
	       )
	    {
#ifdef _OVERALLOC_CODEC_DATA
		ulFrameSize += _OVERALLOC_CODEC_DATA;   // over allocate since codec reads 24bits at a time
#endif	// _OVERALLOC_CODEC_DATA

		if (m_pAllocator)
		{
		    IHXUnknown* pIUnkn = NULL;
		    HX20ALLOCPROPS allocRequest;
		    HX20ALLOCPROPS allocActual;

		    allocRequest.uBufferSize = ulFrameSize;
		    allocRequest.nNumBuffers = 0;
		    m_pAllocator->SetProperties(&allocRequest, &allocActual);
		    pHXCodecData->data = m_pAllocator->GetPacketBuffer(&pIUnkn);
		}
		else
		{
		    pHXCodecData->data = (UINT8*) new ULONG32 [ulFrameSize / 4 + 1];
		}

		if (pHXCodecData->data == NULL)
		{
		    retVal = HXR_OUTOFMEMORY;
		}
	    }
	}

	// Build Codec Data
	if (retVal == HXR_OK)
	{
	    BOOL bNoneLost = TRUE;
	    pHXCodecSegmentInfo = (HXCODEC_SEGMENTINFO*) &(pHXCodecData->Segments[0]);

	    ulFrameSize = 0;

	    for (ulIdx = 0; ulIdx < ulSegmentCount; ulIdx++)
	    {
		HX_ASSERT(!m_InputPackets.IsEmpty());

		pPacket = (IHXPacket*) m_InputPackets.RemoveHead();

		HX_ASSERT(pPacket);

		ulSegmentSize = 0;

		pHXCodecSegmentInfo[ulIdx].ulSegmentOffset = ulFrameSize;

		bIsLost = pPacket->IsLost();
		if (!bIsLost)
		{
		    pBuffer = pPacket->GetBuffer();

		    if (pHXCodecData->data)
		    {
			if (m_bFirstFrame)
			{
#ifdef _APPEND_VOL_HEADER
			    memcpy(pHXCodecData->data, m_pVOLHeader, m_ulVOLHeaderSize); /* Flawfinder: ignore */
			    ulFrameSize += m_ulVOLHeaderSize;
#endif	// _APPEND_VOL_HEADER
			    m_bFirstFrame = FALSE;
			}

			if (pBuffer)
			{
			    ulSegmentSize = pBuffer->GetSize();

			    HX_ASSERT(pHXCodecData->dataLength >= (ulFrameSize + ulSegmentSize));

			    memcpy(pHXCodecData->data + ulFrameSize, /* Flawfinder: ignore */
				   pBuffer->GetBuffer(),
				   ulSegmentSize);

			    pBuffer->Release();
			}
		    }
		    else
		    {
			HX_ASSERT(m_pAllocator);
			HX_ASSERT(ulValidSegmentCount == 1);
#ifdef _APPEND_VOL_HEADER
			HX_ASSERT(m_bFirstFrame == FALSE);
#endif	// _APPEND_VOL_HEADER

			if (pBuffer)
			{
			    ulSegmentSize = pBuffer->GetSize();
			    pHXCodecData->data = m_pAllocator->AddBuffer(pBuffer);
			    pBuffer->Release();
			}
		    }

		    ulFrameSize += ulSegmentSize;
		}

		pHXCodecSegmentInfo[ulIdx].bIsValid = !bIsLost;
		bNoneLost = (bNoneLost && (!bIsLost));

		pPacket->Release();
	    }

	    if (bNoneLost)
	    {
		pHXCodecData->numSegments = 1;
	    }
#ifdef _ASSERT_ON_LOSS
	    else
	    {
		HX_ASSERT(FALSE);
	    }
#endif	// _ASSERT_ON_LOSS

#ifdef _DONOT_SEGMENT
	    pHXCodecData->numSegments = 1;
	    pHXCodecSegmentInfo[0].bIsValid = bNoneLost;
#endif	// _DONOT_SEGMENT
	}

	// Finalize Results
	if (retVal == HXR_OK)
	{
	    pHXCodecDataOut = pData;
	}
	else
	{
	    if (pHXCodecData && pHXCodecData->data)
	    {
		m_pAllocator->ReleasePacketPtr(pHXCodecData->data);
	    }
	    HX_VECTOR_DELETE(pData);
	}

#ifdef _DUMP_FIRST_NFRAMES
	if (m_uSeqNumber < _DUMP_FIRST_NFRAMES)
	{
	    char pFileName[100]; /* Flawfinder: ignore */

	    SafeSprintf(pFileName, 100, "%s%d", "c:\\fframe.bin", m_uSeqNumber);

	    FILE* pFile = fopen(pFileName, "wb");

	    if (pFile)
	    {
		fprintf(pFile, "T=%ld;B=%ld:", pHXCodecData->timestamp, pHXCodecData->dataLength);
		fwrite(pHXCodecData->data, sizeof(UINT8), pHXCodecData->dataLength, pFile);
		fclose(pFile);
	    }
	}
#endif	// _DUMP_FIRST_NFRAMES

	m_uSeqNumber++;
    }

    return retVal;
}


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

    return HXR_OK;
}


BOOL MP4VPayloadFormat::IsPictureStart(IHXPacket* pPacket)
{
    if (m_PayloadID == PYID_X_HX_MP4)
    {
	ULONG32 ulIdx;
	ULONG32 ulSize = 0;
	UINT8* pData = NULL;
	IHXBuffer* pBuffer;

	pBuffer = pPacket->GetBuffer();

	if (pBuffer)
	{
	    ulSize = pBuffer->GetSize();
	    if (ulSize >= 4)
	    {
		ulSize -= 4;
		pData = pBuffer->GetBuffer();
	    }

	    pBuffer->Release();
	}

	if (pData)
	{
	    ulIdx = 0;

	    do
	    {
		if (pData[ulIdx++] == 0x00)
		{
		    if (pData[ulIdx++] == 0x00)
		    {
			if (pData[ulIdx] == 0x01)
			{
			    ulIdx++;
			    if (pData[ulIdx] == 0xb6)
			    {
				return TRUE;
			    }
			}
			else
			{
			    ulIdx--;
			}
		    }
		}
	    } while (ulIdx < ulSize);
	}
    }

    return FALSE;
}


BOOL MP4VPayloadFormat::IsValidPacket(IHXPacket* pPacket)
{
    if (m_PayloadID == PYID_X_HX_MP4)
    {
	ULONG32 ulSize;
	UINT8* pData = NULL;
	IHXBuffer* pBuffer = pPacket->GetBuffer();

	if (pBuffer)
	{
	    ulSize = pBuffer->GetSize();
	    if (ulSize >= 4)
	    {
		ulSize -= 4;
		pData = pBuffer->GetBuffer();
	    }

	    pBuffer->Release();
	}

	if (pData)
	{
	    // Should be more sophisiticated here and fully parse the
	    // headeres and make sure there is no data of substance
	    // following the headers - for this prototype code it
	    // is good enough
	    if ((pData[0] == 0x00) &&
		(pData[1] == 0x00) &&
		(pData[2] == 0x01) &&
		((pData[3] == 0x00) ||
		(pData[3] == 0x20)))
	    {
		return FALSE;
	    }
	}
    }

    return TRUE;
}


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

    HX_ASSERT(pPacket);

    if (m_bUsesRTPPackets && (m_ulSamplesPerSecond != 0))
    {
	ulTime = ((IHXRTPPacket*) pPacket)->GetRTPTime();

	ulTime = m_TSConverter.Convert(ulTime);
    }
    else
    {
	ulTime = pPacket->GetTime();
    }

    return ulTime;
}

⌨️ 快捷键说明

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