代码是从上一篇博客[1]中摘取出来的,只提取nalu的在内存中的偏移量和长度(均刨除起始码的长度)。
h264_parser.h

#pragma once
#include <stdio.h>
#include <stdint.h>
namespace media{
struct H264NALU{
const uint8_t *data;
size_t size;
size_t start_code_size;
};
class H264Parser{
public:enum Result {kOk,kInvalidStream,      // error in streamkUnsupportedStream,  // stream not supported by the parserkEOStream,           // end of stream};
void SetStream(const uint8_t* stream, size_t stream_size);
H264Parser::Result AdvanceToNextNALU(H264NALU* nalu);
bool LocateNALU(size_t* nalu_size, size_t* start_code_size);
static bool FindStartCode(const uint8_t* data,size_t data_size,size_t* offset,size_t* start_code_size);
private:const uint8_t *stream_{nullptr};size_t bytes_left_;
};
}

h264_parser.cc

#include <memory.h>
#include "h264_parser.h"
#include "logging.h"
#define NOTREACHED() CHECK(false)
#define DVLOG(x) VLOG(x)
namespace media{
static inline bool IsStartCode(const uint8_t* data) {return data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01;
}
void H264Parser::SetStream(const uint8_t* stream, size_t stream_size){stream_=stream;bytes_left_=stream_size;
}
H264Parser::Result H264Parser::AdvanceToNextNALU(H264NALU* nalu){size_t start_code_size;size_t nalu_size_with_start_code;if (!LocateNALU(&nalu_size_with_start_code, &start_code_size)) {DVLOG(4) << "Could not find next NALU, bytes left in stream: "<< bytes_left_;stream_ = nullptr;bytes_left_ = 0;return kEOStream;}nalu->data = stream_ + start_code_size;nalu->size = nalu_size_with_start_code - start_code_size;nalu->start_code_size=start_code_size;DVLOG(4) << "NALU found: size=" << nalu_size_with_start_code;// Move parser state to after this NALU, so next time AdvanceToNextNALU// is called, we will effectively be skipping it;// other parsing functions will use the position saved// in bit reader for parsing, so we don't have to remember it here.stream_ += nalu_size_with_start_code;bytes_left_ -= nalu_size_with_start_code;return kOk;
}
bool H264Parser::LocateNALU(size_t* nalu_size, size_t* start_code_size){// Find the start code of next NALU.size_t nalu_start_off = 0;size_t annexb_start_code_size = 0;if (!FindStartCode(stream_, bytes_left_,&nalu_start_off, &annexb_start_code_size)) {DVLOG(4) << "Could not find start code, end of stream?";return false;}// Move the stream to the beginning of the NALU (pointing at the start code).stream_ += nalu_start_off;bytes_left_ -= nalu_start_off;const uint8_t* nalu_data = stream_ + annexb_start_code_size;off_t max_nalu_data_size = bytes_left_ - annexb_start_code_size;if (max_nalu_data_size <= 0) {DVLOG(3) << "End of stream";return false;}// Find the start code of next NALU;// if successful, |nalu_size_without_start_code| is the number of bytes from// after previous start code to before this one;// if next start code is not found, it is still a valid NALU since there// are some bytes left after the first start code: all the remaining bytes// belong to the current NALU.size_t next_start_code_size = 0;size_t nalu_size_without_start_code = 0;if (!FindStartCode(nalu_data, max_nalu_data_size,&nalu_size_without_start_code, &next_start_code_size)) {nalu_size_without_start_code = max_nalu_data_size;}*nalu_size = nalu_size_without_start_code + annexb_start_code_size;*start_code_size = annexb_start_code_size;return true;
}
bool H264Parser::FindStartCode(const uint8_t* data,size_t data_size,size_t* offset,size_t* start_code_size){size_t bytes_left = data_size;while (bytes_left >= 3) {// The start code is "\0\0\1", ones are more unusual than zeroes, so let's// search for it first.const uint8_t* tmp =reinterpret_cast<const uint8_t*>(memchr(data + 2, 1, bytes_left - 2));if (!tmp) {data += bytes_left - 2;bytes_left = 2;break;}tmp -= 2;bytes_left -= tmp - data;data = tmp;if (IsStartCode(data)) {// Found three-byte start code, set pointer at its beginning.*offset = data_size - bytes_left;*start_code_size = 3;// If there is a zero byte before this start code,// then it's actually a four-byte start code, so backtrack one byte.if (*offset > 0 && *(data - 1) == 0x00) {--(*offset);++(*start_code_size);}return true;}++data;--bytes_left;}// End of data: offset is pointing to the first byte that was not considered// as a possible start of a start code.// Note: there is no security issue when receiving a negative |data_size|// since in this case, |bytes_left| is equal to |data_size| and thus// |*offset| is equal to 0 (valid offset).*offset = data_size - bytes_left;*start_code_size = 0;return false;
}
}

test_main.cc

#include <iostream>
#include "h264_parser.h"
using namespace std;
using namespace media;
int main()
{char fake_h264[]={0x00,0x00,0x00,0x01,0x12,0x12,0x12,0x00,0x00,0x01,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12};uint8_t *data=(uint8_t*)fake_h264;int data_size=sizeof(fake_h264);H264Parser parser;parser.SetStream(data,data_size);H264NALU nalu;while(true){if(parser.AdvanceToNextNALU(&nalu)==H264Parser::kOk){std::cout<<"size "<<nalu.size<<" start code len "<<nalu.start_code_size<<std::endl;}else{break;}}return 0;
}

