📄 umc_demuxer.cpp
字号:
if (NULL == data || NULL == pTrack)
return UMC_ERR_NULL_PTR;
if (m_bPSIWasChanged)
{
// CheckNextData was called after notification about PSI changes
// destroy all frame constructors
Ipp32u i;
for(i = 0; i < m_uiTracks; i++)
{
// invalidate allocated TrackInfo structure (instead of deleting them)
if (m_SplInfo.m_ppTrackInfo[i])
((Mpeg2TrackInfo *)m_SplInfo.m_ppTrackInfo[i])->m_iFirstFrameOrder = -1;
// destroy allocated frame constructors
if (m_pFC[i])
{
delete m_pFC[i];
m_pFC[i] = NULL;
}
}
m_uiTracks = 0;
m_bPSIWasChanged = false;
}
if (m_dRate < 0.0)
umcRes = CheckNextDataBackward(&sample, pTrack);
else
umcRes = CheckNextDataForward(&sample, pTrack);
if (UMC_ERR_END_OF_STREAM == umcRes)
{
// if end of stream occurs, deliver END_OF_STREAM to all FCs
Ipp32u i = 0;
for (i = 0; i < m_uiTracks; i++)
{
if (m_pFC[i])
umcRes = m_pFC[i]->UnLockInputBuffer(NULL, UMC_ERR_END_OF_STREAM);
if (umcRes == UMC_OK)
{
*pTrack = m_iCurTrack = i;
break;
}
}
if (UMC_OK != umcRes)
m_bEndOfStream = true;
}
if (UMC_OK == umcRes)
{
SplMediaData *pMediaSampleData = DynamicCast<SplMediaData>(data);
if (pMediaSampleData)
*pMediaSampleData = sample;
else
*data = *((MediaData *)&sample);
}
return umcRes;
}
Status Demuxer::GetNextData(MediaData *data, Ipp32u *pTrack)
{
Status umcRes = UMC_ERR_END_OF_STREAM;
Ipp32s i;
// parse one frame (exactly)
umcRes = CheckNextData(data, pTrack);
if (UMC_OK == umcRes)
{
// if OK, get parsed frame and return it
umcRes = m_pFC[m_iCurTrack]->LockOutputBuffer(data);
if (UMC_OK == umcRes)
m_pFC[m_iCurTrack]->UnLockOutputBuffer(data);
}
if (UMC_OK != umcRes)
{
// in case of error try to find frame in buffers
for (i = 0; i < (Ipp32s)m_uiTracks; i++)
{
if (m_pFC[i])
{
umcRes = m_pFC[i]->LockOutputBuffer(data);
if (UMC_OK == umcRes)
{
umcRes = m_pFC[i]->UnLockOutputBuffer(data);
*pTrack = i;
break;
}
}
}
}
return umcRes;
}
Status Demuxer::CheckNextDataForward(SplMediaData *data, Ipp32u *pTrack)
{
Status umcRes = UMC_OK;
SplMediaData chunk;
Mpeg2TrackInfo *pInfo = NULL;
bool bFrameFound = false;
chunk.SetBufferPointer((Ipp8u *)1, 0);
// try to find next frame in last used buffer
if (-1 != m_iCurTrack)
{
umcRes = m_pFC[m_iCurTrack]->UnLockInputBuffer(NULL);
if (UMC_OK == umcRes)
{
bFrameFound = true;
*pTrack = m_iCurTrack;
}
else
m_iCurTrack = -1;
}
while (!bFrameFound)
{
// check current data chunk
umcRes = m_pParser->CheckNextData(&chunk, pTrack);
if (UMC_OK != umcRes)
{
if (UMC_WRN_INVALID_STREAM == umcRes)
{
Ipp32u i;
for(i = 0; i < m_uiTracks; i++)
{
if (m_pFC[i])
m_pFC[i]->UnLockInputBuffer(NULL, UMC_ERR_END_OF_STREAM);
}
m_iCurTrack = -1;
m_iRefTrack = -1;
m_bPSIWasChanged = true;
}
return umcRes;
}
m_iCurTrack = *pTrack;
// check and if stream is new try to register it
if (NULL == m_pFC[m_iCurTrack])
umcRes = CreateFrameConstructor(m_iCurTrack);
if (m_pFC[m_iCurTrack])
pInfo = m_pFC[m_iCurTrack]->GetInfo();
// pass data from parser to frame constructor
if ((!m_pFC[m_iCurTrack]) ||
(!pInfo->m_isSelected && pInfo->m_iFirstFrameOrder >= 0) ||
(m_dRate > 1.0 && m_iCurTrack != m_iRefTrack))
{
// skip when frame constructor was failed to be created
// skip packets from all except reference track at non-normal playback
// skip packets from unselected tracks for those first frame was constructed
umcRes = m_pParser->MoveToNextHeader();
if (UMC_OK != umcRes) return umcRes;
}
else
{
// order space for chunk in FC's buffer
umcRes = m_pFC[m_iCurTrack]->LockInputBuffer(&chunk);
if (UMC_OK != umcRes)
{
m_bBufFilled = true;
return umcRes;
}
// copy chunk from parser to FC's buffer
umcRes = m_pParser->GetNextData(&chunk, pTrack);
if (UMC_OK != umcRes)
return umcRes;
// ask for whole frame
umcRes = m_pFC[m_iCurTrack]->UnLockInputBuffer(&chunk);
if (UMC_OK == umcRes)
bFrameFound = true;
}
}
m_pFC[m_iCurTrack]->GetLastFrame(data);
if (m_pFC[m_iCurTrack]->GetInfo()->m_iFirstFrameOrder < 0)
{
m_pFC[m_iCurTrack]->GetInfo()->m_iFirstFrameOrder = m_uiTracksReady;
m_uiTracksReady += 1;
}
if (m_iCurTrack == m_iRefTrack)
{
m_uiTotalSize += data->GetDataSize();
m_uiNOfFrames++;
}
// very fast forward adaptive jump
if (m_uiSourceSize > 0 && -1 != m_iCurTrack && m_dRate > 4.0 && m_dBytesPerSec > 0.0)
{
Ipp64u pos, newPos;
Ipp64f frameRate = ((VideoStreamInfo *)m_pFC[m_iRefTrack]->GetInfo()->m_pStreamInfo)->framerate;
Ipp32s bytesPerFrame = (Ipp32s)(0.5 * m_dBytesPerSec / ((frameRate > 0.0) ? frameRate : 30.0));
pos = m_pParser->GetPosition();
newPos = pos + (Ipp32s)(bytesPerFrame * (m_dRate - 1.0) * m_uiAdaptiveFactor);
m_pParser->SetPosition(newPos);
if (-1 != m_iRefTrack)
m_pFC[m_iRefTrack]->SoftReset();
}
return umcRes;
}
Status Demuxer::CheckNextDataBackward(SplMediaData *data, Ipp32u *pTrack)
{
Status umcRes = UMC_OK;
for (;;)
{
// pull next segment
umcRes = m_Segmentator.PullSegment(data);
if (UMC_OK != umcRes && UMC_ERR_NOT_ENOUGH_DATA != umcRes)
return umcRes;
// check if at least one sample is available
if (UMC_OK == m_pFC[m_iRefTrack]->LockOutputBuffer(data))
break;
}
if (UMC_OK == umcRes && m_uiSourceSize > 0 && m_dRate < -4.0 && m_dBytesPerSec > 0.0)
{
Ipp64f frameRate = ((VideoStreamInfo *)m_pFC[m_iRefTrack]->GetInfo()->m_pStreamInfo)->framerate;
Ipp32s bytesPerFrame = (Ipp32s)(1.0 * m_dBytesPerSec / ((frameRate > 0.0) ? frameRate : 30.0));
m_Segmentator.AdditionalJump((Ipp32s)(bytesPerFrame * (m_dRate + 1.0) * m_uiAdaptiveFactor));
}
pTrack[0] = m_iRefTrack;
return UMC_OK;
}
Status Demuxer::CheckNextData(MediaData* data, Ipp32u uiTrack)
{
if (NULL == data)
return UMC_ERR_NULL_PTR;
if (uiTrack >= m_uiTracks)
return UMC_ERR_FAILED;
if (!m_pFC[uiTrack] || !m_pFC[uiTrack]->GetInfo()->m_isSelected)
return UMC_ERR_FAILED;
return m_pFC[uiTrack]->LockOutputBuffer(data);
}
Status Demuxer::GetNextData(MediaData* data, Ipp32u uiTrack)
{
if (NULL == data)
return UMC_ERR_NULL_PTR;
if (uiTrack >= m_uiTracks)
return UMC_ERR_FAILED;
if (!m_pFC[uiTrack] || !m_pFC[uiTrack]->GetInfo()->m_isSelected)
return UMC_ERR_FAILED;
m_pFC[uiTrack]->UnLockOutputBuffer(m_pPrevData[uiTrack]);
Status umcRes = m_pFC[uiTrack]->LockOutputBuffer(data);
if (UMC_OK == umcRes)
m_pPrevData[uiTrack][0] = data[0];
#ifdef DUMP_SOMETHING
if (UMC_OK == umcRes)
DumpSample(uiTrack);
#endif //DUMP_SOMETHING
return umcRes;
}
Ipp32s Demuxer::GetTrackByPid(Ipp32u uiPid)
{
return m_pParser ? m_pParser->GetTrackByPid(uiPid) : -1;
}
void Demuxer::AlterQuality(Ipp64f time)
{
if (time > 0.0)
if (time > m_dPrevTimeGap)
m_uiAdaptiveFactor++;
m_dPrevTimeGap = time;
vm_debug_trace2(VM_DEBUG_PROGRESS, VM_STRING("Demuxer::AlterQuality(time=%f), new adaptive factor is %d\n"), time, m_uiAdaptiveFactor);
}
Status Demuxer::CreateFrameConstructor(Ipp32s iTrack)
{
Status umcRes = UMC_OK;
Ipp32u size = AUDIO_BUFFER_SIZE;
m_uiTracks = m_pParser->GetNumberOfTracks();
Mpeg2TrackInfo *pInfo = m_pParser->GetTrackInfo(iTrack);
if (!pInfo)
return UMC_ERR_FAILED;
m_pFC[iTrack] = NULL;
if (m_bEncryptedData)
{
m_pFC[iTrack] = new PesFrameConstructor;
size = AUDIO_BUFFER_SIZE;
if (m_iRefTrack < 0)
m_iRefTrack = iTrack;
}
else if (pInfo->m_Type & TRACK_ANY_VIDEO)
{
if ((TRACK_MPEG1V | TRACK_MPEG2V) & pInfo->m_Type)
m_pFC[iTrack] = new Mpeg2FrameConstructor;
else if (TRACK_MPEG4V == pInfo->m_Type)
m_pFC[iTrack] = new Mpeg4FrameConstructor;
else if (TRACK_H261 == pInfo->m_Type)
m_pFC[iTrack] = new H261FrameConstructor;
else if (TRACK_H263 == pInfo->m_Type)
m_pFC[iTrack] = new H263FrameConstructor;
else if (TRACK_H264 == pInfo->m_Type)
m_pFC[iTrack] = new H264FrameConstructor;
else
m_pFC[iTrack] = new FrameConstructor;
if (NULL == m_pFC[iTrack])
return UMC_ERR_ALLOC;
if (-1 == m_iRefTrack || !(m_pParser->GetTrackInfo(m_iRefTrack)->m_Type & TRACK_ANY_VIDEO))
m_iRefTrack = iTrack;
size = VIDEO_BUFFER_SIZE;
}
else if (pInfo->m_Type & TRACK_ANY_AUDIO)
{
if (MPEGx_PURE_AUDIO_STREAM == m_SplInfo.m_SystemType ||
WAVE_STREAM == m_SplInfo.m_SystemType ||
AVI_STREAM == m_SplInfo.m_SystemType)
m_pFC[iTrack] = new PureAudioFrameConstructor;
else
{
if (AAC_MPEG4_STREAM == ((AudioStreamInfo *)pInfo->m_pStreamInfo)->stream_type)
m_pFC[iTrack] = new TimeStampedAudioFrameConstructor;
else
m_pFC[iTrack] = new BufferedAudioFrameConstructor;
}
if (NULL == m_pFC[iTrack])
return UMC_ERR_ALLOC;
if (-1 == m_iRefTrack)
m_iRefTrack = iTrack;
}
else if (pInfo->m_Type & TRACK_ANY_VBI)
{
m_pFC[iTrack] = new TimeStampedAudioFrameConstructor;
if (NULL == m_pFC[iTrack])
return UMC_ERR_ALLOC;
}
else if (pInfo->m_Type & TRACK_ANY_SPECIAL)
{
m_pFC[iTrack] = new FrameConstructor;
if (NULL == m_pFC[iTrack])
return UMC_ERR_ALLOC;
}
else // TRACK_UNKNOWN
{
return UMC_OK;
}
FrameConstructorParams fcParams;
fcParams.m_nOfFrames = 10;
fcParams.m_lBufferSize = size;
fcParams.m_pInfo = pInfo;
fcParams.m_pMemoryAllocator = m_pMemoryAllocator;
umcRes = m_pFC[iTrack]->Init((MediaReceiverParams *)&fcParams);
if (UMC_OK != umcRes)
return umcRes;
if (!m_pPrevData[iTrack])
m_pPrevData[iTrack] = new MediaData;
m_pPrevData[iTrack]->SetBufferPointer(NULL, 0);
return umcRes;
}
Ipp64f Demuxer::GetDuration(void)
{
// first, check if parser provides duration
if (m_pParser->GetDuration() >= 0.0)
{
m_dDuration = m_pParser->GetDuration();
return m_dDuration;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -