📄 umc_stream_parser.cpp
字号:
/*//////////////////////////////////////////////////////////////////////////////
//
// INTEL CORPORATION PROPRIETARY INFORMATION
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Intel Corporation and may not be copied
// or disclosed except in accordance with the terms of that agreement.
// Copyright(c) 2005-2007 Intel Corporation. All Rights Reserved.
//
*/
#include <ipps.h>
#include "umc_stream_parser.h"
#include "umc_frame_constructor.h"
#define PARSER_CHECK_INIT CHECK_OBJ_INIT(m_pDataReader)
namespace UMC
{
StreamParserParams::StreamParserParams(void)
{
m_SystemType = UNDEF_STREAM;
m_pDataReader = NULL;
}
StreamParserParams::~StreamParserParams()
{
}
StreamParser::StreamParser()
{
m_pDataReader = NULL;
m_pPacket = NULL;
}
StreamParser::~StreamParser()
{
Close();
}
Status StreamParser::Init(StreamParserParams &init)
{
if (m_pDataReader) // already initialized
return UMC_ERR_FAILED;
if (!init.m_pDataReader)
return UMC_ERR_NULL_PTR;
ippsZero_8u((Ipp8u *)m_pInfo, MAX_TRACK * sizeof(void *));
m_ParserState = HEADER;
m_dDuration = -1.0;
m_uiTracks = 0;
m_SystemType = init.m_SystemType;
m_pDataReader = init.m_pDataReader;
m_uiSourceSize = init.m_pDataReader->GetSize();
if (!m_pPacket) m_pPacket = new Packet;
return UMC_OK;
}
Status StreamParser::Close(void)
{
PARSER_CHECK_INIT;
Ipp32s i;
for (i = 0; i < (Ipp32s)m_uiTracks; i++)
{
if (m_pInfo[i])
{
m_pInfo[i]->ReleaseAll();
delete m_pInfo[i];
m_pInfo[i] = NULL;
}
}
if (m_pPacket)
{
delete m_pPacket;
m_pPacket = NULL;
}
m_pDataReader = NULL;
return UMC_OK;
}
Status StreamParser::CheckNextData(MediaData *pData, Ipp32u* pTrack)
{
PARSER_CHECK_INIT;
if (!pData || !pTrack)
return UMC_ERR_NULL_PTR;
if (0 == m_uiTracks)
{
m_uiTracks = 1;
if (!m_pInfo[0])
m_pInfo[0] = new Mpeg2TrackInfo;
switch (m_SystemType)
{
case MPEG1_PURE_VIDEO_STREAM:
m_pInfo[0]->m_Type = TRACK_MPEG1V; break;
case MPEG2_PURE_VIDEO_STREAM:
m_pInfo[0]->m_Type = TRACK_MPEG2V; break;
case MPEG4_PURE_VIDEO_STREAM:
m_pInfo[0]->m_Type = TRACK_MPEG4V; break;
case H261_PURE_VIDEO_STREAM:
m_pInfo[0]->m_Type = TRACK_H261; break;
case H263_PURE_VIDEO_STREAM:
m_pInfo[0]->m_Type = TRACK_H263; break;
case H264_PURE_VIDEO_STREAM:
m_pInfo[0]->m_Type = TRACK_H264; break;
case MPEG1_PURE_AUDIO_STREAM:
case MPEG2_PURE_AUDIO_STREAM:
case MPEGx_PURE_AUDIO_STREAM:
m_pInfo[0]->m_Type = TRACK_MPEGA; break;
default:
m_pInfo[0]->m_Type = TRACK_UNKNOWN; break;
}
Status err = m_pInfo[0]->Alloc();
if (UMC_OK != err)
return err;
if (m_pInfo[0]->m_Type & TRACK_ANY_AUDIO)
{
if (m_dDuration < 0.0 && (m_pInfo[0]->m_Type & TRACK_MPEGA))
EstimateMPEGAudioDuration();
((AudioStreamInfo *)m_pInfo[0]->m_pStreamInfo)->duration = m_dDuration;
}
}
m_ParserState = PAYLOAD;
pTrack[0] = 0;
m_pPacket->uiSize = 16 * 1024;
m_pPacket->uiAbsPos = m_pDataReader->GetPosition();
PacketToMediaData(*m_pPacket, *pData);
return UMC_OK;
}
Status StreamParser::GetNextData(MediaData *pData, Ipp32u *pTrack)
{
PARSER_CHECK_INIT;
if (END_OF_STREAM == m_ParserState)
return UMC_ERR_END_OF_STREAM;
if (!pData || !pData->GetDataPointer() || !pTrack)
return UMC_ERR_NULL_PTR;
Status umcRes = UMC_OK;
if (HEADER == m_ParserState)
{
umcRes = CheckNextData(pData, pTrack);
if (UMC_OK != umcRes)
return umcRes;
}
if (m_pPacket->uiSize > pData->GetBufferSize())
return UMC_ERR_NOT_ENOUGH_BUFFER;
// move to the beginning of payload
umcRes = m_pDataReader->MovePosition((Ipp64u)m_pPacket->iBufOffset);
if (UMC_ERR_END_OF_STREAM == umcRes)
{
m_ParserState = END_OF_STREAM;
return umcRes;
}
umcRes = m_pDataReader->GetData(pData->GetDataPointer(), &m_pPacket->uiSize);
if (UMC_ERR_END_OF_STREAM == umcRes)
{
m_ParserState = END_OF_STREAM;
if (0 == m_pPacket->uiSize)
return umcRes;
umcRes = UMC_OK;
}
*pTrack = GetTrackByPidOrCreateNew(m_pPacket->iPid, NULL);
#ifdef _BIG_ENDIAN_
if (*pTrack >= 0 && TRACK_PCM == m_pInfo[*pTrack]->m_Type)
ippsSwapBytes_16u_I((Ipp16u *)pData->GetDataPointer(), m_pPacket->uiSize / 2);
#else
if (*pTrack >= 0 && TRACK_LPCM == m_pInfo[*pTrack]->m_Type)
ippsSwapBytes_16u_I((Ipp16u *)pData->GetDataPointer(), m_pPacket->uiSize / 2);
#endif // _BIG_ENDIAN_
m_ParserState = HEADER;
PacketToMediaData(*m_pPacket, *pData);
return umcRes;
}
Ipp32u StreamParser::GetNumberOfTracks(void)
{
return m_pDataReader ? m_uiTracks : 0;
}
Mpeg2TrackInfo *StreamParser::GetTrackInfo(Ipp32u uiTrack)
{
return m_pDataReader && uiTrack < m_uiTracks ? m_pInfo[uiTrack] : NULL;
}
SystemStreamType StreamParser::GetSystemStreamType(void)
{
return m_pDataReader ? m_SystemType : UNDEF_STREAM;
}
void StreamParser::Reset(void)
{
m_ParserState = HEADER;
if (m_pPacket) m_pPacket->Reset();
}
Status StreamParser::SetPosition(Ipp64u bytePos)
{
PARSER_CHECK_INIT;
Reset();
return m_uiSourceSize ? m_pDataReader->SetPosition(IPP_MIN(bytePos, m_uiSourceSize)) : UMC_OK;
}
Ipp64u StreamParser::GetPosition(void)
{
return m_pDataReader ? m_pDataReader->GetPosition() : 0;
}
Ipp64u StreamParser::GetSize(void)
{
return m_pDataReader ? m_uiSourceSize : 0;
}
Status StreamParser::MoveToNextHeader()
{
PARSER_CHECK_INIT;
if (END_OF_STREAM == m_ParserState)
return UMC_ERR_END_OF_STREAM;
else if (HEADER == m_ParserState)
return UMC_OK;
Status umcRes = m_pDataReader->MovePosition(m_pPacket->iBufOffset + m_pPacket->uiSize);
Reset();
return umcRes;
}
Ipp64f StreamParser::GetDuration(void)
{
return m_pDataReader ? m_dDuration : -1.0;
}
Ipp32s StreamParser::GetTrackByPid(Ipp32u uiPid)
{
return GetTrackByPidOrCreateNew((Ipp32s)uiPid, NULL);
}
Ipp32s StreamParser::GetTrackByPidOrCreateNew(Ipp32s iPid, bool *pIsNew)
{
Ipp32u i;
for (i = 0; i < m_uiTracks; i++)
if (m_pInfo[i]->m_PID == (Ipp32u)iPid)
break;
if (i < m_uiTracks)
return (Ipp32s)i;
else if (!pIsNew || m_uiTracks >= MAX_TRACK)
return -1;
*pIsNew = true;
m_uiTracks;
if (!m_pInfo[m_uiTracks])
m_pInfo[m_uiTracks] = new Mpeg2TrackInfo;
m_pInfo[m_uiTracks]->m_PID = iPid;
m_uiTracks++;
return m_uiTracks - 1;
}
void StreamParser::PacketToMediaData(FCSample &packet, MediaData &data)
{
if (NULL == data.GetBufferPointer())
{
data.SetBufferPointer((Ipp8u *)1, packet.uiSize);
data.SetDataSize(packet.uiSize);
}
else
{
data.SetBufferPointer((Ipp8u *)data.GetBufferPointer(), packet.uiSize);
data.SetDataSize(packet.uiSize);
}
data.SetTime(packet.dPTS, packet.dDTS);
if (DynamicCast<SplMediaData>(&data))
((SplMediaData *)&data)->SetAbsPos(packet.uiAbsPos);
}
Status ParseInitialObjectDescriptor(Mpeg2TsPmt &pmt, Ipp8u *pParam, Ipp32s buflen);
Status Mpeg2PesParser::ParsePmtInfo(Mpeg2TsPmt &pmt)
{
Ipp8u *pPtr = NULL;
Ipp32u uiTag, uiLen;
if (pmt.pProgInfo && pmt.uiProgInfoLen)
{
DescriptorNavigator descrNav(pmt.pProgInfo, pmt.uiProgInfoLen);
while (NULL != (pPtr = descrNav.GetNextDescriptor(&uiTag, &uiLen)))
{
if (DESC_IOD == uiTag && uiLen > 2)
ParseInitialObjectDescriptor(pmt, pPtr + 2, uiLen - 2);
}
}
Ipp32u i;
for (i = 0; i < pmt.uiESs; i++)
{
bool bIsNew = false;
Ipp32s iTrack = GetTrackByPidOrCreateNew(pmt.pESs[i].uiPid, &bIsNew);
if (iTrack < 0 || !bIsNew)
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -