超分服务的分量保存

分量说明

    分量的概念主要是对于一个显卡和网络传输而言,显卡可以同时进行几个线程,多个显卡可以分布式进行量的同时进行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 总是零,那么就有两个方法,1 是修改 sequence header的时间戳,2 是修改每一帧关键帧的时间戳,这里有一个问题要说明,就是整体直播出去的时候关键帧的时间戳肯定是对的,为了让文件比较正常,采取修改每一帧时间戳。

总结一下flv头部, 11 个字节头部后,如果是视频加5个字节的扩展,后面就是nalu数据,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 newtag[11];memcpy(newtag, tag, 11);uint32_t nowts = ts - v_record_timestamp;modify_timestamp(newtag, nowts);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);}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);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1552450.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Java 自定义异常及经验小结

1&#xff0e;java内置的异常类可以处理大部分异常情况。此外&#xff0c;用户还可以自定义异常&#xff0c;只需继承Exception类即可。 2&#xff0e;在程序中使用自定义异常类&#xff0c;大体可分为以下几个步骤&#xff1a; &#xff08;1&#xff09;创建自定义异常类 &…

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

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

虚拟机、ubantu不能连接网络,解决办法

虚拟机、ubantu不能连接网络&#xff0c;解决办法 物理机OS&#xff1a; [Windows10 专业版](https://so.csdn.net/so/search?qWindows10 专业版&spm1001.2101.3001.7020) 虚拟机平台&#xff1a; VMware Workstation 16 Pro 虚拟机OS&#xff1a; Ubuntu 18.04 自动配…

适合初学者的[JAVA]: 基础面试题

目录 说明 前言 String/StringBuffer/StringBuilder区别 第一点: 第二点: 总结&#xff1a; 反射机制 JVM内存结构 运行时数据区域被划分为5个主要组件&#xff1a; 方法区&#xff08;Method Area&#xff09; 堆区&#xff08;Heap Area&#xff09; 栈区&#x…

SSM整合:图书管理系统

图书管理系统 一.环境 1.数据库环境 CREATE DATABASE ssmbuild;USE ssmbuild;DROP TABLE IF EXISTS books;CREATE TABLE books (bookID INT(10) NOT NULL AUTO_INCREMENT COMMENT 书id,bookName VARCHAR(100) NOT NULL COMMENT 书名,bookCounts INT(11) NOT NULL COMMENT 数量…

宁夏众智科技OA办公系统存在SQL注入漏洞

漏洞描述 宁夏众智科技OA办公系统存在SQL注入漏洞 漏洞复现 POC POST /Account/Login?ACTIndex&CLRHome HTTP/1.1 Host: Content-Length: 45 Cache-Control: max-age0 Origin: http://39.105.48.206 Content-Type: application/x-www-form-urlencoded Upgrade-Insecur…

《论文阅读》PECER:通过动态人格提取和情境情绪推理产生同理心反应 ICASSP 2024

《论文阅读》PECER:通过动态人格提取和情境情绪推理产生同理心反应 ICASSP 2024 前言简介任务定义模型架构Cognitive-Affective Personality PerceiverMulti-source EncoderInteractive Decoder损失函数实验结果可持续发展观点前言 亲身阅读感受分享,细节画图解释,再也不用…

C++中,如何使你设计的迭代器被标准算法库所支持。

iterator&#xff08;读写迭代器&#xff09; const_iterator&#xff08;只读迭代器&#xff09; reverse_iterator&#xff08;反向读写迭代器&#xff09; const_reverse_iterator&#xff08;反向只读迭代器&#xff09; 以经常介绍的_DList类为例&#xff0c;它的迭代…

ControlGAN:Controllable Text-to-Image Generation

1 研究目的 当前的生成网络通常是不可控的&#xff0c;这意味着如果用户更改句子的某些单词&#xff0c;合成图像将与原始文本生成的合成图像显着不同&#xff1b;当给定的文本描述&#xff08;例如颜色&#xff09;发生变化时&#xff0c;鸟类的相应视觉属性被修改&#xff0c…

大数据实时数仓Hologres(四):基于Flink+Hologres搭建实时数仓

文章目录 基于FlinkHologres搭建实时数仓 一、使用示例 二、方案架构 1、架构优势 2、Hologres核心优势 三、实践场景 四、项目准备 1、创建阿里云账号AccessKey 2、准备MySQL数据源 五、构建实时数仓​编辑 1、管理元数据 2、构建ODS层 2.1、创建CDAS同步作业OD…

fpga系列 硬件(时序收敛):触发器建立时间(setuptime)

触发器 电平触发、边沿触发和脉冲触发是三种主要的触发形式。always (posedge clk or negedge rst_n) 是一个典型的 Verilog 语句&#xff0c;用于定义一个带复位的触发器。D触发器是一种基本的数字存储元件&#xff0c;主要用于数据存储和时序控制。 D触发器的建立时间和保持…

华为-IPv6与IPv4网络互通的6to4自动隧道配置实验

IPv4向IPv6的过渡不是一次性的,而是逐步地分层次地。在过渡时期,为了保证IPv4和IPv6能够共存、互通,人们发明了一些IPv4/IPv6的互通技术。 本实验以6to4技术为例,阐述如何配置IPv6过渡技术。 配置参考 R1 # sysname R1 # ipv6# interface GigabitEthernet0/0/1ip address 200…

躺平成长:微信小程序运营日记第二天

在进行属于生活的开源之后&#xff0c;自己更加感受到自己存在的渺茫&#xff0c;同时更加开始深刻领会&#xff0c;开源的重要性&#xff0c;在开源&#xff0c;开放&#xff0c;创造&#xff0c;再创新的思维模式下&#xff0c;不发布八部金刚功相关的训练视频&#xff0c;自…

Typora---进度条(1)

本系列专门介绍关于typora中用到的小玩意。&#xff08;哈哈哈哈哈哈&#xff09; 本帖子讲述关于 进度条 的事情。 在typora中通过下面的语句可以显示出一个进度条&#xff1a; ![95% done](https://markdone.org/progress//95.png)通过更改上面语句中的数字可以展示不同的进…

中英翻译神器!轻松搞定跨文化沟通

大家好&#xff01;今天咱们来聊聊那些你生活中不可或缺的翻译小助手&#xff1b;不论你是个英语小白&#xff0c;还是希望更快地了解外国文献、掌握外媒信息&#xff0c;或者是从事需要大量翻译工作的小伙伴&#xff0c;总有一款翻译工具能帮你省时省力&#xff0c;让你的生活…

Total_Expectation_Conditional_Bias_Variance_Tradeoff

Statistics with Prof. Liang Liu Topics: Total expectation, consitional expectation, conditional probability, marginal probability, 模型的 Bias, Variance 我们碰到的绝大多数都是 conditional 的probability 。比如&#xff0c;given miu, sigma square, 才能讨论…

【Java基础】Java面试基础知识QA(上)

Java面试基础知识Q&A&#xff08;上&#xff09; 面向对象编程&#xff08; OOP&#xff09; Java 是一个支持并发、基于类和面向对象的计算机编程语言。面向对象软件开发的优点&#xff1a; 代码开发模块化&#xff0c;更易维护和修改。代码复用。增强代码的可靠性和灵活性…

【AIGC】ChatGPT提示词解析:如何打造个人IP、CSDN爆款技术文案与高效教案设计

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;打造个人IP爆款文案提示词使用方法 &#x1f4af;CSDN爆款技术文案提示词使用方法 &#x1f4af;高效教案设计提示词使用方法 &#x1f4af;小结 &#x1f4af;前言 在这…

【无人机设计与技术】自抗扰控制(ADRC)的建模与仿真研究

摘要 本文针对四旋翼无人机姿态控制系统进行了基于自抗扰控制(ADRC)的建模与仿真研究。通过MATLAB/Simulink仿真平台&#xff0c;实现了无人机的姿态控制模型&#xff0c;并采用自抗扰控制器(ADRC)对无人机的姿态进行控制。本文详细介绍了自抗扰控制器的设计方法和应用&#x…

力扣题解 983

大家好&#xff0c;欢迎来到无限大的判断&#xff0c;祝大家国庆假期愉快 题目描述&#xff08;中等&#xff09; 最低票价 在一个火车旅行很受欢迎的国度&#xff0c;你提前一年计划了一些火车旅行。在接下来的一年里&#xff0c;你要旅行的日子将以一个名为 days 的数组给出…