当前位置: 首页 > news >正文

4、提取H264码流中nalu

H264的NALU提取

1、nalu单元

定义nalu的存储单元,ebsp用来存储原始的包含起始码(annexb格式)的原始码流,sodb存储去除防竞争字节后的码流,prefix是3或4字节

nalu_def.h

// nalu_def.h
#pragma once#include <cstdint>class Nalu
{
public:uint8_t* ebsp;uint32_t ebsp_len;uint8_t* sodb;uint32_t sodb_len;uint8_t prefix;uint8_t forbidden_zero_bit;	// 1 bituint8_t nal_ref_idc;		// 2 bitsuint8_t nal_unit_type;		// 5 bitsNalu();Nalu(uint8_t* stream, uint32_t len);~Nalu();void Init(uint8_t* stream, uint32_t len);int ParsePrefix();int ParseRBSP();int ParseHead();uint8_t GetNalUnitType();uint8_t* GetEBSP();uint8_t* GetRBSP();uint8_t* GetSODB();uint32_t GetLenthEBSP();uint32_t GetLenthRBSP();uint32_t GetLenthSODB();};

nalu_def.c

#include <string.h>
#include "nalu_def.h"Nalu::Nalu():ebsp(NULL),ebsp_len(0),sodb(NULL),sodb_len(0),prefix(0),forbidden_zero_bit(0),nal_ref_idc(0),nal_unit_type(0)
{
}Nalu::Nalu(uint8_t* stream, uint32_t len):Nalu()
{Init(stream, len);
}Nalu::~Nalu()
{if (ebsp){delete[] ebsp;}if (sodb){delete[] sodb;}
}void Nalu::Init(uint8_t* stream, uint32_t len)
{if (ebsp){delete[] ebsp;}ebsp = new uint8_t[len];ebsp_len = len;memcpy(ebsp, stream, len);
}int Nalu::ParsePrefix()
{prefix = 0;if (ebsp_len <= 3){if (ebsp[0] == 0 && ebsp[1] == 0 && ebsp[2] == 1)prefix = 3;}else{if (ebsp[0] == 0 && ebsp[1] == 0 && ebsp[2] == 1)prefix = 3;else if (ebsp[0] == 0 && ebsp[1] == 0 && ebsp[2] == 0 && ebsp[3] == 1)prefix = 4;}return prefix == 0 ? -1 : 0;
}int Nalu::ParseRBSP()
{if (ebsp_len < prefix)return -1;if(sodb){delete[] ebsp;}sodb = new uint8_t[ebsp_len];sodb_len = ebsp_len;uint8_t* src = ebsp + prefix;uint8_t* end = ebsp + ebsp_len;uint8_t* dest_temp = sodb;while (src < end){if (src < end - 3 &&(0x00 == src[0] && 0x00 == src[1] && 0x03 == src[2])){*dest_temp++ = 0x00;*dest_temp++ = 0x00;src += 3;continue;}*dest_temp++ = *src++;}sodb_len = dest_temp - sodb;return 0;
}int Nalu::ParseHead()
{if (ebsp_len < prefix + 1)return -1;uint8_t* head = ebsp + prefix;forbidden_zero_bit = (head[0] >> 7) & 0x1;nal_ref_idc = (head[0] >> 5) & 0x3;nal_unit_type = head[0] & 0x1f;return 0;
}uint8_t Nalu::GetNalUnitType()
{return nal_unit_type;
}uint8_t* Nalu::GetEBSP()
{return ebsp;
}uint8_t* Nalu::GetRBSP()
{return ebsp + prefix;
}uint8_t* Nalu::GetSODB()
{return sodb;
}uint32_t Nalu::GetLenthEBSP()
{return ebsp_len;
}uint32_t Nalu::GetLenthRBSP()
{return ebsp_len - prefix;
}uint32_t Nalu::GetLenthSODB()
{return sodb_len;
}

2、nalu文件读取器

每次读取BUFF_SIZE个字节数据到缓冲区中,分割成nalu单元后存入队列,队列为空时加载数据再次存入缓冲区中进行分割

nalu_file_reader.h

#pragma once#include <cstdio>
#include <queue>
#include "nalu_def.h"class NaluFileReader
{
public:NaluFileReader();~NaluFileReader();bool OpenFile(const char* path);Nalu* GetNalu();void CloseFile();private:uint8_t _status;FILE* _file;uint8_t* _buffer;uint32_t _size;std::queue<Nalu*> _nalus;const int32_t BUFF_SIZE = 128 * 1024;void ReadFromFile();int32_t FindStartCode(const uint8_t* buf, uint32_t size, uint8_t* prefix);int Splite();
};

nalu_file_reader.c

#include "nalu_file_reader.h"#pragma warning(disable:4996)NaluFileReader::NaluFileReader() :_status(0),_file(NULL),_buffer(NULL),_size(0)
{_buffer = new uint8_t[BUFF_SIZE];
}NaluFileReader::~NaluFileReader()
{delete[] _buffer;while (!_nalus.empty()){auto nal = _nalus.front();_nalus.pop();delete nal;}
}bool NaluFileReader::OpenFile(const char* path)
{fopen_s(&_file, path, "rb");_status = 0;return _file ? true : false;
}Nalu* NaluFileReader::GetNalu()
{if (!_nalus.empty()){Nalu* nal = _nalus.front();_nalus.pop();return nal;}else if (_status){return NULL;}else{ReadFromFile();Splite();if (!_nalus.empty()){Nalu* nal = _nalus.front();_nalus.pop();return nal;}}return NULL;
}void NaluFileReader::CloseFile()
{fclose(_file);_status = 0;
}void NaluFileReader::ReadFromFile()
{if (_status)return;if (_size != 0){// need seeklong offset = _size;fseek(_file, -offset, SEEK_CUR);_size = 0;}size_t size = fread(_buffer, 1, BUFF_SIZE, _file);if (size != BUFF_SIZE){_status = 1;}_size += size;
}int32_t NaluFileReader::FindStartCode(const uint8_t* buf, uint32_t size, uint8_t* prefix)
{uint32_t pos = 0;*prefix = 0;while (1){if (pos + 4 > size) return -1;if (buf[pos++] != 0x0)	continue;if (buf[pos++] != 0x0)	continue;if (buf[pos] == 0x01){*prefix = 3;break;}if (buf[pos++] != 0x0)	continue;if (buf[pos] == 0x01){*prefix = 4;break;}}return pos + 1;
}int NaluFileReader::Splite()
{uint32_t end_index = 0;uint8_t prefix = 0;uint8_t* buf_stream = _buffer;end_index = FindStartCode(buf_stream, _size, &prefix);if (prefix == 0){return -1;}while (1){uint8_t prefix_pre = prefix;end_index = FindStartCode(buf_stream + prefix, _size - prefix, &prefix);if (prefix == 0){if (_status == 1){Nalu* nalu = new Nalu(buf_stream, _size);_nalus.push(nalu);_size = 0;}break;}else{Nalu* nalu = new Nalu;nalu->Init(buf_stream, end_index - prefix + prefix_pre);_nalus.push(nalu);buf_stream += nalu->GetLenthEBSP();_size -= nalu->GetLenthEBSP();}}return 0;
}

3、使用读取器打印nalu信息

简单示例打印一下所有的nalu单元长度信息

#include <iostream>
#include "nalu_file_reader.h"
using namespace std;int main()
{NaluFileReader nal_reader;nal_reader.OpenFile("F:\\test\\source.h264");while (1){auto nal = nal_reader.GetNalu();if (!nal)break;nal->ParsePrefix();     // 解析前缀0x00000001nal->ParseRBSP();       // 去除防竞争字节nal->ParseHead();       // 解析nal头字段cout << "nal type:" << (int)nal->GetNalUnitType() << ",len:" << nal->GetLenthEBSP() << endl;delete nal;}
}

相关文章:

4、提取H264码流中nalu

H264的NALU提取 1、nalu单元 定义nalu的存储单元&#xff0c;ebsp用来存储原始的包含起始码&#xff08;annexb格式&#xff09;的原始码流&#xff0c;sodb存储去除防竞争字节后的码流&#xff0c;prefix是3或4字节 nalu_def.h // nalu_def.h #pragma once#include <cs…...

哈佛大学单细胞课程|笔记汇总 (二)

哈佛大学单细胞课程|笔记汇总 &#xff08;一&#xff09; &#xff08;二&#xff09;Single-cell RNA-seq data - raw data to count matrix 根据所用文库制备方法的不同&#xff0c;RNA序列&#xff08;也被称为reads或tag&#xff09;将从转录本&#xff08;(10X Genomic…...

java中抽象类和接口的区别

文章目录 接口和抽象类的区别一、定义的区别1、抽象类2、接口 二、使用场景的区别1、抽象类2、接口 三、使用案例1、抽象类2、接口 接口和抽象类的区别 一、定义的区别 1、抽象类 关键字&#xff1a; abstract 是模棱两可的&#xff0c;似是而非的&#xff0c;无法给出具体明…...

Spring Boot - 在Spring Boot中实现灵活的API版本控制(下)_ 封装场景启动器Starter

文章目录 Pre设计思路ApiVersion 功能特性使用示例配置示例 ProjectStarter Code自定义注解 ApiVersion配置属性类用于管理API版本自动配置基于Spring MVC的API版本控制实现WebMvcRegistrations接口&#xff0c;用于自定义WebMvc的注册逻辑扩展RequestMappingHandlerMapping的类…...

EasyCVR视频转码:T3视频平台不支持GB28181协议,应该如何实现与视频联网平台的对接与视频共享呢?

EasyCVR视频管理系统以其强大的拓展性、灵活的部署方式、高性能的视频能力和智能化的分析能力&#xff0c;为各行各业的视频监控需求提供了优秀的解决方案。 T3视频为公网HTTP-FLV或HLS格式的视频流&#xff0c;目前T3平台暂不支持国标GB28181协议&#xff0c;因此也无法直接接…...

Spring统一处理请求响应与异常

在web开发中&#xff0c;规范所有请求响应类型&#xff0c;不管是对前端数据处理&#xff0c;还是后端统一数据解析都是非常重要的。今天我们简单的方式实现如何实现这一效果 实现方式 定义响应类型 public class ResponseResult<T> {private static final String SUC…...

SqlServer公用表表达式 (CTE) WITH common_table_expression

SQL Server 中的公用表表达式&#xff08;Common Table Expressions&#xff0c;简称 CTE&#xff09;是一种临时命名的结果集&#xff0c;它在执行查询时存在&#xff0c;并且只在该查询执行期间有效。CTE 类似于一个临时的视图或者一个内嵌的查询&#xff0c;但它提供了更好的…...

常见中间件漏洞

Tomcat CVE-2017-12615 1.打开环境&#xff0c;抓包 2.切换请求头为 PUT&#xff0c;请求体添加木马&#xff0c;并在请求头添加木马文件名 1.jsp&#xff0c;后方需要以 / 分隔 3.连接 后台弱口令部署war包 1.打开环境,进入指点位置,账户密码均为 tomcat 2.在此处上传一句话…...

elasticsearch的学习(二):Java api操作elasticsearch

简介 使用Java api操作elasticsearch 创建maven项目 pom.xml文件 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…...

docker 部署 ElasticSearch;Kibana

ELasticSearch 创建网络 docker network create es-netES配合Kibana使用时需要组网&#xff0c;使两者运行在同一个网络下 命令 docker run -d \ --name es \ -e "discovery.typesingle-node" \ -v /usr/local/es/data:/usr/share/elasticsearch/data \ -v /usr/…...

k8s使用kustomize来部署应用

k8s使用kustomize来部署应用 本文主要是讲述kustomzie的基本用法。首先&#xff0c;我们说一下部署文件的目录结构。 ./ ├── base │ ├── deployment.yaml │ ├── kustomization.yaml │ └── service.yaml └── overlays└── dev├── kustomization.…...

基于开源FFmpeg和SDL2.0的音视频解码播放和存储系统的实现

目录 1、FFMPEG简介 2、SDL简介 3、视频播放器原理 4、FFMPEG多媒体编解码库 4.1、FFMPEG库 4.2、数据类型 4.3、解码 4.3.1、接口函数 4.3.2、解码流程 4.4、存储&#xff08;推送&#xff09; 4.4.1、接口函数 4.4.2、存储流程 5、SDL库介绍 5.1、数据结构 5.…...

保姆级教程,一文了解LVS

目录 一.什么是LVS tips: 二.优点&#xff08;为什么要用LVS&#xff1f;&#xff09; 三.作用 四.程序组成 五.LVS 负载均衡集群的类型 六.分布式内容 六.一.分布式存储 六.二.分布式计算 六.三.分布式常见应用 tips&#xff1a; 七.LVS 涉及相关的术语 八.LVS 负…...

【STM32】DMA数据转运(存储器到存储器)

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 DMA简介 DMA时钟使能 DMA初始化 转运起始和终止的地址 转运方向 数据宽度 传输次数 转运触发方式 转运模式 通道优先级 开启DMA通道 DMA初始化框架 更改转运次数 DMA应用实例-…...

【Android】通过代码打开输入法

获取焦点 binding.editText.requestFocus()打开键盘 val imm getSystemService(InputMethodManager::class.java) imm.showSoftInput(binding.editText, InputMethodManager.SHOW_IMPLICIT)...

爬虫集群部署:Scrapyd 框架深度解析

&#x1f575;️‍♂️ 爬虫集群部署&#xff1a;Scrapyd 框架深度解析 &#x1f6e0;️ Scrapyd 环境部署 Scrapyd 是一个开源的 Python 爬虫框架&#xff0c;专为分布式爬虫设计。它允许用户在集群中调度和管理爬虫任务&#xff0c;并提供了简洁的 API 进行控制。以下是 Scr…...

pytorch GPU操作事例

>>> import torch >>> if_cuda torch.cuda.is_available() >>> print("if_cuda",if_cuda) if_cuda True >>> gpu_count torch.cuda.device_count() >>> print("gpu_count",gpu_count) gpu_count 8...

linux常见性能监控工具

常用命令top、free 、vmsata、iostat 、sar命令 具体更详细命令可以查看手册&#xff0c;这里只是简述方便找工具 整体性能top,内存看free&#xff0c;磁盘cpu内存历史数据可以vmsata、iostat 、sar、iotop top命令 交互&#xff1a;按P按照CPU排序&#xff0c;按M按照内存…...

C++ | Leetcode C++题解之第331题验证二叉树的前序序列化

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isValidSerialization(string preorder) {int n preorder.length();int i 0;int slots 1;while (i < n) {if (slots 0) {return false;}if (preorder[i] ,) {i;} else if (preorder[i] #){slots--;i…...

【多模态处理】利用GPT逐一读取本地图片并生成描述并保存,支持崩溃后从最新进度恢复

【多模态处理】利用GPT逐一读取本地图片并生成描述&#xff0c;支持崩溃后从最新进度恢复题 代码功能&#xff1a;核心功能最后碎碎念 代码&#xff08;使用中转平台url&#xff09;&#xff1a;代码&#xff08;直接使用openai的key&#xff09; 注意 代码功能&#xff1a; 读…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...