📄 umc_demuxer.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_default_memory_allocator.h"
#include "umc_demuxer.h"
#include "umc_mpeg2ps_parser.h"
#include "umc_mpeg2ts_parser.h"
//#define DUMP_SOMETHING
//#define DUMP_VIDEO_1X_TXT
//#define DUMP_VIDEO_FF_TXT
//#define DUMP_VIDEO_BF_TXT
//#define DUMP_AUDIO_TXT
//#define DUMP_VIDEO_1X_BIN
//#define DUMP_VIDEO_FF_BIN
//#define DUMP_VIDEO_BF_BIN
//#define DUMP_AUDIO_BIN
#define DEM_CHECK_INIT CHECK_OBJ_INIT(m_pParser)
namespace UMC
{
Splitter *CreateMPEG2SplitterNT(void) { return (new Demuxer()); }
Demuxer::Demuxer()
{
m_pParser = NULL;
}
Demuxer::~Demuxer()
{
Close();
}
Status Demuxer::Run(void)
{
DEM_CHECK_INIT;
return UMC_OK;
}
Status Demuxer::Stop(void)
{
DEM_CHECK_INIT;
return UMC_OK;
}
Status Demuxer::Close(void)
{
DEM_CHECK_INIT;
Ipp32s i;
for (i = 0; i < MAX_TRACK; i++)
{
if (m_pFC[i])
{
delete m_pFC[i];
m_pFC[i] = NULL;
}
if (m_pPrevData[i])
{
delete m_pPrevData[i];
m_pPrevData[i] = NULL;
}
}
if (m_pParser)
{
delete m_pParser;
m_pParser = NULL;
}
if (m_bInnerMemAllocator && m_pMemoryAllocator)
{
delete m_pMemoryAllocator;
m_pMemoryAllocator = NULL;
m_bInnerMemAllocator = false;
}
return UMC_OK;
}
Status Demuxer::Init(SplitterParams& init)
{
if (m_pParser) // already initialized
return UMC_ERR_FAILED;
if (NULL == init.m_pDataReader)
return UMC_ERR_NULL_PTR;
m_pParser = NULL;
m_pMemoryAllocator = NULL;
// detect type of stream
bool bEncrypted = (init.m_lFlags & FLAG_VSPL_ENCRYPTED_DATA) > 0;
m_SplInfo.m_SystemType = bEncrypted ? MPEG2_TRANSPORT_STREAM : DetectSystem(init.m_pDataReader);
// select stream parsers
StreamParserParams *pParserParams = NULL;
switch (m_SplInfo.m_SystemType)
{
case MPEG1_PROGRAMM_STREAM:
case MPEG2_PROGRAMM_STREAM:
case MPEG2_PES_PACKETS_STREAM:
m_pParser = new Mpeg2PsParser;
pParserParams = new StreamParserParams;
break;
case MPEG2_TRANSPORT_STREAM:
case MPEG2_TRANSPORT_STREAM_TTS:
case MPEG2_TRANSPORT_STREAM_TTS0:
m_pParser = new Mpeg2TsParser;
pParserParams = new Mpeg2TsParserParams;
break;
case WAVE_STREAM:
m_pParser = new WaveParser;
pParserParams = new StreamParserParams;
break;
case UNDEF_STREAM:
return UMC_ERR_INIT;
default: // pure streams
m_pParser = new StreamParser;
pParserParams = new StreamParserParams;
break;
}
if (!m_pParser || !pParserParams)
{
TerminateInit(pParserParams);
return UMC_ERR_ALLOC;
}
// prepare stream parser parameters
pParserParams->m_pDataReader = init.m_pDataReader;
pParserParams->m_SystemType = m_SplInfo.m_SystemType;
if (DynamicCast<DemuxerParams>(&init) && DynamicCast<Mpeg2TsParserParams>(pParserParams) &&
((DemuxerParams *)&init)->m_pOnPSIChangeEvent)
((Mpeg2TsParserParams *)pParserParams)->m_bDetectPSIChanges = true;
// initialize stream parser object
Status umcRes = m_pParser->Init(*pParserParams);
if (UMC_OK != umcRes)
{
TerminateInit(pParserParams);
return umcRes;
}
// estimate duration
m_dDuration = -1.0;
m_uiSourceSize = m_pParser->GetSize();
if (DynamicCast<Mpeg2PesParser>(m_pParser) && m_uiSourceSize > 0 && !bEncrypted)
{
m_Corrector.AttachParser((Mpeg2PesParser *)m_pParser);
m_dDuration = GetExactDuration();
}
// initialize info fields
m_SplInfo.m_dRate = 1.0;
m_SplInfo.m_dDuration = -1.0;
m_SplInfo.m_nOfTracks = 0;
m_SplInfo.m_splitter_flags = 0;
m_SplInfo.m_ppTrackInfo = m_pInfoStack;
ippsZero_8u((Ipp8u *)m_pInfoStack, MAX_TRACK * sizeof(void *));
// determine memory allocator
m_bInnerMemAllocator = (init.m_pMemoryAllocator == NULL);
m_pMemoryAllocator = m_bInnerMemAllocator ? new DefaultMemoryAllocator : init.m_pMemoryAllocator;
if (!m_pMemoryAllocator)
{
TerminateInit(pParserParams);
return UMC_ERR_ALLOC;
}
ippsZero_8u((Ipp8u *)m_pFC, MAX_TRACK * sizeof(void *));
ippsZero_8u((Ipp8u *)m_pPrevData, MAX_TRACK * sizeof(void *));
m_uiTracksReady = 0;
m_uiTracks = 0;
m_iCurTrack = -1;
m_iRefTrack = -1;
m_bEncryptedData = (init.m_lFlags & FLAG_VSPL_ENCRYPTED_DATA) > 0;
m_bBufFilled = false;
m_bPSIWasChanged = false;
m_bEndOfStream = false;
m_dRate = 1.0;
m_dBytesPerSec = -1.0;
m_uiNOfFrames = 0;
m_uiTotalSize = 0;
m_uiAdaptiveFactor = 1;
m_dPrevTimeGap = -1.0;
delete pParserParams;
return umcRes;
}
Status Demuxer::EnableTrack(Ipp32u nTrack, Ipp32s iState)
{
if (nTrack >= m_uiTracks)
return UMC_ERR_FAILED;
if (NULL == m_pFC[nTrack])
return UMC_ERR_FAILED;
// reset buffer if it was unselected before
if (1 == iState && !m_pFC[nTrack]->GetInfo()->m_isSelected)
m_pFC[nTrack]->Reset();
m_pFC[nTrack]->GetInfo()->m_isSelected = iState;
if (m_SplInfo.m_ppTrackInfo[nTrack])
m_SplInfo.m_ppTrackInfo[nTrack]->m_isSelected = iState;
if (m_iRefTrack < 0 || !m_pFC[m_iRefTrack]->GetInfo()->m_isSelected)
AssignRefTrack();
return UMC_OK;
}
Status Demuxer::SetRate(Ipp64f rate)
{
Status umcRes = UMC_OK;
m_dRate = rate;
m_uiAdaptiveFactor = 1;
m_dPrevTimeGap = -1.0;
m_bEndOfStream = false;
Ipp32s i;
for (i = 0; i < (Ipp32s)m_uiTracks; i++)
{
if (NULL != m_pFC[i])
{
m_pFC[i]->Reset();
m_pPrevData[i]->SetBufferPointer(NULL, 0);
m_pFC[i]->SetRate(rate);
}
}
if (m_dRate < 0.0 && m_iRefTrack >= 0 && m_pFC[m_iRefTrack]->GetInfo()->m_Type & TRACK_ANY_VIDEO)
m_Segmentator.RestartSegmentation(m_pParser, m_iRefTrack, (VideoFrameConstructor *)m_pFC[m_iRefTrack]);
return umcRes;
}
Status Demuxer::SetPosition(Ipp64u pos)
{
Status umcRes = m_pParser->SetPosition(pos);
if (UMC_OK != umcRes)
return umcRes;
m_iCurTrack = -1;
m_bEndOfStream = false;
Ipp32s i;
for (i = 0; i < (Ipp32s)m_uiTracks; i++)
{
if (NULL != m_pFC[i])
{
m_pFC[i]->Reset();
m_pPrevData[i]->SetBufferPointer(NULL, 0);
}
}
if (m_dRate < 0.0 && m_iRefTrack >= 0 && m_pFC[m_iRefTrack]->GetInfo()->m_Type & TRACK_ANY_VIDEO)
m_Segmentator.RestartSegmentation(m_pParser, m_iRefTrack, (VideoFrameConstructor *)m_pFC[m_iRefTrack]);
return UMC_OK;
}
Status Demuxer::SetTimePosition(Ipp64f timePos)
{
Status umcRes = UMC_OK;
Ipp32s attempt;
vm_debug_trace1(VM_DEBUG_INFO, VM_STRING("Demuxer: seek at %.3f sec\n"), timePos);
if (!DynamicCast<Mpeg2PesParser>(m_pParser) || 0 == m_uiSourceSize || m_dDuration <= 0.0)
{
Ipp64f duration = GetDuration();
return SetPosition(duration > 0.0 ? (Ipp64u)(timePos * ((Ipp64s)m_uiSourceSize / duration)) : (Ipp64u)0);
}
timePos += m_Start.dTime;
if (timePos < m_Start.dTime)
timePos = m_Start.dTime;
if (timePos > m_End.dTime)
timePos = m_End.dTime;
// reset streaming variables
m_iCurTrack = -1;
m_bEndOfStream = false;
// reset buffers
Ipp32u uiTrack;
for (uiTrack = 0; uiTrack < m_uiTracks; uiTrack++)
{
if (m_pFC[uiTrack])
{
m_pFC[uiTrack]->Reset();
m_pPrevData[uiTrack]->SetBufferPointer(NULL, 0);
}
}
// step-by-step approximation
CheckPoint checkPointA = m_Start;
CheckPoint checkPointB = m_End;
CheckPoint checkPointC;
Ipp64f dLocalBytesPerSec;
for (attempt = 0; attempt < 5; attempt++)
{
dLocalBytesPerSec = (Ipp64s)(checkPointB.uiPos - checkPointA.uiPos) / (checkPointB.dTime - checkPointA.dTime);
checkPointC.uiPos = (Ipp64u)((Ipp64s)checkPointA.uiPos + (dLocalBytesPerSec * (timePos - checkPointA.dTime)));
umcRes = m_pParser->SetPosition(checkPointC.uiPos);
if (UMC_OK != umcRes) return umcRes;
m_Corrector.ResetAfterReposition();
umcRes = m_Corrector.GetSystemTime(checkPointC);
if (UMC_OK != umcRes)
return umcRes;
// approximated point is coincide with one of ends (A or B)
if (checkPointC.uiPos == checkPointA.uiPos || checkPointC.uiPos == checkPointB.uiPos)
break;
if (checkPointC.dTime < timePos)
checkPointA = checkPointC;
else
checkPointB = checkPointC;
vm_debug_trace1(VM_DEBUG_INFO, VM_STRING("Demuxer: attempt %d \n"), attempt);
vm_debug_trace2(VM_DEBUG_INFO, VM_STRING("at byte %d, sec %.3f\n"), (Ipp32s)checkPointC.uiPos, checkPointC.dTime);
if (UMC_OK != umcRes || (timePos - checkPointC.dTime < 0.6 && timePos - checkPointC.dTime > -0.6))
break;
}
umcRes = m_pParser->SetPosition(checkPointC.uiPos);
if (m_dRate < 0.0 && m_iRefTrack >= 0 && m_pFC[m_iRefTrack]->GetInfo()->m_Type & TRACK_ANY_VIDEO)
m_Segmentator.RestartSegmentation(m_pParser, m_iRefTrack, (VideoFrameConstructor *)m_pFC[m_iRefTrack]);
vm_debug_trace(VM_DEBUG_INFO, VM_STRING("Demuxer: seeking finished\n"));
return UMC_OK;
}
Status Demuxer::GetTimePosition(Ipp64f &)
{
return UMC_ERR_NOT_IMPLEMENTED;
}
Status Demuxer::GetInfo(SplitterInfo **ppInfo)
{
Ipp32u i;
if (!ppInfo)
return UMC_ERR_NULL_PTR;
bool bDurationUpdated = false;
m_SplInfo.m_dRate = m_dRate;
if (m_SplInfo.m_dDuration < 0.0)
{
bDurationUpdated = true;
m_SplInfo.m_dDuration = GetDuration();
}
m_SplInfo.m_SystemType = m_pParser->GetSystemStreamType();
if (IsPure() && m_pFC[0])
{
if (TRACK_MPEG1V == m_pFC[0]->GetInfo()->m_Type)
m_SplInfo.m_SystemType = MPEG1_PURE_VIDEO_STREAM;
}
m_SplInfo.m_nOfTracks = m_uiTracks;
m_SplInfo.m_splitter_flags = 0;
for (i = 0; i < m_SplInfo.m_nOfTracks; i++)
{
m_SplInfo.m_ppTrackInfo[i] = m_pFC[i] ? m_pFC[i]->GetInfo() : m_pParser->GetTrackInfo(i);
((Mpeg2TrackInfo *)m_SplInfo.m_ppTrackInfo[i])->SetDuration(m_SplInfo.m_dDuration);
}
ppInfo[0] = &m_SplInfo;
return UMC_OK;
}
Status Demuxer::CheckNextData(MediaData *data, Ipp32u *pTrack)
{
Status umcRes = UMC_OK;
SplMediaData sample;
if (NULL == m_pParser)
return UMC_ERR_NOT_INITIALIZED;
if (m_bEndOfStream)
return UMC_ERR_END_OF_STREAM;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -