📄 umc_mpeg2_muxer_chunk.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) 2003-2007 Intel Corporation. All Rights Reserved.
//
*/
#include "ipps.h"
#include "ippdc.h"
#include "vm_debug.h"
#include "umc_mpeg2_muxer_chunk.h"
using namespace UMC;
/*
* MPEG2ChunkWriter
*/
MPEG2ChunkWriter::MPEG2ChunkWriter()
{
m_pDataWriter = NULL;
} //MPEG2ChunkWriter::MPEG2ChunkWriter()
MPEG2ChunkWriter::~MPEG2ChunkWriter()
{
Close();
} //MPEG2ChunkWriter::~MPEG2ChunkWriter()
Status MPEG2ChunkWriter::Close(void)
{
MPEG2MuxerLinearBuffer::Close();
m_pDataWriter = NULL;
m_ESType = MPEG2MUX_ES_UNKNOWN;
m_dReferenceClock = 0.0;
m_uiMuxRate = 0;
m_dFrameRate = 0.0;
m_uiBitRate = 0;
return UMC_OK;
} //Status MPEG2ChunkWriter::Close(void)
Status MPEG2ChunkWriter::Init(MediaReceiverParams *pInit)
{
UMC_CALL(MPEG2MuxerLinearBuffer::Init(pInit));
MPEG2ChunkWriterParams *pParams = DynamicCast<MPEG2ChunkWriterParams>(pInit);
if (!pParams || !pParams->pDataWriter)
return UMC_ERR_NULL_PTR;
m_pDataWriter = pParams->pDataWriter;
m_ESType = pParams->esType;
m_dFrameRate = pParams->dFrameRate;
m_uiBitRate = pParams->uiBitRate;
return UMC_OK;
} //Status MPEG2ChunkWriter::Init(MediaReceiverParams *pInit)
void MPEG2ChunkWriter::SetReferenceClock(Ipp64f dReferenceClock)
{
m_dReferenceClock = dReferenceClock;
} //void MPEG2ChunkWriter::SetReferenceClock(Ipp64f dReferenceClock)
void MPEG2ChunkWriter::SetMuxRate(Ipp32u uiMuxRate)
{
m_uiMuxRate = uiMuxRate;
} //void MPEG2ChunkWriter::SetMuxRate(Ipp32u uiMuxRate)
Status MPEG2ChunkWriter::GetOutputTime(Ipp64f &dTime)
{
if (m_uiNOfUsedSamples < 1)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;
dTime = m_pFirstUsedSample->dExactDTS;
return UMC_OK;
} //Status MPEG2ChunkWriter::GetOutputTime(Ipp64f &dTime)
Status MPEG2ChunkWriter::LockInputBuffer(MediaData *pData)
{
Status umcRes;
MPEG2MuxerSample sample;
umcRes = MPEG2MuxerLinearBuffer::LockInputBuffer(&sample);
pData->SetBufferPointer(sample.pData, sample.uiSize);
return umcRes;
} //Status MPEG2ChunkWriter::LockInputBuffer(MediaData *pData)
Status MPEG2ChunkWriter::UnLockInputBuffer(MediaData *pData, Status streamStatus)
{
if (UMC_OK != streamStatus)
return MPEG2MuxerLinearBuffer::UnLockInputBuffer(NULL, streamStatus);
MPEG2MuxerSample sample;
pData->GetTime(sample.dPTS, sample.dDTS);
// DTS should not be more or equal PTS
if (sample.dDTS >= sample.dPTS)
sample.dDTS = -1.0;
// DTS should not present for non-video streams
if (!IsVideo(m_ESType))
sample.dDTS = -1.0;
// first sample should have valid time stamp and it should be not earlier than 0.3 sec
Ipp64f time = sample.dDTS > 0.0 ? sample.dDTS : sample.dPTS;
if (m_dNextDTS < 0.0 && time < 0.0 && m_ESType != MPEG2MUX_ES_UNKNOWN)
return UMC_ERR_INVALID_PARAMS;
sample.uiFrameType = TYPE_UNDEF; // should be assigned for video frames
sample.pData = (Ipp8u *)pData->GetDataPointer();
sample.uiSize = pData->GetDataSize();
sample.uiTSOffset = 0; // should refer to picture start code for video frames
// estimate duration of the sample
if (IsVideo(m_ESType))
{
sample.dDuration = 1.0 / m_dFrameRate;
SetFrameTypeAndOffset(&sample);
}
else
sample.dDuration = (8.0 * sample.uiSize) / m_uiBitRate;
return MPEG2MuxerLinearBuffer::UnLockInputBuffer(&sample, streamStatus);
} //Status MPEG2ChunkWriter::UnLockInputBuffer(MediaData *pData, Status streamStatus)
Status MPEG2ChunkWriter::WriteChunk(void)
{
if (m_uiNOfUsedSamples == 0)
return m_bEndOfStream ? UMC_ERR_END_OF_STREAM : UMC_ERR_NOT_ENOUGH_DATA;
Ipp8u *pBuf = m_pFirstUsedSample->pData;
Ipp32s uiSize = (Ipp32s)m_pFirstUsedSample->uiSize;
UMC_CALL(m_pDataWriter->PutData(pBuf, uiSize));
return UnLockOutputBuffer(m_pFirstUsedSample);
} //Status MPEG2ChunkWriter::WriteChunk(void)
void MPEG2ChunkWriter::SetFrameTypeAndOffset(MPEG2MuxerSample *pData)
{
Ipp8u *pBuf = pData->pData;
Ipp32u uiSize = pData->uiSize;
Ipp32u uiPos = 0;
if (MPEG2MUX_ES_MPEG1_VIDEO == m_ESType ||
MPEG2MUX_ES_MPEG2_VIDEO == m_ESType)
{
for (uiPos = 0; uiPos + 5 < uiSize; uiPos++)
{
if (pBuf[uiPos + 0] == 0x00 &&
pBuf[uiPos + 1] == 0x00 &&
pBuf[uiPos + 2] == 0x01 &&
pBuf[uiPos + 3] == 0x00)
{
FrameType type = (FrameType)((pBuf[uiPos + 5] >> 3) & 0x07);
if (I_PICTURE == type)
pData->uiFrameType = TYPE_I_PIC;
else if (P_PICTURE == type)
pData->uiFrameType = TYPE_P_PIC;
else if (B_PICTURE == type)
pData->uiFrameType = TYPE_B_PIC;
else
pData->uiFrameType = TYPE_UNDEF;
pData->uiTSOffset = uiPos;
break;
}
}
}
else if (MPEG2MUX_ES_MPEG4_VIDEO == m_ESType)
{
for (uiPos = 0; uiPos + 4 < uiSize; uiPos++)
{
if (pBuf[uiPos + 0] == 0x00 &&
pBuf[uiPos + 1] == 0x00 &&
pBuf[uiPos + 2] == 0x01 &&
pBuf[uiPos + 3] == 0xb6)
{
FrameType type = (FrameType)((pBuf[uiPos + 4] >> 6) + 1);
if (I_PICTURE == type)
pData->uiFrameType = TYPE_I_PIC;
else if (P_PICTURE == type)
pData->uiFrameType = TYPE_P_PIC;
else if (B_PICTURE == type)
pData->uiFrameType = TYPE_B_PIC;
else
pData->uiFrameType = TYPE_UNDEF;
pData->uiTSOffset = uiPos;
break;
}
}
}
else if (MPEG2MUX_ES_H264_VIDEO == m_ESType)
{
for (uiPos = 0; uiPos + 4 < uiSize; uiPos++)
{
if (pBuf[uiPos + 0] == 0x00 &&
pBuf[uiPos + 1] == 0x00 &&
pBuf[uiPos + 2] == 0x00 &&
pBuf[uiPos + 3] == 0x01 &&
((pBuf[uiPos + 4] & 0x1f) == 0x01 || (pBuf[uiPos + 4] & 0x1f) == 0x05))
{
if ((pBuf[uiPos + 4] & 0x1f) == 0x05)
pData->uiFrameType = TYPE_I_PIC;
else
pData->uiFrameType = TYPE_UNDEF;
pData->uiTSOffset = uiPos;
break;
}
}
}
} //void MPEG2ChunkWriter::SetFrameTypeAndOffset(MPEG2MuxerSample *pData)
/*
* MPEG2PSChunkWriter
*/
MPEG2PSChunkWriter::MPEG2PSChunkWriter(void)
{
m_pHeaderBuf = NULL;
m_pSystemStreamID = NULL;
m_pSystemBoundScale = NULL;
m_pSystemSizeBound = NULL;
} //MPEG2PSChunkWriter::MPEG2PSChunkWriter(void)
MPEG2PSChunkWriter::~MPEG2PSChunkWriter(void)
{
Close();
} //MPEG2PSChunkWriter::~MPEG2PSChunkWriter(void)
Status MPEG2PSChunkWriter::Close(void)
{
MPEG2ChunkWriter::Close();
m_uiPacketSize = 0;
m_uiSpecialHeaderSize = 0;
m_uiPackHeaderSize = 0;
// System header section
m_uiSystemHeaderSize = 0;
m_uiSystemHeaderLength = 0;
m_uiSystemRateBound = 0;
m_uiSystemAudioBound = 0;
m_uiSystemVideoBound = 0;
m_uiSystemNumberOfStreams = 0;
UMC_FREE(m_pHeaderBuf);
UMC_FREE(m_pSystemStreamID);
UMC_FREE(m_pSystemBoundScale);
UMC_FREE(m_pSystemSizeBound);
m_uiStreamID = 0;
m_uiSubStreamID = 0;
m_uiOffset = 0;
m_uiNextOffset = 0;
m_uiNOfFrames = 0;
m_uiFrameNumber = 0;
return UMC_OK;
} //Status MPEG2PSChunkWriter::Close(void)
Status MPEG2PSChunkWriter::Init(MediaReceiverParams *pInit)
{
UMC_CALL(MPEG2ChunkWriter::Init(pInit));
MPEG2PSChunkWriterParams *pParams = DynamicCast<MPEG2PSChunkWriterParams>(pInit);
UMC_CHECK_PTR(pParams);
m_uiSpecialHeaderSize = 0;
if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
m_uiSpecialHeaderSize = 7;
else if (MPEG2MUX_ES_AC3_AUDIO == m_ESType)
m_uiSpecialHeaderSize = 4;
m_uiPacketSize = IPP_MAX(pParams->uiPacketSize, MPEG2MUX_CHUNK_HEADER_SIZE);
UMC_ALLOC_ARR(m_pHeaderBuf, Ipp8u, MPEG2MUX_CHUNK_HEADER_SIZE);
m_uiHeaderBufSize = 0;
// Pack header section
m_uiPackHeaderSize = pParams->bPackHeaderPresent ? 14 : 0;
m_dReferenceClock = 0.0;
m_uiMuxRate = 0;
// System header section
m_uiSystemHeaderSize = 0;
m_uiSystemHeaderLength = 0;
// PES header section
m_uiStreamID = pParams->uiStreamID;
m_uiSubStreamID = pParams->uiSubStreamID;
return UMC_OK;
} //Status MPEG2PSChunkWriter::Init(MediaReceiverParams *pInit)
Status MPEG2PSChunkWriter::SetSystemHeaderParams(SystemHeaderParams *pSysHeaderParams)
{
UMC_CHECK_PTR(pSysHeaderParams);
UMC_CHECK_PTR(pSysHeaderParams->pSystemStreamID);
UMC_CHECK_PTR(pSysHeaderParams->pSystemSizeBound);
// System header section
m_uiSystemHeaderSize = 0;
m_uiSystemHeaderLength = 0;
m_uiSystemRateBound = pSysHeaderParams->uiSystemRateBound;
m_uiSystemAudioBound = pSysHeaderParams->uiSystemAudioBound;
m_uiSystemVideoBound = pSysHeaderParams->uiSystemVideoBound;
m_uiSystemNumberOfStreams = pSysHeaderParams->uiSystemNumberOfStreams;
m_uiSystemHeaderLength = 6 + 3 * m_uiSystemNumberOfStreams;
UMC_ALLOC_ARR(m_pSystemStreamID, Ipp32u, m_uiSystemNumberOfStreams);
UMC_ALLOC_ARR(m_pSystemSizeBound, Ipp32u, m_uiSystemNumberOfStreams);
UMC_ALLOC_ARR(m_pSystemBoundScale, Ipp32u, m_uiSystemNumberOfStreams);
ippsCopy_32s((Ipp32s *)pSysHeaderParams->pSystemStreamID, (Ipp32s *)m_pSystemStreamID, m_uiSystemNumberOfStreams);
ippsCopy_32s((Ipp32s *)pSysHeaderParams->pSystemSizeBound, (Ipp32s *)m_pSystemSizeBound, m_uiSystemNumberOfStreams);
Ipp32u i;
for (i = 0; i < m_uiSystemNumberOfStreams; i++)
{
m_pSystemBoundScale[i] = 1; // means video
if (m_pSystemStreamID[i] == 0xb8 ||
m_pSystemStreamID[i] == 0xbf ||
m_pSystemStreamID[i] >= 0xc0 && m_pSystemStreamID[i] <= 0xdf)
m_pSystemBoundScale[i] = 0; // means audio
m_pSystemSizeBound[i] /= m_pSystemBoundScale[i] ? 1024 : 128;
}
return UMC_OK;
} //Status MPEG2PSChunkWriter::SetSystemHeaderParams(SystemHeaderParams *pSysHeaderParams)
void MPEG2PSChunkWriter::ToggleSystemHeader(void)
{
m_uiSystemHeaderSize = 6 + m_uiSystemHeaderLength;
} //void MPEG2PSChunkWriter::ToggleSystemHeader(void)
void MPEG2PSChunkWriter::GenerateNonPESHeaders(void)
{
AdvancedBitStream bs;
if (m_uiPackHeaderSize)
{
bs.Reset(m_pHeaderBuf, MPEG2MUX_CHUNK_HEADER_SIZE);
Ipp32u scrExt = (Ipp32u)(((Ipp64u)(m_dReferenceClock * MPEG2MUX_SYS_CLOCK_FREQ)) % 300);
Ipp64u scrBase = ((Ipp64u)(m_dReferenceClock * MPEG2MUX_SYS_CLOCK_FREQ)) / 300;
bs.AddBits(0x000001BA, 32); // pack_start_code
bs.AddBits(0x01, 2); // 01
bs.AddBits((Ipp32u)((scrBase >> 30) & 0x7), 3); // system_clock_reference_base [32..30]
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits((Ipp32u)((scrBase >> 15) & 0x7FFF), 15); // system_clock_reference_base [29..15]
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits((Ipp32u)(scrBase & 0x7FFF), 15); // system_clock_reference_base [14..0]
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits(scrExt & 0x1FF, 9); // system_clock_reference_extension
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits(m_uiMuxRate / 50, 22); // program_mux_rate
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits(0x1f, 5); // reserved
bs.AddBits(0x00, 3); // pack_stuffing_length
m_uiHeaderBufSize = bs.m_lpb - m_pHeaderBuf;
}
if (m_uiSystemHeaderSize > 0)
{
bs.Reset(&m_pHeaderBuf[m_uiHeaderBufSize], MPEG2MUX_CHUNK_HEADER_SIZE - m_uiHeaderBufSize);
bs.AddBits(0x000001BB, 32); // pack_start_code
bs.AddBits(m_uiSystemHeaderLength, 16); // header_length
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits(m_uiSystemRateBound / 50, 22); // rate_bound
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits(m_uiSystemAudioBound, 6); // audio_bound
bs.AddBits(0x00, 1); // fixed_flag
bs.AddBits(0x00, 1); // CSPS_flag
bs.AddBits(0x00, 1); // system_audio_lock_flag
bs.AddBits(0x00, 1); // system_video_lock_flag
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits(m_uiSystemVideoBound, 5); // video_bound
bs.AddBits(0x00, 1); // packet_rate_restriction_flag
bs.AddBits(0x7f, 7); // reserved_byte
Ipp32u i;
for (i = 0; i < m_uiSystemNumberOfStreams; i++)
{
bs.AddBits(m_pSystemStreamID[i], 8); // stream_id
bs.AddBits(0x3, 2); // '11'
bs.AddBits(m_pSystemBoundScale[i], 1); // P-STD_buffer_bound_scale
bs.AddBits(m_pSystemSizeBound[i], 13); // P-STD_buffer_size_bound
}
m_uiSystemHeaderSize = 0;
m_uiHeaderBufSize = bs.m_lpb - m_pHeaderBuf;
}
} //void MPEG2PSChunkWriter::GenerateNonPESHeaders(void)
void MPEG2PSChunkWriter::GeneratePESHeader(void)
{
AdvancedBitStream bs;
bs.Reset(&m_pHeaderBuf[m_uiHeaderBufSize], MPEG2MUX_CHUNK_HEADER_SIZE - m_uiHeaderBufSize);
bs.AddBits(0x000001, 24); // PES start code
bs.AddBits(m_uiStreamID, 8); // stream_id
bs.AddBits(m_uiPESPacketLength, 16); // PES_packet_length
bs.AddBits(0x02, 2); // '10'
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -