📄 umc_mpeg2_muxer_chunk.cpp
字号:
bs.AddBits(0x00, 2); // PES_scrambling_control
bs.AddBits(0x00, 1); // PES_priority
bs.AddBits(0x00, 1); // data_alignment_indicator
bs.AddBits(0x00, 1); // copyright
bs.AddBits(0x00, 1); // original_or_copy
bs.AddBits(m_uiPTSDTSFlags, 2); // PTS_DTS_flags
bs.AddBits(0x00, 1); // ESCR_flag
bs.AddBits(0x00, 1); // ES_rate_flag
bs.AddBits(0x00, 1); // DSM_trick_mode_flag
bs.AddBits(0x00, 1); // additional_copy_info_flag
bs.AddBits(0x00, 1); // PES_CRC_flag
bs.AddBits(0x00, 1); // PES_extension_flag
bs.AddBits(m_uiPESHeaderDataLength, 8); // PES_header_data_length
if (m_uiPTSDTSFlags & 0x02)
{
Ipp64u pts = (Ipp64u)(payload.dPTS * 90000.0 + 0.5);
bs.AddBits(m_uiPTSDTSFlags & 3, 4); // '0010' or '0011'
bs.AddBits((Ipp32s)((pts >> 30) & 0x07), 3); // PTS [32..30]
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits((Ipp32s)((pts >> 15) & 0x7fff), 15); // PTS [29..15]
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits((Ipp32s)(pts & 0x7fff), 15); // PTS [14..0]
bs.AddBits(0x01, 1); // marker_bit
}
if (0x03 == m_uiPTSDTSFlags)
{
Ipp64u dts = (Ipp64u)(payload.dDTS * 90000.0 + 0.5);
bs.AddBits(0x01, 4); // '0001'
bs.AddBits((Ipp32s)((dts >> 30) & 0x07), 3); // DTS [32..30]
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits((Ipp32s)((dts >> 15) & 0x7fff), 15); // DTS [29..15]
bs.AddBits(0x01, 1); // marker_bit
bs.AddBits((Ipp32s)(dts & 0x7fff), 15); // DTS [14..0]
bs.AddBits(0x01, 1); // marker_bit
}
Ipp32u i;
for (i = 0; i < m_uiNOfStuffingBytes; i++)
bs.AddBits(0xff, 8); // stuffing_byte
m_uiHeaderBufSize = bs.m_lpb - m_pHeaderBuf;
} //void MPEG2PSChunkWriter::GeneratePESHeader(void)
void MPEG2PSChunkWriter::GenerateSpecialHeader(void)
{
AdvancedBitStream bs;
bs.Reset(&m_pHeaderBuf[m_uiHeaderBufSize], MPEG2MUX_CHUNK_HEADER_SIZE - m_uiHeaderBufSize);
if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
{
bs.AddBits(m_uiSubStreamID, 8); // LPCM_ID (0xA0...0xA7)
bs.AddBits(m_uiNOfFrames, 8); // number_of_frames
bs.AddBits(m_uiOffset + 4, 16); // first_access_unit_pointer (4)
bs.AddBits(0x00, 1); // emphasis_flag (off)
bs.AddBits(0x00, 1); // mute_flag (off)
bs.AddBits(0x00, 1); // reserved
bs.AddBits(m_uiFrameNumber, 5); // number_of_frame
bs.AddBits(0x00, 2); // sample_size_code (16bit)
bs.AddBits(0x00, 2); // sample_rate_code (48k)
bs.AddBits(0x09, 4); // number_of_channels_code (dual_mono)
bs.AddBits(0x80, 8); // dynamic_range_control
// update special header fields
m_uiFrameNumber = (m_uiFrameNumber + m_uiNOfFrames) % 20;
m_uiOffset = m_uiNextOffset;
m_uiNOfFrames = 0;
}
else if (MPEG2MUX_ES_AC3_AUDIO == m_ESType)
{
bs.AddBits(m_uiSubStreamID, 8); // AC3_ID (0x80...0x87)
bs.AddBits(0x00, 1); // emphasis_flag (off)
bs.AddBits(0x00, 1); // mute_flag (off)
bs.AddBits(0x00, 1); // reserved
bs.AddBits(m_uiNOfFrames, 5); // number_of_frames
bs.AddBits(m_uiOffset, 16); // offset of first access unit
// update special header fields
m_uiNOfFrames = 0;
m_uiOffset = m_uiNextOffset;
}
m_uiHeaderBufSize = bs.m_lpb - m_pHeaderBuf;
} //void MPEG2PSChunkWriter::GenerateSpecialHeader(void)
Status MPEG2PSChunkWriter::PrepareChunk(void)
{
m_uiPESPacketLength = 0;
m_uiPESHeaderDataLength = 0;
m_uiNOfStuffingBytes = 0;
m_uiNOfPaddingBytes = 0;
m_uiPayloadSize = 0;
m_uiPTSDTSFlags = 0x00;
// calculate PES_packet_length of PES packet
m_uiPESPacketLength = m_uiPacketSize;
m_uiPESPacketLength -= m_uiPackHeaderSize; // pack header if exist
m_uiPESPacketLength -= m_uiSystemHeaderSize; // system header if exist
m_uiPESPacketLength -= 6; // PES_start_code and PES_header_length
// calculate maximum space available for payload
m_uiPayloadSize = m_uiPESPacketLength;
m_uiPayloadSize -= 3; // PES_flags and PES_header_data_length field
m_uiPayloadSize -= m_uiSpecialHeaderSize; // special header (AC3 or LPCM)
// try to get payload
payload.uiSize = m_uiPayloadSize;
if (MPEG2MUX_ES_AC3_AUDIO == m_ESType)
payload.uiSize += 4; // it is to be sure that whole AC3 header will be available
UMC_CALL(LockOutputBuffer(&payload));
// analize time stamps
if (payload.dPTS > 0.0)
{
m_uiPESHeaderDataLength += 5;
m_uiPayloadSize -= 5;
m_uiPTSDTSFlags = 0x02;
if (payload.dDTS > 0.0)
{
m_uiPESHeaderDataLength += 5;
m_uiPayloadSize -= 5;
m_uiPTSDTSFlags = 0x03;
}
}
//analize size of payload
if (payload.uiSize < m_uiPayloadSize)
{
if (m_uiPayloadSize - payload.uiSize > 6)
{ // size of payload is much smaller, padding packet is needed
m_uiNOfPaddingBytes = m_uiPayloadSize - payload.uiSize;
m_uiPESPacketLength -= m_uiNOfPaddingBytes;
}
else
{ // size of payload is not much smaller, add stuffing bytes right to PES header
m_uiNOfStuffingBytes = m_uiPayloadSize - payload.uiSize;
m_uiPESHeaderDataLength += m_uiNOfStuffingBytes;
}
m_uiPayloadSize = payload.uiSize;
}
else
{
payload.uiSize = m_uiPayloadSize;
if (payload.uiTSOffset >= m_uiPayloadSize)
{ // time stamps is proved to be out of this packet
if (m_uiPTSDTSFlags & 0x02)
{ // add stuffing bytes intead of time stamps
m_uiNOfStuffingBytes += 5;
if (m_uiPTSDTSFlags == 0x03)
m_uiNOfStuffingBytes += 5;
}
m_uiPTSDTSFlags = 0x00;
}
}
// prepare special header fields
if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
{
if (payload.uiSize & 1)
{ // even number of byte of LPCM should be written
m_uiPayloadSize--;
payload.uiSize--;
m_uiNOfStuffingBytes++;
m_uiPESHeaderDataLength++;
}
m_uiNOfFrames = (payload.uiSize - m_uiOffset + MPEG2MUX_LPCM_FRAME_SIZE - 1) / MPEG2MUX_LPCM_FRAME_SIZE;
m_uiNextOffset = m_uiOffset + m_uiNOfFrames * MPEG2MUX_LPCM_FRAME_SIZE - payload.uiSize;
}
else if (MPEG2MUX_ES_AC3_AUDIO == m_ESType)
{
Ipp8u *pBuf = payload.pData;
Ipp32u uiPos = 0;
m_uiFrameNumber = 0;
if (m_uiOffset >= m_uiPayloadSize)
{ // AC3 syncword is out of this packet, update offset
m_uiOffset -= m_uiPayloadSize;
return UMC_OK;
}
if (pBuf[uiPos + m_uiOffset] != 0x0b || pBuf[uiPos + m_uiOffset + 1] != 0x77)
{ // wrong offset, look for AC3 syncword
for (; uiPos < m_uiPayloadSize; uiPos++)
if (pBuf[uiPos] == 0x0b && pBuf[uiPos + 1] == 0x77)
break;
// offset is not found in this packet
if (uiPos >= m_uiPayloadSize)
return UMC_OK;
m_uiOffset = uiPos; // correct offset is found
}
else
{ // correct offset, go to it
uiPos = m_uiOffset;
}
m_uiFrameNumber++; // one AC3 syncword is found
// evaluate next offset
Ipp8u fscod = pBuf[uiPos + 4] >> 6;
Ipp8u frmsizecod = pBuf[uiPos + 4] & 0x3F;
m_uiNextOffset = 2 * AC3FrameSize[3 * frmsizecod + fscod];
// count AC3 frames
while (uiPos + m_uiNextOffset < m_uiPayloadSize)
{
if (pBuf[uiPos + m_uiNextOffset] != 0x0b || pBuf[uiPos + m_uiNextOffset + 1] != 0x77)
{ // wrong offset, look for AC3 syncword
m_uiNextOffset = 0;
for (; uiPos < m_uiPayloadSize; uiPos++)
if (pBuf[uiPos] == 0x0b && pBuf[uiPos + 1] == 0x77)
break;
// no more AC3 syncwords in this packet
if (uiPos >= m_uiPayloadSize)
break;
m_uiNextOffset = uiPos; // correct offset is found
}
else
uiPos += m_uiNextOffset;
m_uiFrameNumber++;
fscod = pBuf[uiPos + 4] >> 6;
frmsizecod = pBuf[uiPos + 4] & 0x3F;
m_uiNextOffset = 2 * AC3FrameSize[3 * frmsizecod + fscod];
}
m_uiNextOffset -= m_uiPayloadSize - uiPos;
}
return UMC_OK;
} //Status MPEG2PSChunkWriter::PrepareChunk(void)
Status MPEG2PSChunkWriter::WriteChunk(void)
{
UMC_CALL(PrepareChunk());
GenerateNonPESHeaders();
GeneratePESHeader();
if (m_uiSpecialHeaderSize > 0)
GenerateSpecialHeader();
// write headers
Ipp32s iToWrite = (Ipp32s)m_uiHeaderBufSize;
UMC_CALL(m_pDataWriter->PutData(m_pHeaderBuf, iToWrite));
#ifndef _BIG_ENDIAN_
if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
ippsSwapBytes_16u_I((Ipp16u *)payload.pData, payload.uiSize / 2);
#endif
// write payload data
iToWrite = (Ipp32s)payload.uiSize;
UMC_CALL(m_pDataWriter->PutData(payload.pData, iToWrite));
// check if packet is had to be padded
if (m_uiNOfPaddingBytes > 0)
{
UMC_CALL(WritePadding(m_uiNOfPaddingBytes));
}
return UnLockOutputBuffer(&payload);
} //Status MPEG2PSChunkWriter::WriteChunk(void)
static const Ipp8u paddingArray[2048] = {0x00};
Status MPEG2PSChunkWriter::WritePadding(Ipp32s iNOfPaddingBytes)
{
Ipp32s iToWrite, i;
Ipp32s size = iNOfPaddingBytes - 6;
if (size < 0)
size += m_uiPacketSize;
Ipp8u pPaddingHeader[6];
pPaddingHeader[0] = 0x00;
pPaddingHeader[1] = 0x00;
pPaddingHeader[2] = 0x01;
pPaddingHeader[3] = MPEG2MUX_PES_ID_PADDING;
pPaddingHeader[4] = (Ipp8u)(size >> 8);
pPaddingHeader[5] = (Ipp8u)(size & 0xFF);
iToWrite = 6;
UMC_CALL(m_pDataWriter->PutData(pPaddingHeader, iToWrite));
iToWrite = 2048;
for (i = 0; i < size / 2048; i++)
UMC_CALL(m_pDataWriter->PutData((void *)paddingArray, iToWrite));
iToWrite = size % 2048;
UMC_CALL(m_pDataWriter->PutData((void *)paddingArray, iToWrite));
return UMC_OK;
} //Status MPEG2PSChunkWriter::WritePadding(Ipp32s iNOfPaddingBytes)
/*
* MPEG2TSChunkWriter
*/
MPEG2TSChunkWriter::MPEG2TSChunkWriter()
{
} //MPEG2TSChunkWriter::MPEG2TSChunkWriter()
MPEG2TSChunkWriter::~MPEG2TSChunkWriter()
{
Close();
} //MPEG2TSChunkWriter::MPEG2TSChunkWriter()
Status MPEG2TSChunkWriter::Close(void)
{
MPEG2PSChunkWriter::Close();
m_uiPID = 0;
m_bIsPCRPID = false;
m_dPCR = 0.0;
m_uiPCRFlag = 0;
m_uiStartIndicator = 0;
m_uiCounter = 0;
m_uiAdaptFieldCtrl = 0;
m_uiAdaptFieldLen = 0;
m_uiNOfTSStuffingBytes = 0;
return UMC_OK;
} //Status MPEG2TSChunkWriter::Close(void)
Status MPEG2TSChunkWriter::Init(MediaReceiverParams *pInit)
{
UMC_CALL(MPEG2PSChunkWriter::Init(pInit));
MPEG2TSChunkWriterParams *pParams = DynamicCast<MPEG2TSChunkWriterParams>(pInit);
if (!pParams)
return UMC_ERR_NULL_PTR;
m_uiPID = pParams->uiPID;
m_bIsPCRPID = pParams->bIsPCRPID;
m_uiStartIndicator = 1;
m_uiPackHeaderSize = 0;
m_uiSystemHeaderSize = 0;
m_uiSpecialHeaderSize = 0;
if (MPEG2MUX_ES_LPCM_AUDIO == m_ESType)
m_uiSpecialHeaderSize = 6;
return UMC_OK;
} //Status MPEG2TSChunkWriter::Init(MediaReceiverParams *pInit)
Status MPEG2TSChunkWriter::UnLockOutputBuffer(MPEG2MuxerSample *pData)
{
if (pData->uiSize == m_pFirstUsedSample->uiSize)
m_uiStartIndicator = 1;
return MPEG2MuxerLinearBuffer::UnLockOutputBuffer(pData);
} //Status MPEG2TSChunkWriter::UnLockOutputBuffer(MPEG2MuxerSample *pData)
Status MPEG2TSChunkWriter::PrepareChunk(void)
{
// PES section
m_uiPESPacketLength = 0;
m_uiPTSDTSFlags = 0x00;
m_uiPESHeaderDataLength = 0;
m_uiNOfStuffingBytes = 0;
m_uiPayloadSize = 0;
m_uiNOfPaddingBytes = 0;
// TS section
Ipp32u uiMaxPayloadSize = MPEG2MUX_TS_PACKET_LENGTH;
m_uiAdaptFieldCtrl = 0x01;
m_uiAdaptFieldLen = 0;
m_uiPCRFlag = 0;
m_uiNOfTSStuffingBytes = 0;
uiMaxPayloadSize -= 4; // obligatory TS packet fields
payload = *m_pFirstUsedSample;
if (m_uiStartIndicator && m_ESType != MPEG2MUX_ES_VBI_DATA)
{
if (m_bIsPCRPID)
{
m_uiPCRFlag = 1;
m_uiAdaptFieldCtrl = 0x03;
m_uiAdaptFieldLen = 7;
uiMaxPayloadSize -= 8;
if (m_dPCR < payload.dExactDTS - 0.3)
m_dPCR = payload.dExactDTS - 0.3;
else
m_dPCR += 1.0 / MPEG2MUX_SYS_CLOCK_FREQ;
}
if (payload.dPTS > 0.0)
{
m_uiPTSDTSFlags = 0x02;
m_uiPESHeaderDataLength += 5;
if (payload.dDTS > 0.0)
{
m_uiPTSDTSFlags = 0x03;
m_uiPESHeaderDataLength += 5;
}
}
m_uiPESPacketLength = payload.uiSize;
m_uiPESPacketLength += m_uiSpecialHeaderSize; // special header is needed for LPCM
m_uiPESPacketLength += m_uiPESHeaderDataLength; // PTS/DTS
m_uiPESPacketLength += 3; // PES flags and PES_header_data_length field
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -