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

超分服务的分量保存

分量说明

    分量的概念主要是对于显卡解码,编码和网络传输而言,显卡可以同时进行几个线程,多个显卡可以分布式计算,对分量进行AI识别,比如我们有cuda的显卡,cuda的核心量可以分给不同的分片视频,第一步先将视频减小,第二部分割视频。对于小视频片而言,不同的智能盒子也可以接收网络传输来进行接收数据,进行并行识别服务。这就是我说的分量服务的概念。

采样

    在超分服务中,上采样和下采样是两个重要的操作,分别用于增加和减少图像的分辨率。我们在下采样后存储文件和传输,可以显著减少存储的量,同时减少网络的传输量,而接收端收到以后再进行上采样放大,同时进行AI 分析

超分服务说明

    实现超分服务,将实时视频能够缩小并且传输和保存,同时需要将文件分成片,同时保证每个文件的最后一帧和下一个文件的第一帧相同,还需要解决两个问题
文件切片是问了能够分布式传输出去,同时本地如果有多个显卡,可以同时进行文件的搜索,比如再多个文件中同时启动AI服务,搜索同一个人脸。

    采用rtsp,rtmp服务器接收,rtmp服务器在接收文件时保存为flv文件,为了不污染任何代码,不采用开源的各种服务,使用c++20 去写rtmp和rtsp服务器,这个花了两天时间,协议没啥问题,结果反而时卡在了文件保存上面,下面具体说几个问题,主要体现在时间戳上面。

    以下为flv文件保存的要素,首先时flv 头部,在头部中查找0x17 和 0x00 0x01
*/
//0x17 key 00(AVCPacketType ) 00 表示 是AVCDecoderConfigurationRecord
//0x17 key 01(AVCPacketType ) 01 表示 raw data ->nalu
//0x27 not key 01 01 表示 raw data ->nalu

//FLV head 9 bytes
//4 bytes previous tag
//tag data —>11 bytes head -> 5 bytes video head -> nalu data
//4 bytes previous tag
//tag data
熟悉flv文件格式的人一看就懂,无需多言。

1 关键帧问题
2 时间戳问题

关键帧问题

    必须保证一个文件第一帧一定为关键帧,所以在分割视频的时候必须能够拿到关键帧的时候才能分割,为了能够保证未丢失文件,上一个文件的最后一帧为下一个文件的第一帧,否则会有很多依靠关键帧解码的p帧b帧无法解码,变成比较难受的绿色,也有可能为绿加黑。

分量保存的时间戳

看下图,
在这里插入图片描述

    显然除了第一个文件是正确的,但除了第一个分量文件,其他文件第一帧的时间戳是不对的,这是因为AVC sequence header 总是零,vlc播放的时候计算的时间就不正确了,那么就有两个方法:

1 是修改 sequence header的时间戳,
2 是修改每一帧时间戳,

    这里有一个问题要说明,就是整体直播出去的时候关键帧的时间戳肯定是对的,为了让文件比较正常,采取修改每一帧时间戳。

    总结一下flv头部, 11 个字节头部后,如果是视频,加5个字节的扩展,后面就是nalu数据,如果是音频,加2个字节的扩展,视频5个字节里面第一个就是判别是关键帧和非关键帧的紧要,这里简单一点先用0x17 0x27来判别,注意实际上不是这样,只有h264才是这个值,先找定时间戳,假定我们从协议里面获取的时间戳是正确的,看下面的代码


//11 个字节头部
static void pack_tag_header(uint8_t *buf, uint8_t type, uint32_t data_size, uint32_t timestamp) {//8 audio ; 9 video ; 18 script//8 is the most if (type == 8 || type == 9 || type == 18){*buf++ = type;//one bytesbuf = write_be_ui24(buf, data_size); //three bytesbuf = write_be_ui24(buf, timestamp & 0xffffff);//three bytes*buf++ = timestamp >> 24; //one bytesbuf = write_be_ui24(buf, 0); //three bytes}
}//flv header length is 11
//type 8:audio,  9:video,  18:script meta
static void pack_tag(uint8_t* header, ptr_s_memory mem, uint8_t type, uint32_t timestamp) {pack_tag_header(header, type, (uint32_t)mem->v_len, timestamp);uint8_t* p = mem->v_data_r + mem->v_len;//last write the frame length ,it must include the header lengthwrite_be_ui32(p, FLV_TAG_HEADER_LEN + (uint32_t)mem->v_len);
}

1 2 3 4 5 6 7 8 9 10 11
09 xx xx xx 00 7c 79 00 00 00 00
11 个flv字节头部里面有四个字节包含了时间戳,第5个字节到第8,也是我们自己的代码写入的,我们要做的就是重写时间戳,但是不能修改传入的tag数组,这是外面传输出去要用的

0 和 1 之间无缝衔接,同时每个文件的时间长度和时间戳都保证正确
在这里插入图片描述

在这里插入图片描述
开头和结尾衔接
在这里插入图片描述
相邻两个文件开头和结尾为同一帧

code

主要就是需要重新改写时间戳,直接看代码

#pragma once
#include <stdint.h>
#include <stdio.h>
#include <string>#include "c_hub.h"
#include "util_flv_pack.h"
//flv 文件读写
class c_flv_writer
{FILE* v_fp = NULL;int64_t v_num = 0;uint32_t v_hash = 0;std::string v_deviceurl;uint32_t v_record_timestamp = 0;
public:ptr_s_memory v_head_video = nullptr;ptr_s_memory v_head_audio = nullptr;int v_frame_count = 2000;int v_frame_record = 0;int v_inited = 0;protected:std::string GetFileName(){//判断v_deviceurl是否"/"结尾std::string name = v_deviceurl + std::to_string(v_hash);name +="_" + std::to_string(v_num);name += ".flv";v_num++;return name;}
public:void initStart(std::string deviceurl, uint32_t hash, ptr_s_memory v, ptr_s_memory a){v_hash = hash;v_deviceurl = deviceurl;v_head_video = v;v_head_audio = a;v_inited = 1;}static void modify_timestamp(uint8_t* buf, uint32_t timestamp) {buf = buf + 4; // write_be_ui24(buf, data_size); //three bytesbuf = write_be_ui24(buf, timestamp & 0xffffff);//three bytes*buf++ = timestamp >> 24; //one bytes}int writeStart(uint32_t ts){if (v_fp == NULL){v_frame_record = 0;std::string name = GetFileName();v_fp = fopen(name.c_str(), "wb+");if (v_fp == NULL)return -1;fwrite(FLV_HEADER_BUF_13, 13, 1, v_fp);//video headif (v_head_video != nullptr){uint8_t* data_v = v_head_video->v_data_h; //flvhub->v_cache_hv->v_data_h;size_t len_v = v_head_video->v_len + 11 + 4;fwrite(data_v, len_v, 1, v_fp);}//audio headif (v_head_audio != nullptr){uint8_t* data_a = v_head_audio->v_data_h;size_t len_a = v_head_audio->v_len + 11 + 4;fwrite(data_a, len_a, 1, v_fp);}}v_record_timestamp = ts;return 0;}void writeData(uint8_t* tag, int taglen, uint8_t* data, size_t len, uint32_t ts){if (v_fp == NULL)writeStart(ts);//遇到关键帧才能重新开始if (v_fp != NULL /*&& v_frame_record < v_frame_count*/){uint8_t a = *data;uint8_t b = *(data + 1);if (v_frame_record > v_frame_count && ((a == 0x17) && (b == 0x01))){//需要重复最后一帧放开uint8_t newtag[11];memcpy(newtag, tag, 11);uint32_t nowts = ts - v_record_timestamp;modify_timestamp(newtag, nowts);fwrite(newtag, taglen, 1, v_fp);fwrite(data, len, 1, v_fp);fclose(v_fp);v_fp = NULL;std::cout << "close the file now" << std::endl;writeStart(ts);}uint8_t newtag[11];memcpy(newtag, tag, 11);uint32_t nowts = ts - v_record_timestamp;modify_timestamp(newtag, nowts);fwrite(newtag, taglen, 1, v_fp);fwrite(data, len, 1, v_fp);v_frame_record++;std::cout << "write the number " << v_frame_record << std::endl;}}
};

调用

调用的时候放在音视频接收以后并且下采样结束的地方

if (flvhub->v_flv_w.v_inited == 0)
{flvhub->v_flv_w.initStart("./", hash, flvhub->v_cache_hv, flvhub->v_cache_ha);flvhub->v_flv_w.v_inited = 1;
}
flvhub->v_flv_w.writeData(tag,taglen, mem->v_data_r ,len, mem->v_ts);

其他编码

    由于rtmp协议已经加入enhanced 扩展,rtmp/flv已经有统一支持H265的国际版本,我后面会修改rtmp server,加入对h265的支持,那么这边存储flv 也必须进行修改,适应编码

相关文章:

超分服务的分量保存

分量说明 分量的概念主要是对于显卡解码&#xff0c;编码和网络传输而言&#xff0c;显卡可以同时进行几个线程&#xff0c;多个显卡可以分布式计算&#xff0c;对分量进行AI识别&#xff0c;比如我们有cuda的显卡&#xff0c;cuda的核心量可以分给不同的分片视频&#xff0c;第…...

Windows11系统下SkyWalking环境搭建教程

目录 前言SkyWalking简介SkyWalking下载Agent监控实现启动配置SkyWalking启动Java应用程序启动Elasticsearch安装总结 前言 本文为博主在项目环境搭建时记录的SkyWalking安装流程&#xff0c;希望对大家能够有所帮助&#xff0c;不足之处欢迎批评指正&#x1f91d;&#x1f91…...

前端BOM常用操作

BOM操作常用命令详解及代码案例 BOM&#xff08;Browser Object Model&#xff09;是浏览器对象模型&#xff0c;是浏览器提供的JavaScript操作浏览器的API。BOM提供了与网页无关的浏览器的功能对象&#xff0c;虽然没有正式的标准&#xff0c;但现代浏览器已经几乎实现了Java…...

【Go】-viper库的使用

目录 viper简介 viper使用 通过viper.Set设置值 读取配置文件说明 读取配置文件 读取多个配置文件 读取配置项的值 读取命令行的值 io.Reader中读取值 写配置文件 WriteConfig() 和 SafeWriteConfig() 区别: viper简介 配置管理解析库&#xff0c;是由大神 Steve Fr…...

JavaWeb酒店管理系统(详细版)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

C++ | 定长内存池 | 对象池

文章目录 C | 定长内存池 | 对象池一、内存池的引入二、代码中的内存池实现 - ObjectPool类&#xff08;一&#xff09;整体结构&#xff08;二&#xff09;内存分配 - New函数&#xff08;三&#xff09;内存回收 - Delete函数 三、内存池在TreeNode示例中的性能测试演示四、脱…...

python画图|自制渐变柱状图

在前述学习过程中&#xff0c;我们已经通过官网学习了如何绘制渐变的柱状图及其背景。 掌握一门技能的最佳检验方式就是通过实战&#xff0c;因此&#xff0c;本文尝试做一些渐变设计。 前述学习记录可查看链接&#xff1a; Python画图|渐变背景-CSDN博客 【1】柱状图渐变 …...

基于RPA+BERT的文档辅助“悦读”系统 | OPENAIGC开发者大赛高校组AI创作力奖

在第二届拯救者杯OPENAIGC开发者大赛中&#xff0c;涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到&#xff0c;我们特意开设了优秀作品报道专栏&#xff0c;旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者&#xff0c;希望能带给…...

K8S部署流程

一、war打包镜像(survey,analytics,trac系统) 代码打包成war准备tomcat的server.xml文件&#xff0c;修改connector中8080端口为项目的端口 修改前&#xff1a; <Connector port"8080" protocol"HTTP/1.1"connectionTimeout"20000"redirect…...

DevExpress WinForms中文教程:Data Grid - 如何添加或删除行?

本教程介绍DevExpress WinForm的Data Grid控件UI元素和API&#xff0c;它们使您和最终用户能够添加或删除数据行。您将首选学习如何启用内置的数据导航器&#xff0c;然后学习如何使用Microsoft Outlook启发的New Item行添加新记录。最后教程将向您展示基本的API&#xff0c;它…...

u盘格式化后数据能恢复吗?2024年Top4恢复神器来帮忙

在这个电脑和手机满天飞的时代&#xff0c;U盘是我们用来存东西和传文件的得力助手&#xff0c;特别重要。但是&#xff0c;有时候U盘可能会不小心被格式化了&#xff0c;里面的重要文件就不见了。那么&#xff0c;U盘格式化后的数据还能恢复吗&#xff1f;当然可以。今天会告诉…...

深度学习·Argparse

Argparse 命令行选项、参数和子命令解析器 ArgumentParser 命令行传参数->解析参数->获得对应参数 初始化&#xff1a;parser argparse.ArgumentParser(descriptionxxx)添加命令行参数&#xff1a; parser.add_argument("--training_filepath", typestr, he…...

制造企业为何需要PLM系统?PLM系统解决方案对制造业重要性分析

制造企业为何需要PLM系统&#xff1f;PLM系统解决方案对制造业重要性分析 新华社9月23日消息&#xff0c;据全国组织机构统一社会信用代码数据服务中心统计&#xff0c;我国制造业企业总量突破600万家。数据显示&#xff0c;2024年1至8月&#xff0c;我国制造业企业数量呈现稳…...

http协议中的header详细讲解

http协议中的header详细讲解 HTTP 协议和 TCP/IP 协议族内的其他众多的协议相同&#xff0c;用于客户端和服务器之间的通信。 请求访问文本或图像等资源的一端称为客户端&#xff0c;而提供资源响应的一端称为服务器端。 HTTP 协议规定&#xff0c;请求从客户端发出&#xf…...

探索后量子安全:基于格加密技术的未来密码学展望

在信息技术日新月异的今天&#xff0c;量子计算作为下一代计算技术的代表&#xff0c;正逐步从理论走向实践。量子计算的出现对现有的加密体系构成了严重威胁&#xff0c;尤其是基于大数分解和离散对数难题的传统密码学&#xff08;如RSA和Diffie-Hellman协议&#xff09;。为了…...

WPF之UI进阶--完整了解wpf的控件和布局容器及应用

前面三篇有关WPF的基础介绍&#xff0c;分别介绍了wpf与winform的异同&#xff0c;wpf的事件生成和使用以及数据绑定。但我们还缺乏一副好的“皮囊”&#xff0c;所以从这篇开始我们来开始学习wpf的UI相关的内容&#xff0c;首当其冲的就是布局容器。 其实我们知道&#xff0c;…...

unity一键注释日志和反注释日志

开发背景&#xff1a;游戏中日志也是很大的开销&#xff0c;虽然有些日志不打印但是毕竟有字符串的开销&#xff0c;甚至有字符串拼接的开销&#xff0c;有些还有装箱和拆箱的开销&#xff0c;比如Debug.Log(1) 这种 因此需要注释掉&#xff0c;当然还需要提供反注释的功能&am…...

VBA数据库解决方案第十五讲:Recordset集合中单个数据的精确处理

《VBA数据库解决方案》教程&#xff08;版权10090845&#xff09;是我推出的第二套教程&#xff0c;目前已经是第二版修订了。这套教程定位于中级&#xff0c;是学完字典后的另一个专题讲解。数据库是数据处理的利器&#xff0c;教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…...

甄选范文“论软件需求管理”,软考高级论文,系统架构设计师论文

论文真题 软件需求管理是一个对系统需求变更了解和控制的过程。需求管理过程与需求开发过程相互关联,初始需求导出的同时就要形成需求管理规划,一旦启动了软件开发过程,需求管理活动就紧密相伴。 需求管理过程中主要包含变更控制、版本控制、需求跟踪和需求状态跟踪等4项活…...

Android Studio Dolphin 中Gradle下载慢的解决方法

我用的版本Android Studio Dolphin | 2021.3.1 Patch 1 1.Gradle自身的版本下载慢 解决办法&#xff1a;修改gradle\wrapper\gradle-wrapper.properties中的distributionUrl 将https\://services.gradle.org/distributions为https\://mirrors.cloud.tencent.com/gradle dis…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...