 里面有一些调试信息,需要log模块,可以去这里下载[2]。不想下载就注释掉了那些DVLOG这类代码。
Reference:
[1]h264 raw stream parser-读取H264裸流信息
[2]log

H264 raw stream获取nalu的长度信息相关推荐

  1. FFMPEG之H264获取NALU并且解析其RBSP类型03

    FFMPEG之H264获取NALU并且解析其RBSP类型03 前言 FFMPEG之H264理论篇. 理论的就不多讲了,可以参考上面那篇文章,下面将给出两种版本,一种是我自己的,用C++方法实现,另一种 ...

  2. H264实时编码及NALU,RTP传输(续)

    对h.264压缩视频码流中i帧的提取(firstime) 2010-06-30 09:15 转载自 fandy586  http://hi.baidu.com/sdlyfdy 最终编辑 fandy58 ...

  3. H264实时编码及NALU,RTP传输(ZZ)

    rfc3984 Standards Track [Page 2] RFC 3984 RTP Payload Format for H.264 Video February 2005 1. 按照RFC3 ...

  4. H264文件解析出nalu数据,送给ffmpeg解码,opencv显示

    本博客主要是H264的视频码流有ffmpeg 解码后,有opencv先,这里贴出全部代码,你只需自己建个工程,配置一下ffmpeg库和opencv3.0库就好了.(这里采用自己打开h264文件,解析出 ...

  5. python获取原图GPS位置信息,轻松得到你的活动轨迹

    点击上方"AI搞事情"关注我们 一.图像EXIF信息 介绍 EXIF(Exchangeable image file format,可交换图像文件格式)是专门为数码相机的照片设定的 ...

  6. python获取输入框内容长度_python3 tkinter 获取输入字符串长度

    python 3  获取输入字符长度 #-*- coding:utf-8 -*- from tkinter import * from tkinter import messagebox def ge ...

  7. Go的反射是如何获取结构体成员信息的?

    前言 哈喽,大家好,今天这篇文章的目的主要是解答一位读者的疑问,涉及知识点是反射和结构体内存布局.我们先看一下读者的问题: img 我们通过两个问题来解决他的疑惑: 结构体在内存中是如何存储的 反射获 ...

  8. linux系统获取光盘信息api,C++ 通过WIN32 API 获取逻辑磁盘详细信息的几种方法

    今天我们主要介绍的是几个常用的api函数,通过它我们可以获取用户磁盘的相关信息 其主要函数原型说明如下: 1.获取系统中逻辑驱动器的数量 The GetLogicalDrives function r ...

  9. C/C++通过WMI和系统API函数获取获取系统硬件配置信息(转)

    前段时间由于项目需要,要求做一个服务器的实时性能监控(CPU.内存.网络利用率等)和读取服务器的硬件配置参数的接口供项目组使用,就是一个类似于鲁大师之类的东东吧... 当然第一想法肯定是利用Windo ...

最新文章

  1. CPU与内存的那些事
  2. cocos2d-x 3.2 listview scorllview 等容器在小米华为等部分手机显示泛白解决
  3. ArcGIS几种数据格式2
  4. Boost:不受约束的bimap双图的测试程序
  5. 2013年长沙网络赛G题
  6. const修饰指针和引用的用法【转贴】
  7. Nginx PageSpeed模块配置和使用
  8. 支付系统详解:清结算系统
  9. 手工雕刻图纸_鬼斧神工--木雕手工雕刻技法
  10. python—马氏距离
  11. 使用Python打印爱心图案
  12. PDCAOODA循环
  13. 人脸识别技术的简单认识(含原理)
  14. 软考系统分析师倒计时第0天
  15. IBM Cloud 2015 - Invoice - 06 账期 Credit term, payment days, Net 30 days terms
  16. 【zephyr】apds9660 接近(Proximity)传感器 驱动模型实现方式(一)
  17. Proxmark3教程3:IC卡三文件数据比对工具,轻松找出不同和相同
  18. python龙格库塔_龙格库塔积分法
  19. 【顶】辞职也需要辞得帅,辞得大家都开心,多为将来考虑,辞职不要急,本是好事要办好
  20. Java复习之模板方法设计模式

热门文章

  1. 建设数据中心机房主要看这几点,否则被定为劣质机房!!!
  2. SendKeys.SendWait()用法
  3. html5 canvas绘制图形,html5 Canvas绘制图形入门详解
  4. 布法罗计算机专业怎么样,2019上海软科世界一流学科排名计算机科学与工程专业排名纽约州立大学布法罗分校排名第76-100...
  5. 软件工程师资格认证,你合格吗?
  6. 搭建YApi接口管理平台+IDEA插件easyYapi一键生成接口动态发布到YApi平台
  7. 计算机网络期末复习知识点
  8. linux-查看cpu核数
  9. Kafka 消息中间件
  10. winpe 能否修复服务器系统,教你如何使用winpe来修复系统