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

android rtsp 拉流h264 h265,解码nv12转码nv21耗时卡顿问题及ffmpeg优化

一、 背景介绍及问题概述

     项目需求需要在rk3568开发板上面,通过rtsp协议拉流的形式获取摄像头预览,然后进行人脸识别 姿态识别等后续其它操作。由于rtsp协议一般使用h.264 h265视频编码格式(也叫 AVC 和 HEVC)是不能直接用于后续处理,需要先解码后获取解码后的数据,一般解码后的数据格式为:YUV420P 或者  NV12 格式,YUV420P格式转码的可以参考libyuv库 ,这边测试设备是大华摄像头解码后格式为NV12格式,所有是以NV12转码NV21(也称之为:裸码或原始数据) ,Android 手机相机预览帧就是NV21格式。

先看NV21 输出优化后的效果 55 -58秒  4秒视频,gif限制5M  仅参考效果即可

二、 RTSP 拉流基础与编码格式简述

RTSP 协议在 Android 中的应用:
RTSP 是用于控制流媒体播放的协议,Android 中常通过 FFmpeg 或 GStreamer 实现视频流的接入与播放,适用于实时监控、远程视频等场景。

H264 与 H265 编码格式区别
H265 相比 H264 压缩效率更高,支持更高分辨率的视频传输,但解码开销更大,对性能要求更高,尤其在移动端解码时容易造成卡顿。

FFmpeg 在拉流中的角色
FFmpeg 负责解析 RTSP 协议、解封装音视频流,并将其解码为原始帧数据,为后续图像处理与播放提供底层支持。

NV12
YUV420 格式,Y 分量后紧跟交错排列的 UV 分量,常用于解码输出。

NV21
YUV420 格式,Y 分量后紧跟交错排列的 VU 分量,Android 摄像头默认输出格式。

三、RTSP 拉流

        网上常见Android拉流第三方库:VLC for Android / LibVLC     FFmpeg / FFmpegKit / FFmpeg Android Java FFmpeg  FFmpeg / FFmpegKit / FFmpeg Android Java    ExoPlayer + RTSP 扩展   GStreamer for Android
简单说一下上面几个库的情况,第一个库适用快速播放,第四个库对Android支持不太友好,所以在第二和第三个之中挑选,由于也是第一次接触rtsp协议,选择简单易于集成和官方库第三个ExoPlayer + RTSP,尝试直接通过rtsp协议获取摄像头预览数据,单从播放流畅度来看,效果还是很不错的,但是由于rtsp协议获取到是压缩后的数据格式H264.H.265,并不能满足项目需求。

下面是一个 AndroidX Media ExoPlayer demo示例参考地址:AndroidX Media ExoPlayer

四、RTSP   H.264、H.265 解码、转码和出现的问题

RTSP拉流之后H.264 还需要java层通过MediaCodec硬解码获取NV12,在转码格式NV21 后传入YuvImage 构造 Bitmap,再绘制到 Canvas 上这种形式效率很低,单纯解码NV12需要32毫秒左右,在转码NV21到Canvas显示更是需要100毫秒,这种就会在预览界面上看到明显的延迟。
然后感觉java层rtsp协议读取 转码确实效率比较低,哪怕是另开线程转码也不能解决效率问题。

只能想在C层处理了,那就有前面提到的FFmpeg库,但是这个开源库需要自己搭建linux/ubuntu环境编译出来so和源码,在集成到Android项目。必要时可以考虑自己编译,网上有很多教程~
直接找了一个比较贴近项目需求的FFmpeg解码转码nv21的项目,拉下来后运行后发现画面拉伸,卡顿掉帧严重,而且FFmpeg版本比较老旧。
https://github.com/1244975831/RtmpPlayerDemo

下面是已经编译的 FFmpeg_Android Demo地址:RtmpPlayerDemo
 

五、解决卡顿掉帧 拉伸问题

优化前FFmpeg拉流源码

extern "C"
JNIEXPORT void JNICALL
Java_com_example_rtmpplaydemo_RtmpPlayer_nativeStart(JNIEnv *env, jobject) {//开始播放stop = false;if (frameCallback == NULL) {return;}// 读取数据包int count = 0;while (!stop) {if (av_read_frame(pFormatCtx, pPacket) >= 0) {//解码int gotPicCount = 0;int decode_video2_size = avcodec_decode_video2(pCodecCtx, pAvFrame, &gotPicCount,pPacket);LOGI("decode_video2_size = %d , gotPicCount = %d", decode_video2_size, gotPicCount);LOGI("pAvFrame->linesize  %d  %d %d", pAvFrame->linesize[0], pAvFrame->linesize[1],pCodecCtx->height);if (gotPicCount != 0) {count++;sws_scale(pImgConvertCtx,(const uint8_t *const *) pAvFrame->data,pAvFrame->linesize,0,pCodecCtx->height,pFrameNv21->data,pFrameNv21->linesize);//获取数据大小 宽高等数据int dataSize = pCodecCtx->height * (pAvFrame->linesize[0] + pAvFrame->linesize[1]);LOGI("pAvFrame->linesize  %d  %d %d %d", pAvFrame->linesize[0],pAvFrame->linesize[1], pCodecCtx->height, dataSize);jbyteArray data = env->NewByteArray(dataSize);env->SetByteArrayRegion(data, 0, dataSize,reinterpret_cast<const jbyte *>(v_out_buffer));// onFrameAvailable 回调jclass clazz = env->GetObjectClass(frameCallback);jmethodID onFrameAvailableId = env->GetMethodID(clazz, "onFrameAvailable", "([B)V");env->CallVoidMethod(frameCallback, onFrameAvailableId, data);env->DeleteLocalRef(clazz);env->DeleteLocalRef(data);}}av_packet_unref(pPacket);}
}

优化后FFmpeg拉流源码

extern "C"
JNIEXPORT void JNICALL
Java_com_natives_lib_RtmpPlayer_nativeStart(JNIEnv *, jobject) {isPlaying = true;// 启动解码和渲染线程pthread_create(&decodeThread, nullptr, decodeFunc, nullptr);pthread_create(&renderThread, nullptr, renderFunc, nullptr);AVRational timeBase = formatCtx->streams[0]->time_base;while (isPlaying && av_read_frame(formatCtx, packet) >= 0) {if (packet->stream_index != 0) {av_packet_unref(packet);continue;}AVPacket *pktCopy = av_packet_alloc();if (!pktCopy) {av_packet_unref(packet);continue;}av_packet_ref(pktCopy, packet);// 使用 packet->pts 或 dts(回退方案),并转换为微秒int64_t pts = (packet->pts != AV_NOPTS_VALUE) ? packet->pts : packet->dts;if (pts == AV_NOPTS_VALUE) {// 最后兜底:使用系统时间(非推荐)pts = av_gettime();} else {pts = av_rescale_q(pts, timeBase, {1, 1000000}); // 转换为微秒单位}pktCopy->pts = pts;// 清理队列中过期帧{std::unique_lock<std::mutex> lock(queueMutex);while (!packetQueue.empty()) {AVPacket *front = packetQueue.front();int64_t frontPts = front->pts;if (av_gettime() - frontPts > MAX_QUEUE_TIME * 1000000) {av_packet_unref(front);packetQueue.pop();} else {break;}}// 判断是否可入队(关键帧优先)if ((packet->flags & AV_PKT_FLAG_KEY) || packetQueue.size() < MAX_QUEUE_SIZE) {packetQueue.push(pktCopy);queueCond.notify_one();} else {av_packet_unref(pktCopy); // 丢弃非关键帧}}av_packet_unref(packet);}// 通知线程退出isPlaying = false;queueCond.notify_all();pthread_join(decodeThread, nullptr);pthread_join(renderThread, nullptr);
}

优化前:单线程处理拉流、解码、渲染,所有处理都在单线程处理,无时间戳控制,播放帧不判断时效性,可能导致延迟累积或卡顿所有帧无差别处理,avcodec_decode_video2较旧 API效率低。


优化后:使用多线程(拉流、解码、渲染分离)提升并发效率,使用 packet->pts 转换为微秒进行帧时间控制时间,增加队列管理逻辑、清理超时帧、控制最大缓存避免内存堆积,关键帧优先入队丢弃非关键帧,保障解码连续性和渲染提高播放流畅度。


注:
这边还有一个问题,在视频流分辨率在2688*1520下,在3568开发板下只有每秒9帧(输入源每秒25帧),在1920*1080分辨率下有每秒18帧,1280*720分辨率则是  每秒25帧。
市面上主流手机则不存在这种问题,在2688*1520下也可以跑满25帧。

 

六、cmake编译问题

      一开始是在app里面直接编译so库,没有其它问题。当我把编译源码相关文件拉到本地依赖库时,就会找不到编译的so库。感觉很奇妙的问题,花了几个小时才找到原因,还是遭了熟练度的坑。
流程:新建lib库,在app里依赖lib,然后直接调用lib内的native


1.刚开始以为是so没有编译成功,但是在build里可以找到生成的so。
2 .考虑到是否生成so没有打入apk问题,所以一直找不到。但是直接依赖lib是直接合并到APK 或 AAB 中 dex和lib库的,会默认合并so库才对哇。
3.直接查看apk包内的lib库

确实有cpp生成的so库,但是怎么有多出来了x86,arm64-v8a这些库呢?在lib模块里面指定了一个armeabi-v7a架构,在app里面也没有其它编译so的cmake文件。
只能猜测是在app第三方依赖库里面,然后直接把依赖库丢到gpt排查,经过测试果然是

上面这个第三方依赖生成的 libimage_processing_util jni.so库

问题找到了,那就好解决了

方案一
在app内同步指定 ndk 为  armeabi-v7a 架构


方案二
去掉或替换生成多余的第三方依赖库


附demo连接: Demo

相关文章:

android rtsp 拉流h264 h265,解码nv12转码nv21耗时卡顿问题及ffmpeg优化

一、 背景介绍及问题概述 项目需求需要在rk3568开发板上面&#xff0c;通过rtsp协议拉流的形式获取摄像头预览&#xff0c;然后进行人脸识别 姿态识别等后续其它操作。由于rtsp协议一般使用h.264 h265视频编码格式&#xff08;也叫 AVC 和 HEVC&#xff09;是不能直接用于后续处…...

Day(21)--网络编程

网络编程 在网络通信协议下&#xff0c;不同计算机上运行的程序&#xff0c;进行的数据传输 应用场景&#xff1a;即使通信、网友对战、金融证券等等&#xff0c;不管是什么场景&#xff0c;都是计算机和计算机之间通过网络进行的数据传输 java.net 常见的软件架构 C/S&am…...

Android主流播放器功能详解

Android主流播放器功能详解 前言 本文将深入介绍Android三大主流播放框架(ijkplayer、ExoPlayer和MediaPlayer)的功能特性和实战应用,帮助你选择合适的播放框架并掌握其使用方法。 三大播放框架概述 播放框架开发方特点适用场景MediaPlayerAndroid官方简单易用,系统内置…...

牟乃夏《ArcGIS Engine地理信息系统开发教程》学习笔记2

目录 一、ArcGIS Engine概述 1、 定义 2、 核心功能 3、 与ArcObjects&#xff08;AO&#xff09;的关系 二、开发环境搭建 1、 开发工具要求 2、 关键步骤 三、 ArcGIS Engine核心组件 1、 对象模型 2、 类库分类 四、 第一个AE应用程序&#xff08;C#示例&#xf…...

语音合成(TTS)从零搭建一个完整的TTS系统-第一节-效果演示

一、概述 语音合成又叫文字转语音&#xff08;TTS-text to speech &#xff09;&#xff0c;本专题我们记录从零搭建一个完整的语音合成系统&#xff0c;包括文本前端、声学模型和声码器&#xff0c;从模型训练到系统的工程化实现&#xff0c;模型可以部署在手机等嵌入式设备上…...

文章记单词 | 第35篇(六级)

一&#xff0c;单词释义 across [əˈkrɒs] prep. 从一边到另一边&#xff1b;横过&#xff1b;在… 对面&#xff1b;遍及&#xff1b;在… 上&#xff1b;跨越&#xff1b;adv. 从一边到另一边&#xff1b;横过&#xff1b;宽&#xff1b;从… 的一边到另一边&#xff1b;在…...

MySQL Binlog 数据恢复总结

&#x1f332; 总入口&#xff1a;你想恢复什么&#xff1f; 恢复类型 ├── 表结构 表数据&#xff08;整张表被 DROP&#xff09; │ ├── Binlog 中包含 CREATE TABLE │ │ └── ✅ 直接用 mysqlbinlog 提取建表 数据语句&#xff0c;回放即可 │ └── B…...

【Linux】进程基础入门指南(下)

> &#x1f343; 本系列为Linux的内容&#xff0c;如果感兴趣&#xff0c;欢迎订阅&#x1f6a9; > &#x1f38a;个人主页:【小编的个人主页】 >小编将在这里分享学习Linux的心路历程✨和知识分享&#x1f50d; >如果本篇文章有不足&#xff0c;还请多多包涵&a…...

NoETL×大模型:Aloudata重构数据智能新范式,开启Chat BI新落地之道

在当今数据驱动的时代&#xff0c;企业对于高效、智能的数据处理与分析需求日益增长。随着大模型的兴起&#xff0c;如DeepSeek等&#xff0c;数据智能领域正经历着前所未有的变革。 Aloudata大应科技创始人&CEO周卫林表示&#xff0c;企业的核心竞争力包括人才壁垒、技术…...

算法题(126):前缀和

审题&#xff1a; 本题需要我们将题目给出的数组的数据的[l,r]范围内的数据和打印 思路&#xff1a; 方法一&#xff1a;前缀和 前缀和的思想就是预处理数据&#xff0c;通过空间换时间的方式提高代码效率 第一步&#xff1a;利用数组f将前缀和记录下来&#xff0c;f[i]表示索引…...

选择排序(简单选择排序、堆排序)

简单选择排序&#xff08;Selection Sort&#xff09; 1. 算法思想 它通过多次遍历数组&#xff0c;每次从未排序部分中选择最小&#xff08;或最大&#xff09;的元素&#xff0c;将其放到已排序部分的末尾&#xff08;或开头&#xff09;&#xff0c;直到整个数组有序。 2.…...

【JavaEE】Spring AOP的注解实现

目录 一、AOP 与 Spring AOP二、Spring AOP简单实现三、详解Spring AOP3.1 Spring AOP 核心概念3.1.1 切点&#xff08;Pointcut&#xff09;3.1.2 连接点&#xff08;Join Point&#xff09;3.1.3 通知&#xff08;Advice&#xff09;3.1.4 切面&#xff08;Aspect&#xff09…...

【天外之物】加速度与速度的单位向量的内积得到加速度在切向向量上的值

切向加速度的标量值 a T a_T aT​ 正是加速度矢量 a \mathbf{a} a 与单位切矢量 T ^ \mathbf{\hat{T}} T^ 的内积&#xff08;点积&#xff09;。 1. 数学定义 设物体的速度为 v \mathbf{v} v&#xff0c;加速度为 a \mathbf{a} a&#xff0c;单位切矢量为 T ^ \mathbf{…...

​​eBay 2025春季财报揭示跨境电商新蓝海:五大隐秘品类引爆增长密码​

核心数据速览​​ 2024年第一季度&#xff0c;eBay全球商品交易总额&#xff08;GMV&#xff09;达255亿美元&#xff0c;同比增长5%。这一增长不仅源于季节性消费回暖&#xff0c;更折射出跨境电商行业在能源转型、供应链重构及消费需求升级中的结构性变革。透过数据&#xff…...

兔子桌面tv版下载-兔子桌面tv版官方app免费下载安装

兔子桌面 TV 版是一款专为智能电视和机顶盒设计的轻量化桌面应用&#xff0c;其界面采用大图标、大字体设计&#xff0c;支持自由调整应用顺序&#xff0c;将常用的影视、游戏 App 置顶&#xff0c;还可通过主题市场下载动态背景&#xff0c;满足用户对电视界面的个性化需求。 …...

绿算轻舟系列FPGA加速卡:驱动数字化转型的核心动力【2】

工业与医疗&#xff1a;精准化的幕后推手 在工业4.0与智慧医疗领域&#xff0c;绿算轻舟FPGA加速卡通过实时信号处理与高精度控制&#xff0c;推动关键场景的技术升级。 工业自动化&#xff1a;在机器视觉质检中&#xff0c;实现亚像素级缺陷检测&#xff0c;产线检测速度大幅…...

ubuntu1804服务器开启ftp,局域网共享特定文件给匿名用户

要在 Ubuntu 18.04 上设置一个 FTP 服务器&#xff0c;满足以下要求&#xff1a; 允许匿名登录&#xff08;无需账号密码&#xff09;。指定分享特定目录下的文件。只允许只读下载。 可以使用 vsftpd&#xff08;Very Secure FTP Daemon&#xff09;来实现。以下是详细步骤&a…...

k8s中pod报错 FailedCreatePodSandBox

问题现象&#xff1a; 创建容器时出现一下情况 而且删掉控制器的时候pod还会卡住 解决&#xff1a; 将calico的pod重新删掉。其中有1个控制器pod以及3个node pod 删掉后&#xff0c;大概10来秒就重新创建完成了。 然后现在在使用kubectl apply -f 文件.yaml 就可以正常创…...

请详细说明下面训练阶段的差别: Supervised Fine-Tuning、Reward Modeling、PPO、DPO、KTO、Pre-Training

目录 &#x1f527; 一、训练阶段总体流程&#xff08;从底层到上层&#xff09; &#x1f9e0; 1. Pre-Training&#xff08;预训练&#xff09; &#x1f4cc; 目的&#xff1a; &#x1f4da; 数据&#xff1a; ⚙️ 方法&#xff1a; &#x1f4a1; 举个例子&#xf…...

Go语言入门到入土——一、安装和Hello World

Go语言入门到精通——安装和Hello World 文章目录 Go语言入门到精通——安装和Hello World下载并安装让Go跑起来为你的代码启动依赖跟踪调用外部包总结 下载并安装 下载地址&#xff1a;https://go.dev/dl/ 下载后傻瓜式安装 查看是否安装完成 go version让Go跑起来 创建一个…...

React 入门完全指南:从零开始构建现代 Web 应用

在当今快速发展的前端开发领域&#xff0c;React 凭借其高效的组件化架构和强大的生态系统&#xff0c;已成为最受欢迎的 JavaScript 库之一。根据 2023 年 Stack Overflow 开发者调查&#xff0c;React 连续七年成为最常用的 Web 框架。无论是初创公司还是科技巨头&#xff0c…...

0701表单组件-react-仿低代码平台项目

文章目录 1 react表单组件1.1 受控组件 (Controlled Components)示例代码&#xff1a; 1.2 非受控组件 (Uncontrolled Components)示例代码&#xff1a; 2 AntD表单组件实战2.1 开发搜索功能2.2 开发注册页2.3 开发登录页2.4 表单组件校验 结语 1 react表单组件 input表单组件…...

Android ViewStub显示VISIBLE与消失GONE,Kotlin(2)

Android ViewStub显示VISIBLE与消失GONE&#xff0c;Kotlin&#xff08;2&#xff09; 在 Android ViewStub显示VISIBLE与消失GONE&#xff0c;Kotlin-CSDN博客 基础上完善。 import android.os.Bundle import android.util.Log import android.view.View import android.view…...

跨站脚本(XSS) 的详细分类、对比及解决方案

以下是 跨站脚本&#xff08;XSS&#xff09; 的详细分类、对比及解决方案&#xff1a; 一、XSS的分类与详解 1. 反射型XSS&#xff08;非持久型XSS&#xff09; 定义&#xff1a;攻击载荷通过URL参数传递&#xff0c;服务器直接返回到页面中&#xff0c;需用户主动触发。 工…...

JVM:程序计数器、虚拟机栈、本地方法栈

一、程序计数器 &#xff08;1&#xff09;程序计数器介绍 作用&#xff1a;当线程执行 Java 方法时&#xff0c;程序计数器记录该线程下一条要执行的字节码指令的地址&#xff1b;当线程执行本地方法时&#xff0c;程序计数器的值为未指定&#xff08;undefined&#xff09;…...

适配器模式在Java开发中的应用

适配器模式&#xff08;Adapter Pattern&#xff09;是设计模式中的一种结构型模式&#xff0c;它允许将一个类的接口转换成客户端所期望的另一个接口。通过这种方式&#xff0c;原本因接口不兼容而无法协同工作的类能够一起工作。适配器模式在Java开发中非常常见&#xff0c;尤…...

(三)谷歌Code as Policies复现(操作记录)

目录 《复现的项目来源》 一、创建虚拟环境 二、下载原项目并修改&#xff08;非必须&#xff09; 二、可直接下载修改后的项目 三、配置环境 &#xff08;1&#xff09;安装jupyterlab以及内核 &#xff08;2&#xff09;安装ffmpeg &#xff08;3&#xff09;配置环境…...

驱动学习专栏--字符设备驱动篇--2_字符设备注册与注销

对于字符设备驱动而言&#xff0c;当驱动模块加载成功以后需要注册字符设备&#xff0c;同样&#xff0c;卸载驱动模 块的时候也需要注销掉字符设备。字符设备的注册和注销函数原型如下所示 : static inline int register_chrdev(unsigned int major, const char *name, const…...

奥创中心卸载工具Armoury Crate Uninstall Tool官网下载

为了应对用户对 Armoury Crate 占用资源大、卸载困难等问题的普遍反馈&#xff0c;ASUS 官方提供了一个专门的卸载工具&#xff0c;即 Armoury Crate Uninstall Tool(奥创中心卸载工具)。该工具的主要作用是帮助用户彻底从系统中移除 Armoury Crate 相关的所有组件&#xff0c;…...

【Linux网络】网络基础概念深度解析

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…...

【NLP 61、大模型应用 —— RAG方法】

生活打不败一个大口吃饭的人&#xff01; —— 25.4.13 一、模型幻觉问题 模型幻觉&#xff08;AI Hallucination&#xff09;是指人工智能模型&#xff08;尤其是大语言模型&#xff09;生成看似合理但实际不准确、虚构或与事实不符内容的现象。其本质是模型基于统计概…...

UV工具——小试牛刀

背景 MCP开发使用到 为什么MCP更推荐使用uv进行环境管理&#xff1f; MCP 依赖的 Python 环境可能包含多个模块&#xff0c;uv 通过 pyproject.toml 提供更高效的管理方式&#xff0c;并且可以避免 pip 的一些依赖冲突问题。此外&#xff0c;uv 的包管理速度远超 pip…...

vue3+vite 多个环境配置

同一套代码 再也不用在不同的环境里来回切换请求地址了 然后踩了一个坑 就是env的文件路径是在当前项目下 不是在views内 因为公司项目需求只有dev和pro两个环境 虽然我新增了3个 但是只在这两个里面配置了 .env是可以配置一些公共配置的 目前需求来说不需要 所以我也懒得配了。…...

《分布式软总线架构下,设备虚拟化技术的深度剖析与优化策略》

设备之间的互联互通和协同工作已成为一种趋势。分布式软总线架构作为实现这一目标的关键技术&#xff0c;为不同设备之间的通信和协作提供了基础。而设备虚拟化技术则是在分布式软总线架构下&#xff0c;进一步提升设备资源利用效率的重要手段。本文将深入探讨在分布式软总线架…...

MCP 正当时:FunctionAI MCP 开发平台来了!

作者&#xff1a;封崇 MCP&#xff1a;AI 时代的“操作系统接口” 2024 年 11 月&#xff0c;Anthropic 发布模型上下文协议&#xff08;MCP&#xff09;&#xff0c;这一开放标准迅速引发开发者社区的"协议觉醒"。其本质是通过标准化接口实现 LLM 与外部世界的双向…...

AI Agents系列之AI代理的类型

在本文中,我们将探讨不同类型的 AI 代理,包括它们的实现、实际应用、优势和局限性。从简单反射代理到多代理系统,我们将了解这些模型如何推动自动化、决策制定和智能问题解决。 文章目录 1. AI代理的类型1.1 简单反射代理1.1.1 实现**1.1.2 优势****1.1.3 局限性**1.2 基于…...

Go RabbitMQ基础教程:入门与实践指南,实战代码讲解

简介&#xff1a; RabbitMQ是一款实现高级消息队列协议&#xff08;AMQP&#xff09;的消息代理软件&#xff0c;也称为消息队列或消息中间件。它通过解耦应用程序之间的直接通信&#xff0c;支持异步数据交换&#xff0c;增强了系统的可扩展性和灵活性。RabbitMQ能够跨平台运…...

LeetCode详解之如何一步步优化到最佳解法:27. 移除元素

LeetCode详解系列的总目录&#xff08;持续更新中&#xff09;&#xff1a; LeetCode详解之如何一步步优化到最佳解法&#xff1a;前100题目录&#xff08;更新中...&#xff09;-CSDN博客 LeetCode详解系列的上一题链接&#xff1a; LeetCode详解之如何一步步优化到最佳解法…...

c++原子操作

原子操作&#xff0c;顾名思义&#xff0c;该操作不可分割。多线程环境也能保证读写数据不错乱。百度搜索了下&#xff0c;其核心概念如下&#xff1a; 1、不可分割性。原子操作是指一系列不可被CPU上下文交换的机器指令&#xff0c;操作要么完全执行&#xff0c;要么完全不执…...

在 Redis Lua 脚本中,keyCount 参数的作用是明确区分脚本参数中的 KEYS 和 ARGV,具体关系如下:

在 Redis Lua 脚本中&#xff0c;keyCount 参数的作用是**明确区分脚本参数中的 KEYS 和 ARGV**&#xff0c;具体关系如下&#xff1a; --- ### 核心作用 1. **参数分类标识** - keyCount 表示脚本中使用的 Redis KEY 的数量&#xff08;即 KEYS 数组的长度&#xff09;…...

小白如何从0学习CSS

以下是针对小白从零开始系统学习 CSS 的完整路径和实用指南&#xff0c;结合核心概念、实践技巧和项目经验&#xff0c;助你掌握网页样式的精髓&#xff1a; 1. 理解 CSS 是什么&#xff1f; 定义&#xff1a;CSS&#xff08;层叠样式表&#xff09;用于控制网页的视觉表现&…...

一文掌握RK3568开发板Android13挂载Windows共享目录

在物联网和边缘计算场景中&#xff0c;开发板与PC端的高效文件交互尤为重要。现以iTOP-RK3568开发板为例&#xff0c;详细演示Android13系统如何通过CIFS协议挂载Windows共享目录&#xff0c;实现开发板与PC的无缝文件共享。 RK3568开发板优势 iTOP-3568开发板采用瑞芯微RK3…...

UE5烘培后->为什么C磁盘满了

烘培会产生ddc 需要把路径切换一下&#xff0c;比如切换到游戏空间下。 如何修改&#xff0c;修改如下&#xff1a; 使用记事本打开BaseEngine.ini文件。 将以下内容&#xff1a; textCopy Code Path\"%ENGINEVERSIONAGNOSTICUSERDIR%DerivedDataCache\" 替换为&…...

本地搭建全网可访问的开源音乐服务器Melody结合内网穿透随时听歌

文章目录 前言1. 添加镜像源2. 本地部署Melody3. 本地访问与使用演示4. 安装内网穿透5. 配置Melody公网地址6. 配置固定公网地址 前言 嗨&#xff0c;各位音乐发烧友们&#xff01;今天我要带你们解锁一个超酷的新技能——在香橙派Zero3上搭建自己的在线音乐平台&#xff0c;并…...

深度学习Y5周:yolo.py文件解读

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、前言 文件位置&#xff1a;./models/yolo.py 此文件是实现YOLOv5网络模型的搭建文件&#xff0c;如果想改进YOLOv5&#xff0c;这个文件是必须进行修改的…...

Qt实现文件传输服务器端(图文详解+代码详细注释)

Qt实现文件传输服务器 1、前言2、服务器2.1 服务器UI界面2.2添加网络模块和头文件2.3、创建服务器对象2.4 连接有新连接的信号与槽2.5实现有新连接处理的槽函数2.6 选择文件按钮实现2.6.1 连接按钮点击的信号与槽2.6.2 添加头文件2.6.3 创建所需对象2.6.3 选择文件按钮实现 2.7…...

记录学习的第二十七天

今天效率低下&#xff0c;只做了一道力扣的每日一题。 看了题解才懂的。下面复述一遍吧。 算法就是越长越合法型滑动窗口。 核心&#xff1a; 如果此时窗口中有c个元素x&#xff0c;此时再进一个x&#xff0c;那么相同数对就增加c个。 如果此时窗口有c个元素x&#xff0c;此…...

docker 安装TDengine 时序数据库

TDengine是一个高性能、分布式a的时序数据库&#xff0c;专为物联网(loT)和大数据分析日设计。使用Docker快速地搭建 TDengine 的开发或测试环境。以下技术指南&#xff0c;帮助您通过Docker Compose 安装并运行TDengine 1.拉取镜像 (3.3.6.0版本) docker pull registry.cn-ha…...

如何更好使用呼叫中心系统和语音机器人

​要更好地使用呼叫中心系统和语音机器人&#xff0c;需要结合两者的优势&#xff0c;实现自动化、智能化、高效率的客户服务与业务运营。以下是优化策略和具体实践方法&#xff1a; 一、呼叫中心系统优化 1. 智能路由与IVR优化 ​ ​智能ACD&#xff08;自动呼叫分配&…...

C复习(主要复习)

指针和数组 指针数组是一个数组&#xff0c;数组的每个元素都是指针。它适用于需要存储多个指针的场景&#xff0c;如字符串数组。数组指针是一个指针&#xff0c;指向一个数组。它适用于需要传递整个数组给函数或处理多维数组的场景。 函数指针&#xff1a;函数指针的定义需要…...