#ifndef __DATA_FRAME_BUFFER_BASE__
#define __DATA_FRAME_BUFFER_BASE__
#include <vector>
class DataFrameBufferBase
{
public:
DataFrameBufferBase(void);
virtual ~DataFrameBufferBase(void);
public:
virtual void reset();
virtual int addStreamData(const char * data, const int data_len);
virtual int getNextFrameLen() const;
virtual int getNextFrame(char * buffer, const int buffer_size);
protected:
virtual void checkNextFrame(const int offset = 0);
virtual void resetState();
protected:
int m_data_len;
std::vector<char> m_data_buffer;
int m_next_frame_offset;
int m_next_frame_len;
bool m_is_next_frame_complete;
};
#endif
#include "DataFrameBufferBase.h"
#include <assert.h>
DataFrameBufferBase::DataFrameBufferBase(void)
: m_data_len(0)
, m_data_buffer(0)
, m_next_frame_offset(-1)
, m_next_frame_len(0)
, m_is_next_frame_complete(false)
{
}
DataFrameBufferBase::~DataFrameBufferBase(void)
{
}
void DataFrameBufferBase::reset()
{
m_data_len = 0;
m_next_frame_offset = -1;
m_next_frame_len = 0;
m_is_next_frame_complete = false;
}
int DataFrameBufferBase::addStreamData(const char * data, const int data_len)
{
try
{
if (m_data_len + data_len > (int)m_data_buffer.size())
{
m_data_buffer.resize((size_t)m_data_len + (size_t)data_len + 1, 0x00);
}
::memcpy_s((char*)&m_data_buffer[m_data_len],
m_data_buffer.size() - m_data_len, data, data_len);
const int offset = m_data_len;
m_data_len += data_len;
checkNextFrame(offset);
}
catch(...)
{
return 0;
}
return data_len;
}
int DataFrameBufferBase::getNextFrameLen() const
{
return m_is_next_frame_complete ? m_next_frame_len : 0;
}
int DataFrameBufferBase::getNextFrame(char * buffer, const int buffer_size)
{
assert(buffer && buffer_size);
if (!buffer || !buffer_size)
return 0;
if (!m_is_next_frame_complete || 0 >= m_next_frame_len)
return 0;
if (m_next_frame_len > buffer_size)
return 0;
assert(m_data_len >= m_next_frame_len);
::memcpy_s(buffer, buffer_size, (char*)&m_data_buffer[m_next_frame_offset], m_next_frame_len);
::memcpy_s((char*)&m_data_buffer[0], m_data_buffer.size(),
(char*)& m_data_buffer[(size_t)m_next_frame_offset + (size_t)m_next_frame_len],
(size_t)m_data_len - (size_t)m_next_frame_offset - (size_t)m_next_frame_len);
m_data_len -= m_next_frame_offset + m_next_frame_len;
const int frame_len = m_next_frame_len;
resetState();
checkNextFrame();
return frame_len;
}
void DataFrameBufferBase::checkNextFrame(const int offset )
{
if (offset >= m_data_len)
{
return;
}
if (m_is_next_frame_complete)
{
return;
}
m_next_frame_offset = offset;
m_next_frame_len = m_data_len - m_next_frame_offset;
m_is_next_frame_complete = true;
}
void DataFrameBufferBase::resetState()
{
m_next_frame_offset = -1;
m_next_frame_len = 0;
m_is_next_frame_complete = false;
}
#ifndef __H264_NALU_BUFFER_H__
#define __H264_NALU_BUFFER_H__
#include "DataFrameBufferBase.h"
class H264NaluBuffer : public DataFrameBufferBase
{
public:
H264NaluBuffer(void);
virtual ~H264NaluBuffer(void);
protected:
virtual void checkNextFrame(const int offset = 0);
virtual void resetState();
private:
unsigned long m_evaluation_value;
};
#endif
#include "H264NaluBuffer.h"
#include <assert.h>
const unsigned long H264_START_CODE = 0x00000001;
H264NaluBuffer::H264NaluBuffer(void)
: m_evaluation_value(0x00000000)
{
}
H264NaluBuffer::~H264NaluBuffer(void)
{
}
void H264NaluBuffer::checkNextFrame(const int offset)
{
if (offset >= m_data_len)
{
return;
}
if (m_is_next_frame_complete)
{
return;
}
for (int pos = offset; pos < m_data_len; ++pos)
{
++m_next_frame_len;
int start_code_len = 0;
m_evaluation_value = (m_evaluation_value << 8) | (unsigned char)m_data_buffer[pos];
if (H264_START_CODE == m_evaluation_value && 4 <= m_next_frame_len)
{
start_code_len = 4;
}
else if (H264_START_CODE == (m_evaluation_value & 0x00ffffff) && 3 <= m_next_frame_len)
{
start_code_len = 3;
}
else
{
continue;
}
m_next_frame_len = 0;
if (0 > m_next_frame_offset)
{
m_next_frame_offset = pos - start_code_len + 1;
continue;
}
m_next_frame_len = pos - m_next_frame_offset + 1 - start_code_len;
m_is_next_frame_complete = true;
return;
}
}
void H264NaluBuffer::resetState()
{
DataFrameBufferBase::resetState();
m_evaluation_value = 0x00000000;
}
m_video_buffer->addStreamData(pData,len);
int next_frame_len = m_video_buffer->getNextFrameLen();
while (next_frame_len)
{
next_frame_len = m_video_buffer->getNextFrameLen();
}