格式化h264nalu

#ifndef __DATA_FRAME_BUFFER_BASE__
#define __DATA_FRAME_BUFFER_BASE__

#include <vector>

class DataFrameBufferBase
{
public:
    DataFrameBufferBase(void);
    virtual ~DataFrameBufferBase(void);

public:
    /**
     * reset
     *
     * 重置数据缓冲区
     * 
     * @return void
     */
    virtual void reset();

    /**
     * addStreamData
     *
     * 追加数据流
     * 
     * @param[in] const char * data      要追加的数据流
     * @param[in] const int data_len     数据长度
     * 
     * @return int 已经追加的数据长度。大于零表示追加成功,否则表示追加失败。
     * 
     */
    virtual int  addStreamData(const char * data, const int data_len);

    /**
     * getNextFrameLen
     *
     * 获取下一个完整的数据帧长度
     * 
     * @return int 数据帧长度。大于零表示获取成功,否则表示数据帧还未收集完整。
     * 
     * @note 
     *     不考虑内存访问异常等系统错误的情况下,获取失败可能为以下原因:
     *     1、已缓存的数据无法判断是否为一帧完整的数据帧;
     */
    virtual int  getNextFrameLen() const;

    /**
     * getNextFrame
     *
     * 获取一个完整的数据帧
     * 
     * @param[in,out] char * buffer        保存完整数据帧的缓冲区,由调用者提供
     * @param[in] const int buffer_size    缓冲区大小
     * 
     * @return int 获取的数据帧长度。大于零表示获取成功,否则表示获取失败。
     * 
     * @note 
     *     不考虑内存访问异常等系统错误的情况下,获取失败可能为以下原因:
     *     1、缓冲区指针_szDataBuffer为NULL或者长度_iBufferSize小于数据帧长度;
     *     2、已缓存的数据无法判断是否为一帧完整的数据帧;
     */
    virtual int  getNextFrame(char * buffer, const int buffer_size);

protected:
    /**
     * checkNextFrame
     *
     * 检测下一个完整的数据帧
     * 
     * @param[in] const int _iOffset        缓冲区中的偏移,从该字节开始检测
     */
    virtual void checkNextFrame(const int offset = 0);

	/**
	 * resetState
	 *
	 * 重置状态,但不重置缓冲区
	 */
	virtual void resetState();

protected:
    int                 m_data_len;         ///< 已缓存的数据长度
    std::vector<char>   m_data_buffer;    ///< NALU数据缓冲区

    int                 m_next_frame_offset; ///< 下一个完整数据帧的起始位置
    int                 m_next_frame_len;    ///< 下一个完整数据帧的长度
    bool                m_is_next_frame_complete;///< 下一个完整数据帧是否完整
};

#endif//__DATA_FRAME_BUFFER_BASE__

#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 /*= 0*/)
{
    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//__H264_NALU_BUFFER_H__

#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/* = 0*/)
{
    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();
//todo
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值