📄 umc_h264_au_stream.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 "umc_defs.h"
#if defined (UMC_ENABLE_H264_SPLITTER)
#include "umc_h264_au_stream.h"
#ifndef abs
#define abs(a) (((a) < 0) ? -(a) : (a))
#endif /* abs */
#include <memory>
#define TRAILING_SPAN 8
namespace UMC
{
H264_AU_Stream::H264_AU_Stream(void)
{
m_iActiveUA = 0;
m_iOutData = 0;
}
H264_AU_Stream::~H264_AU_Stream(void){}
void H264_AU_Stream::Init(Ipp32s p_iSize)
{
m_au[0].buffer.reserve(p_iSize + TRAILING_SPAN);
m_au[1].buffer.reserve(p_iSize + TRAILING_SPAN);
}
Status H264_AU_Stream::PutData(MediaData & p_rawAnnexB)
{
if(p_rawAnnexB.GetDataSize() < 1){
return UMC_ERR_NOT_ENOUGH_DATA;
}
Status status = UMC_ERR_NOT_ENOUGH_DATA;
H264NALUOctet octet;
octet.ReadOctet((Ipp8u *)p_rawAnnexB.GetDataPointer());
#ifdef AU_TRACING
printf("--nalu type=%d", (Ipp32s)octet.Type);
#endif // AU_TRACING
switch(octet.Type){
case H264_NAL_SLICE_NON_IDR:
case H264_NAL_SLICE_A:
case H264_NAL_SLICE_B:
case H264_NAL_SLICE_C:
case H264_NAL_SLICE_IDR:
status = OnSlice(p_rawAnnexB);
break;
case H264_NAL_SET_SEQ:
status = OnSequenceSet(p_rawAnnexB);
break;
case H264_NAL_SET_PIC:
status = OnPictureSet(p_rawAnnexB);
break;
case H264_NAL_AU_DEL:
m_lastSlice.is_valid = false;
status = StartAU();
AppendAU(p_rawAnnexB);
break;
case H264_NAL_END_SEQ:
m_lastSlice.is_valid = false;
AppendAU(p_rawAnnexB);
status = StartAU();
break;
case H264_NAL_END_STM:
m_lastSlice.is_valid = false;
AppendAU(p_rawAnnexB);
status = StartAU();
break;
default:
// H264_NAL_FIL_DATA
// H264_NAL_SLICE_SEI
// H264_NAL_SET_SEQ_EXT
// H264_NAL_SLICE_NI_05
AppendAU(p_rawAnnexB);
status = UMC_ERR_NOT_ENOUGH_DATA;
break;
}
#ifdef AU_TRACING
printf("\n");
#endif // AU_TRACING
return status;
}
Status H264_AU_Stream::OnSlice(MediaData & p_dataNALU)
{
H264SliceHeaderParse slice;
MediaData localData = p_dataNALU;
slice.octet.ReadOctet((Ipp8u *)localData.GetDataPointer());
localData.MoveDataPointer(1);
H264_SyntaxReader syntaxReader(localData);
H264SequenceSetParse * pSeqSet = 0;
if( UMC_OK != Read_slice_header(slice, syntaxReader, pSeqSet)){
return UMC_ERR_FAILED;
}
if (m_lastSlice.is_valid && !IsPictureSame(slice)){
Status status = StartAU();
AppendAU(p_dataNALU);
SetLastAttrs(*pSeqSet, slice);
m_lastSlice = slice;
m_lastSlice.is_valid = true;
return status;
}
SetLastAttrs(*pSeqSet, slice);
m_lastSlice = slice;
m_lastSlice.is_valid = true;
AppendAU(p_dataNALU);
return UMC_ERR_NOT_ENOUGH_DATA;
}
Status H264_AU_Stream::OnPictureSet(MediaData & p_dataNALU)
{
if( p_dataNALU.GetDataSize() == 0){
return UMC_ERR_NOT_ENOUGH_DATA;
}
H264PictureSetParse pic;
MediaData localData = p_dataNALU;
pic.octet.ReadOctet((Ipp8u *)localData.GetDataPointer());
localData.MoveDataPointer(1);
Ipp8u * pData = (Ipp8u *)localData.GetDataPointer();
pic.buffer.insert(pic.buffer.end(), pData, pData + localData.GetDataSize());
H264_SyntaxReader syntaxReader(localData);
if( UMC_OK != Read_pic_parameter_set_rbsp(pic, syntaxReader)){
return UMC_ERR_FAILED;
}
m_mapPic[pic.pic_parameter_set_id] = pic;
Status status = UMC_ERR_NOT_ENOUGH_DATA;
if (m_lastSlice.is_valid)
{
status = StartAU();
}
AppendAU(p_dataNALU);
m_lastSlice.is_valid = false;
return status;
}
Status H264_AU_Stream::OnSequenceSet(MediaData & p_dataNALU)
{
if( p_dataNALU.GetDataSize() == 0){
return UMC_ERR_NOT_ENOUGH_DATA;
}
H264SequenceSetParse seq;
MediaData localData = p_dataNALU;
H264_SyntaxReader syntaxReader(localData);
seq.octet.ReadOctet((Ipp8u *)localData.GetDataPointer());
localData.MoveDataPointer(1);
Ipp8u * pData = (Ipp8u *)localData.GetDataPointer();
seq.buffer.insert(seq.buffer.end(), pData, pData + localData.GetDataSize());
if( UMC_OK != Read_seq_parameter_set_rbsp(seq, syntaxReader)){
return UMC_ERR_FAILED;
}
m_mapSeq[seq.seq_parameter_set_id] = seq;
Status status = UMC_ERR_NOT_ENOUGH_DATA;
if (m_lastSlice.is_valid)
{
status = StartAU();
}
AppendAU(p_dataNALU);
m_lastSlice.is_valid = false;
return status;
}
void H264_AU_Stream::AppendAU(MediaData & p_dataNALU)
{
static const Ipp8s s_stopSeq[] = {0x00, 0x00, 0x00, 0x01};
Ipp8u * pData = (Ipp8u*)p_dataNALU.GetDataPointer();
m_au[m_iActiveUA].buffer.insert(m_au[m_iActiveUA].buffer.end(), (Ipp8u*)s_stopSeq, (Ipp8u*)s_stopSeq + sizeof(s_stopSeq));
m_au[m_iActiveUA].buffer.insert(m_au[m_iActiveUA].buffer.end(), pData, pData + p_dataNALU.GetDataSize());
}
Status H264_AU_Stream::StartAU()
{
if( m_au[m_iActiveUA].buffer.empty()){
return UMC_ERR_NOT_ENOUGH_DATA;
}
// Swapping buffers
m_iActiveUA = ( m_iActiveUA + 1) % 2;
m_au[m_iActiveUA].buffer.clear();
return UMC_OK;
}
void H264_AU_Stream::Swap()
{
m_iActiveUA = ( m_iActiveUA + 1) % 2;
}
Status H264_AU_Stream::LockOutputData(MediaData & o_dataAU)
{
Ipp32s iNum = ( m_iActiveUA + 1) % 2;
// Ensuring that there is also a span in the end of NALU
Ipp32s iTrail = (Ipp32s)(m_au[iNum].buffer.capacity() - m_au[iNum].buffer.size());
if( iTrail < TRAILING_SPAN ){
m_au[iNum].buffer.reserve(m_au[iNum].buffer.size() + TRAILING_SPAN);
}
if (m_au[iNum].buffer.size() == 0)
{
o_dataAU.SetBufferPointer(0, 0);
o_dataAU.SetDataSize(0);
return UMC_OK;
}
o_dataAU.SetBufferPointer(&(m_au[iNum].buffer[0]), m_au[iNum].buffer.size());
o_dataAU.SetDataSize(m_au[iNum].buffer.size());
m_iOutData += (Ipp32s)m_au[iNum].buffer.size();
return UMC_OK;
}
Status H264_AU_Stream::UnLockOutputData(MediaData & /*o_dataAU*/)
{
return UMC_OK;
}
#define GO_OR_QUIT_SIMPLE( op ) if( UMC_OK != op ) return UMC_ERR_FAILED;
#define GO_OR_QUIT( op ) if( UMC_OK != p_reader.op ) return UMC_ERR_FAILED;
Status H264_AU_Stream::Read_seq_parameter_set_rbsp(H264SequenceSetParse & p_SequenceSet, H264_SyntaxReader & p_reader)
{
Ipp32u iValue = 0;
Ipp32s siValue = 0;
Ipp32u profile_idc = 0;
GO_OR_QUIT( ReadU(8, profile_idc) );
GO_OR_QUIT( ReadU(1, iValue) );
GO_OR_QUIT( ReadU(1, iValue) );
GO_OR_QUIT( ReadU(1, iValue) );
GO_OR_QUIT( ReadU(1, iValue) );
GO_OR_QUIT( ReadU(4, iValue) );
GO_OR_QUIT( ReadU(8, iValue) );
GO_OR_QUIT( ReadUE(p_SequenceSet.seq_parameter_set_id) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -