协议-ACLLite-ffmpeg

news2025/3/13 2:51:07

是什么?

  • FFmpeg是一个开源的多媒体处理工具包,它集成了多种功能,包括音视频的录制、转换和流式传输处理。
  • FFmpeg由一系列的库和工具组成,其中最核心的是libavcodec和libavformat库。
    • libavcodec是一个领先的音频/视频编解码器库,支持多种音频和视频格式的编码和解码操作。
    • libavformat库则用于处理各种不同的多媒体容器格式,如MP4、AVI、MKV等。它能够解析提取其中的音频和视频流,以便进行进一步的处理

为什么?

为什么有GStreamer的前提下,还要使用FFmpeg?

  • 在某些情况下,GStreamer 会比 FFmpeg 更适合特定的需求
    • FFmpeg 是一个功能强大的单体框架,主要专注于媒体的编解码、转码和流处理
    • GStreamer适合构建复杂的媒体处理管道,如视频会议、实时流媒体处理和视频编辑
功能FFmpegGStreamer
核心架构Monolithic模块化,基于管道线
易用性使用 CLI 更容易完成简单的媒体任务需要更多设置,但管道灵活
编解码器支持广泛的编解码器支持,几乎涵盖所有编解码器功能强大,但通常需要额外的插件
使用案例媒体转换、流媒体转码、实时流媒体、媒体应用
模块化模块化程度低,围绕特定命令构建模块化程度高,可定制组件
插件系统有限的插件系统,主要集中于编解码器广泛的插件系统,用于自定义处理
实时处理可以,但不直观专为实时流媒体和处理而设计
跨平台是(Linux、Windows、macOS 等)是(Linux、Windows、macOS 等)
复杂性对于简单的任务来说更简单对于复杂的自定义媒体工作流程来说更好
许可LGPL 或 GPL(取决于配置)LGPL
开发者社区庞大、活跃、被广泛采用活跃,但规模小于 FFmpeg

怎么做?

  • 官网Download FFmpeg,选择安装包Windows builds from gyan.dev
  • 找到release bulids部分,选择 ffmpeg-release-essentials.zip
  • 解压文件并检查目录结构
  • 配置环境变量 并检验 ffmpeg -version

核心本质

本质就四个名词

  • Demuxer:拆解多媒体文件,提取音频和视频流。
  • Decoder:将编码后的音频或视频数据解码为原始数据。
  • Encoder:将原始音频或视频数据编码为特定格式。
  • Muxer:将音频和视频流重新封装为多媒体文件。

![[Pasted image 20240704090349.png]]

  • Demuxer:拆解多媒体文件,提取音频和视频流。

![[Pasted image 20250206212037.png]]

  • 解码器接收音频、视频、 或字幕基本流,并将它们解码为原始帧( 视频的像素,音频的 PCM)

![[Pasted image 20250206212045.png]]

  • 编码器接收原始音频、视频或字幕帧并进行编码 它们被编码为数据包

![[Pasted image 20250206212106.png]]

  • Muxer:将音频和视频流重新封装为多媒体文件

![[Pasted image 20250206212115.png]]


大局观总览

  • 库总览

![[Pasted image 20240704161618.png]]

真正有用三库

  • libavcodec库包含多种音频、视频和字幕流的解码器和编码器,以及多种位流过滤器。
  • libavformat库用于将音频、视频和字幕流多路复用和解复用
  • libavfilter库用于处理音频/视频数据,例如进行视频的缩放、裁剪、旋转,音频的混音、音量调整

辅助类型库

  • libavutil包含了一些安全的、可移植的字符串函数、随机数生成器、数据结构、额外的数学函数、密码学和与多媒体相关的功能(如枚举像素和采样格式)

  • libswscale是一个用于图像缩放和颜色空间以及像素格式转换的高效库。

  • libswresample是一个高度优化的音频重采样、重矩阵和采样格式转换库。

  • libavdevice是一个通用的框架,用于抓取和渲染许多常见的多媒体输入/输出设备。

  • 命令总览

![[Pasted image 20240704161704.png]]

  • 功能总览

![[Pasted image 20240704161807.png]]

转换格式流程图

  • 输入文件拆解多媒体文件,提取音频和视频流 ;将编码后的音频或视频数据解码为原始数据;将原始音频或视频数据编码为特定格式;将音频和视频流重新封装为多媒体文件;

![[Pasted image 20250206170140.png]]

ffmpeg -i INPUT.mkv -map 0:v -map 0:a -c:v libx264 -c:a copy OUTPUT.mp4

简单的 filtergraph

  • 将编码后的音频或视频数据解码为原始数据;并对原始数据进行处理;将原始音频或视频数据编码为特定格式;

![[Pasted image 20250206170159.png]]

复杂 filtergraph 它可能有多个输入,多个输出,可能是不同类型的(音频或 video)

  • 第二个输入的帧将叠加在来自第一个输入的帧上。第三个 input 被重新缩放,然后被复制到两个相同的流中。其中之一 它们叠加在组合的前两个输入上,显示为 FilterGraph 的第一个输出。另一个是 filterGraph 的第二个输出

![[Pasted image 20250206172117.png]]


基本命令

ffmpeg -y -c:a libfdk_aac -c:v libx264 -i input.mp4 -c:v libvpx-vp9 -c:a libvorbis output.webm 
  • -y:不经过确认,输出时直接覆盖同名文件
  • -c:指定编码器
    • -c copy:直接复制,不经过重新编码(这样比较快)
    • -c:v:指定视频编码器
    • -c:a:指定音频编码器
  • -i:指定输入文件
  • -an:去除音频流
  • -vn: 去除视频流
  • -preset:指定输出的视频质量,会影响文件的生成速度,有以下几个可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow。
  • -f:fmt指定格式(音频或视频格式)
  • -t:duration 记录时长为t
  • -acodec: 音频选项, 一般后面加copy表示拷贝
  • -vcodec:视频选项,一般后面加copy表示拷贝
  • h264: 表示输出的是h264的视频裸流
  • mp4: 表示输出的是mp4的视频
  • mpegts: 表示ts视频流
ffmpeg -r 1 -i racing.mp4 -c:v libx264 -profile:v high -level:v 5.1 -c:a copy -r 60 racingoutput.mp4
  • -r 强制输入文件的帧速率(仅对 Raw 格式有效)为 1 fps,并且 输出文件的帧速率为 24 fps
  • -profile:v -level 设置H.264画质级别
ffmpeg -i input.avi output.mp4
  • 通过重新编码媒体流,将输入媒体文件转换为其他格式
ffmpeg -i input.avi -b:v 64k -bufsize 64k output.mp4
  • -b:v 64k 设置输出文件的视频码率为 64 kbit/s

Streamcopy 流复制 -map 的使用

![[Pasted image 20250207162306.png]]

ffmpeg -i INPUT.mkv -map 0:1 -c copy OUTPUT.mp4

![[Pasted image 20250207162209.png]]

ffmpeg -i INPUT0.mkv -i INPUT1.aac -map 0:0 -map 1:0 -c copy OUTPUT.mp4

![[Pasted image 20250207162215.png]]

ffmpeg -i INPUT.mkv -map 0:0 -c copy OUTPUT0.mp4 -map 0:1 -c copy OUTPUT1.mp4

推拉流RTSP命令

UDP推流

ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream
  • -re 为以流的方式读取

TCP推流

ffmpeg -re -i input.mp4 -c copy -rtsp_transport tcp -f rtsp rtsp://127.0.0.1:8554/stream

循环推流

ffmpeg -re -stream_loop -1 -i input.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream
  • -stream_loop 为循环读取视频源的次数,-1为无限循环

拉流

ffplay rtsp://127.0.0.1:8554/stream

FFmpeg拉流保存成视频

ffmpeg -stimeout 30000000 -i rtsp://127.0.0.1:8554/stream -c copy output.mp4
  • -stimeout 30000000 为等待RTSP 流连接的时间,单位为us微秒,等待 30 秒如果连接失败则退出

过滤器(fliter)命令

  • 过滤器就是实现某一种视频功能的工具,FFmpeg自带开发了很多种filter用于实现不同的功能

  • 源视频宽度扩大两倍

ffmpeg -i jidu.mp4 -t 10 -vf pad=2 * iw output.mp4
  • 源视频水平翻转
ffmpeg -i jidu.mp4 -t 10 -vf hflip output2.mp4
  • 水平翻转视频覆盖output.mp4
ffmpeg -i output.mp4 -i output2.mp4 -filter_complex overlay=w compare.mp4

核心结构体

  • 围绕解协议,解封装,解码
  • libavcodec 的核心是 AVCodec 和 AVCodecContext

AVIOContext,URLProtocol,URLContext,AVFormatContext

解协议(http,rtsp,rtmp,mms)

  • AVIOContext,URLProtocol,URLContext
    • AVIOContext是FFMPEG管理输入输出数据的结构体,内含指针指向URLContext结构体
    • URLContext结构体中包含结构体URLProtocol
      • URLContext存储音频/视频使用的协议的类型以及状态
      • URLProtocol存储音频/视频使用的协议(rtp,rtmp,file等)操作函数接口

解封装(flv,avi,rmvb,mp4)

  • AVFormatContext存储音频/视频封装包含的数据和信息
  • AVInputFormat表示音频/视频输入格式

![[Pasted image 20250207121801.png]]

AVCodec AVCodecContext AVStream

架构类似于昇腾的device conent steam

![[Pasted image 20250207000401.png]]

解码(h264,mpeg2,aac,mp3)

  • AVCodecContext,存储该音视频流使用解码器的相关数据(所需的上下文环境)
  • AVCodec (该音视频的解码器)(h264 mpeg2 AAC mp3)

![[Pasted image 20250207091506.png]]

  • 实际使用时有可能会有多个 AVCodecContext 关联同一个 AVCodec 的情况。尤其是我们解码音频的时候。

音频文件时 5.1声道的 AVCodec AVCodecContext AVStream关系

  • 通常会对应 3 个 AVStream

    • 左右声道在一个 AVStream
    • 环绕声在一个 AVStream
    • 最后低音在另一个AVStream
  • 3 个AVStream的编码可能是相同的

  • 解码这个音频文件时就应该建立 3 个 AVCodecContext ,分别对应三个 AVStream。然后只需要有 1 个 AVCodec 。每个 AVCodecContext 都利用这一个 AVCodec 来解码。


AVPacket - AVFrame

  • 所谓解码就是把一个 AVPacket 中的数据解成 AVFrame
    • AVPacket是 编码压缩之后的数据
    • AVFrame 是原始的,没有编码、没有压缩的数据 对视频来说是YUV RGB,对音频来说是PCM

![[Pasted image 20250207114701.png]]

I帧 P帧 B帧 的影响

  • 我们会遇到前几个 AVPacket 解不出数据。

    • 到了某个 AVPacket ,可以连续解出多个 AVFrame 来的情况。
    • 这时这多个 AVFrame 就包括前面积压的 AVPacket 里的数据
  • avcodec_send_packet() 调用一次将一个 packet 推给Codec,

  • avcodec_receive_frame() 调用一次或多次来获得 frame


华为昇腾ACLLite库封装ffmpeg案例

什么是华为昇腾ACLLite库?

  • ACLLite库是对CANN提供的ACL接口进行的高阶封装,简化用户调用流程,为用户提供一组简易的公共接口。当前主要针对边缘场景设计

![[Pasted image 20250207153015.png]]

ACLLite\Media\CameraRead.cpp

void CameraRead::DecodeFrameThread(void* decoderSelf)

对照核心结构体 理解 具体解码流程

void CameraRead::DecodeFrameThread(void* decoderSelf)
{
    CameraRead* thisPtr = (CameraRead*)decoderSelf;
    int videoStreamIndex = -1;
    for (int i = 0; i < thisPtr->formatContext_->nb_streams; ++i) {
        if (thisPtr->formatContext_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
            break;
        }
    }
    if (videoStreamIndex == -1) {
        LOG_PRINT("[ERROR] usb camera %s index is -1", thisPtr->streamName_.c_str());
        thisPtr->isOpened_ = false;
        return;
    }
    AVCodecParameters* codecParameters = thisPtr->formatContext_->streams[videoStreamIndex]->codecpar;
    AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id);
    if (codec == nullptr) {
        LOG_PRINT("[ERROR] Could not find ffmpeg decoder.");
        thisPtr->isOpened_ = false;
        return;
    }
    AVCodecContext* codecContext = avcodec_alloc_context3(codec);
    if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) {
        LOG_PRINT("[ERROR] Could not create decoder context.");
        thisPtr->isOpened_ = false;
        return;
    }
    if (avcodec_open2(codecContext, codec, nullptr) < 0) {
        LOG_PRINT("[ERROR] Could not open decoder context.");
        thisPtr->isOpened_ = false;
        return;
    }
    AVFrame* frame = av_frame_alloc();
    AVPacket packet;

    while (av_read_frame(thisPtr->formatContext_, &packet) >= 0 && !thisPtr->isStop_) {
        if (packet.stream_index == videoStreamIndex) {
            int response = avcodec_send_packet(codecContext, &packet);
            if (response < 0 || response == AVERROR(EAGAIN)) {
                continue;
            }
            while (response >= 0) {
                response = avcodec_receive_frame(codecContext, frame);
                if (response == AVERROR(EAGAIN)) {
                    break;
                } else if (response < 0) {
                    LOG_PRINT("[ERROR] Receive false frame from ffmpeg.");
                    thisPtr->isOpened_ = false;
                    return;
                }
                bool ret = thisPtr->SendFrame(packet.data, packet.size);
                if (!ret) {
                    thisPtr->isOpened_ = false;
                    LOG_PRINT("[ERROR] Send single frame from ffmpeg failed.");
                    return;
                }
            }
        }
        av_packet_unref(&packet);
    }
    av_frame_free(&frame);
    avcodec_close(codecContext);
    avformat_close_input(&thisPtr->formatContext_);
    thisPtr->isOpened_ = false;
    return;
}
  • avcodec_find_decoder 根据编解码参数的编解码器ID查找对应的编解码器
  • avcodec_alloc_context3 分配编解码器上下文
  • avcodec_open2 打开编解码器上下文
  • av_frame_alloc 分配帧结构体
  • av_read_frame 从输入文件中读取一个数据包(AVPacket),并将其存储到 packet 中
  • avcodec_send_packet 将一个数据包发送到解码器
  • avcodec_receive_frame 从解码器中接收一个解码后的帧
  • SendFrame 用于将解码后的帧发送到其他地方(例如显示或进一步处理)
  • av_frame_free avcodec_close avformat_close_input 最后释放资源

ACLLite\DVPPLite\src\VideoRead.cpp

void FFmpegDecoder::Decode(FrameProcessCallBack callback,void *callbackParam)

对照核心结构体 理解 具体解码流程

void FFmpegDecoder::Decode(FrameProcessCallBack callback,
                           void *callbackParam)
{
    LOG_PRINT("[INFO] Start ffmpeg decode video %s ...", streamName_.c_str());
    avformat_network_init(); // init network

    AVFormatContext* avFormatContext = avformat_alloc_context();

    // check open video result
    if (!OpenVideo(avFormatContext)) {
        return;
    }

    int videoIndex = GetVideoIndex(avFormatContext);
    if (videoIndex == kInvalidVideoIndex) { // check video index is valid
        LOG_PRINT("[ERROR] Rtsp %s index is -1", streamName_.c_str());
        return;
    }

    AVBSFContext* bsfCtx = nullptr;
    // check initialize video parameters result
    if (!InitVideoParams(videoIndex, avFormatContext, bsfCtx)) {
        return;
    }

    LOG_PRINT("[INFO] Start decode frame of video %s ...", streamName_.c_str());

    AVPacket avPacket;
    int processOk = true;
    // loop to get every frame from video stream
    while ((av_read_frame(avFormatContext, &avPacket) == 0) && processOk && !isStop_) {
        if (avPacket.stream_index == videoIndex) { // check current stream is video
          // send video packet to ffmpeg
            if (av_bsf_send_packet(bsfCtx, &avPacket)) {
                LOG_PRINT("[ERROR] Fail to call av_bsf_send_packet, channel id:%s",
                    streamName_.c_str());
            }

            // receive single frame from ffmpeg
            while ((av_bsf_receive_packet(bsfCtx, &avPacket) == 0) && !isStop_) {
                int ret = callback(callbackParam, avPacket.data, avPacket.size);
                if (ret != 0) {
                    processOk = false;
                    break;
                }
            }
        }
        av_packet_unref(&avPacket);
    }

    av_bsf_free(&bsfCtx); // free AVBSFContext pointer
    avformat_close_input(&avFormatContext); // close input video

    isFinished_ = true;
    LOG_PRINT("[INFO] Ffmpeg decoder %s finished", streamName_.c_str());
}

  • av_read_frame 从输入文件中读取一个数据包(AVPacket)
  • av_bsf_send_packet 数据包发送到解码器
  • av_bsf_receive_packet 从解码器中接收解码后的帧
  • callback 进一步处理
  • av_packet_unref av_bsf_free avformat_close_input 最后释放资源

根据对应类型初始化过滤器

void FFmpegDecoder::InitVideoStreamFilter(const AVBitStreamFilter*& videoFilter)
{
    if (videoType_ == AV_CODEC_ID_H264) { // check video type is h264
        videoFilter = av_bsf_get_by_name("h264_mp4toannexb"); // 目的是从Avcodec库中获取一个名为"h264_mp4toannexb"的视频过滤器。
    } else { // the video type is h265
        videoFilter = av_bsf_get_by_name("hevc_mp4toannexb");
    }
}

附录-h264基础概念

H264

![[Pasted image 20250206183105.png]]

为什么诞生

  • ⼀段分辨率为 1920 * 1080,每个像素点为 RGB 占⽤3 个字节,帧率是 25 的视频,对于传输带宽的要求是

  • 换成 bps 则意味着视频每秒带宽为 1186.523Mbps,这样的速率对于⽹络存储是不可接受的

  • H264 采⽤了 16 * 16 的分块⼤⼩对,视频帧图像进⾏相似⽐较和压缩编码

![[Pasted image 20250206184128.png]]

  • 一帧图片经过 H.264 编码器之后,就被编码为一个或多个片(slice),而装载着这些片(slice)的载体,就是 NALU 了

![[Pasted image 20250206184103.png]]

H264有两种封装

  • H.264码流分Annex-B和mp4两种格式。

  • ⼀种是 annexb 模式,传统模式

  • ⼀种是 mp4 模式,⼀般 mp4 mkv 都是 mp4 模式

  • 很多解码器只⽀持 annexb 这种模式,因此需要将 mp4 做转换:

  • 在 ffmpeg 中⽤h264_mp4toannexb_filter 可以做转换

ffmpeg -i INPUT.mp4 -codec copy -bsf:v h264_mp4toannexb OUTPUT.ts
  • -bsf:v h264_mp4toannexb:指定视频过滤器为h264_mp4toannexb,这个过滤器的作用是将H.264流从长度前缀模式转换为开始代码前缀模式。

H.264有四种画质级别,分别是baseline, extended, main, high:

  • Baseline Profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC;
  • Extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;(用的少)
  • Main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced), 也支持CAVLC 和CABAC 的支持;
  • High profile:高级画质。在main Profile 的基础上增加了8x8内部预测、自定义量化、 无损视频编码和更多的YUV 格式;
ffmpeg -i input.mp4 -profile:v baseline -level 3.0 output.mp4
ffmpeg -i input.mp4 -profile:v main -level 4.2 output.mp4
ffmpeg -i input.mp4 -profile:v high -level 5.1 output.mp4

GOP - I帧 P帧 B帧

  • 编码器将多张图像进行编码后生产成一段一段的 GOP ( Group of Pictures )

  • 解码器在播放时则是读取一段一段的 GOP 进行解码后读取画面再渲染显示

  • GOP ( Group of Pictures) 是一组连续的画面,由一张 I 帧和数张 B / P 帧组成

  • I 帧是内部编码帧(也称为关键帧),P帧是前向预测帧(前向参考帧),B 帧是双向内插帧(双向参考帧)

简单地讲,I 帧是一个完整的画面,而 P 帧和 B 帧记录的是相对于 I 帧的变化。

![[Pasted image 20250206174901.png]]

  • I帧表示关键帧,你可以理解为经过适度地压缩这一帧画面的完整保留
  • P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别

![[Pasted image 20250206173959.png]]

  • B帧记录的是本帧与前后帧的差别
  • B帧传送的是它与前面的I帧或P帧和后面的P帧之间的预测误差及运动矢量

![[Pasted image 20250206174047.png]]

有了 I帧,P帧, 为什么需要B帧

  • 因为B帧记录的是前后帧的差别,比P帧能节约更多的空间

IDR 图像(立即刷新图像

  • 一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像
  • H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,
    • 将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列
  • 如果前一个序列出现重大错误,在这里可以获得重新同步的机会
    • IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码

![[Pasted image 20250206180211.png]]

DTS PTS

为什么会有PTS和DTS的概念

  • P帧需要参考前面的I帧或P帧才可以生成一张完整的图片

  • B帧则需要参考前面I帧或P帧及其后面的一个P帧才可以生成一张完整的图片

  • 这样就带来了一个问题:在视频流中,先到来的 B 帧无法立即解码,需要等待它依赖的后面的 I、P 帧先解码完成,这样一来播放时间与解码时间不一致了,顺序打乱了,那这些帧该如何播放呢?

PTS和DTS的概念

  • DTS(Decoding Time Stamp):即解码时间戳
    • 这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。
  • PTS(Presentation Time Stamp):即显示时间戳
    • 这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。

[Pasted image 20250206175718.png]]![在这里插入图片描述

文档链接说明

  • 官方文档
    Documentation (ffmpeg.org)

  • 基本概念
    I帧、P帧、B帧、GOP、IDR 和PTS, DTS之间的关系 - 夜行过客 - 博客园

  • 参考文档
    音视频八股文 – h264 AnnexB_音视频开发面试八股文-CSDN博客

  • 参考文档
    FFmpeg基础知识之-—— H264编码profile & level控制_ffmpeg level-CSDN博客

  • 参考文档
    基于 FFMPEG 的视频解码(libavcodec ,致敬雷霄骅)-CSDN博客

  • 参考文档
    ffmpeg 结构体之间的关系_packet解码frame之间的对应-CSDN博客
    FFMPEG结构体分析:AVIOContext-CSDN博客

  • 参考文档
    ffmpeg 常用命令汇总_ffmpeg命令大全-CSDN博客
    基于FFmpeg进行rtsp推流及拉流(详细教程)_ffmpeg rtsp推流-CSDN博客

  • 华为昇腾ACLLite仓库
    Ascend/ACLLite

  • 华为昇腾对照概念
    AscendCL架构及基本概念-AscendCL应用开发概述-AscendCL应用开发(C&C++)-应用开发-开发指南-CANN社区版8.0.0.alpha003开发文档-昇腾社区

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

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

相关文章

树和二叉树_7

树和二叉树_7 一、leetcode-102二、题解1.引库2.代码 一、leetcode-102 二叉树的层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 样例输入&#xff1a;root [3,9,20,null,nu…

Rocky Linux9安装Zabbix7.0(精简版)

Linux 系统版本 Rocky Linux release 9.3 (Blue Onyx) 注意&#xff1a;zabbix 7以上版本不支持CentOS 7系统&#xff0c;需要CentOS 8以上&#xff0c; 本教程支持CentOS9及Rocky Linux 9 在Rocky Linux release 9.3测试通过 Linux环境准备 关闭防火墙和selinux #关闭防…

网络分析工具—WireShark的安装及使用

Wireshark 是一个广泛使用的网络协议分析工具&#xff0c;常被网络管理员、开发人员和安全专家用来捕获和分析网络数据包。它支持多种网络协议&#xff0c;能够帮助用户深入理解网络流量、诊断网络问题以及进行安全分析。 Wireshark 的主要功能 数据包捕获与分析&#xff1a; …

C++开发(软件开发)常见面试题

目录 1、C里指针和数组的区别 2、C中空指针请使用nullptr不要使用NULL 3、http/https区别和头部结构&#xff1f; 4、有了mac地址为什么还要ip地址&#xff1f;ip地址的作用 5、有了路由器为什么还要交换机&#xff1f; 6、面向对象三大特性 7、友元函数 8、大端小端 …

WEB攻防-文件下载文件读取文件删除目录遍历目录穿越

目录 一、文件下载漏洞 1.1 文件下载案例&#xff08;黑盒角度&#xff09; 1.2 文件读取案例&#xff08;黑盒角度&#xff09; 二、文件删除 三、目录遍历与目录穿越 四、审计分析-文件下载漏洞-XHCMS 五、审计分析-文件读取漏洞-MetInfo-函数搜索 六、审计分析-…

MySQL数据库(七)SQL 优化

一 插入数据 采用方法 1 批量插入 2 手动提交事务 3 主键顺序插入 4* 使用load插入指令数据 二 主键优化 1 数据组织方式 在InnoDB存储引擎中&#xff0c;表中的数据都是根据主键顺序组织存放的&#xff0c;这种存储方式的表称为索引组织表 2 页分裂 页可以为空也可…

使用EVE-NG实现单臂路由

一、基础知识 1.三层vlan vlan在三层环境中通常用作网关vlan配上ip网关内部接口ip 2.vlan创建步骤 创建vlan将接口划分到不同的vlan给vlan配置ip地址 二、项目案例 1、项目拓扑 2、项目实现 PC1配置 配置PC1IP地址为192.168.1.10/24网关地址为192.168.1.1 ip 192.168.1…

本地部署DeepSeek(Mac版本,带图形化操作界面)

一、下载安装&#xff1a;Ollama 官网下载&#xff1a;Download Ollama on macOS 二、安装Ollama 1、直接解压zip压缩包&#xff0c;解压出来就是应用程序 2、直接将Ollama拖到应用程序中即可 3、启动终端命令验证 # 输入 ollama 代表已经安装成功。 4、下载模型 点击模型…

Linux LED 实验

一、Linux 下 LED 灯驱动原理 其实跟裸机实验很相似&#xff0c;只不过要编写符合 Linux 的驱动框架。 1. 地址映射 MMU全称 Memory Manage Unit&#xff0c;即内存存储单元。 MMU主要功能为&#xff1a; 1&#xff09;完成虚拟空间到物理空间的映射&#xff1b; 2&#x…

【Redis】redis 存储的列表如何分页和检索

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

2025.2.6 数模AI智能体大更新,更专业的比赛辅导,同提示词效果优于gpt-o1/o3mini、deepseek-r1满血

本次更新重新梳理了回复逻辑规则&#xff0c;无任何工作流&#xff0c;一共3.2k字细节描述。具体效果可以看视频&#xff0c;同时也比对了gpt-o1、gpt-o3mini、deepseek-r1-67BI&#xff0c;从数学建模题目解答上来看&#xff0c;目前我的数模AI智能体具有明显优势。 AI智能体优…

cursor指令工具

Cursor 工具使用指南与实例 工具概览 Cursor 提供了一系列强大的工具来帮助开发者提高工作效率。本指南将通过具体实例来展示这些工具的使用方法。 1. 目录文件操作 1.1 查看目录内容 (list_dir) 使用 list_dir 命令可以查看指定目录下的文件结构: 示例: list_dir log…

【玩转全栈】----Django模板语法、请求与响应

目录 一、引言 二、模板语法 三、传参 1、视图函数到模板文件 2、模板文件到视图函数 四、引入静态文件 五、请求与响应 ?1、请求 2、响应 六、综合小案例 1、源码展示 2、注意事项以及部分解释 3、展示 一、引言 像之前那个页面&#xff0c;太过简陋&#xff0c;而且一个完整…

C++,设计模式,【单例模式】

文章目录 一、模式定义与核心价值二、模式结构解析三、关键实现技术演进1. 基础版(非线程安全)2. 线程安全版(双重检查锁)3. 现代C++实现(C++11起)四、实战案例:全局日志管理器五、模式优缺点深度分析✅ 核心优势⚠️ 潜在缺陷六、典型应用场景七、高级实现技巧1. 模板化…

基于yolov11的阿尔兹海默症严重程度检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv11的阿尔兹海默症严重程度检测系统是一种创新的医疗辅助工具&#xff0c;旨在通过先进的计算机视觉技术提高阿尔兹海默症的早期诊断和病情监测效率。阿尔兹海默症是一种渐进性的神经退行性疾病&#xff0c;通常表现为认知障碍、记忆丧失和语言障碍等症状…

设计模式-生产者消费者模型

阻塞队列&#xff1a; 在介绍生产消费者模型之前&#xff0c;我们先认识一下阻塞队列。 阻塞队列是一种支持阻塞操作的队列&#xff0c;常用于生产者消费者模型&#xff0c;它提供了线程安全的队列操作&#xff0c;并且在队列为空或满时&#xff0c;能够阻塞等待&#xff0c;…

RabbitMQ介绍以及基本使用

文章目录 一、什么是消息队列&#xff1f; 二、消息队列的作用&#xff08;优点&#xff09; 1、解耦 2、流量削峰 3、异步 4、顺序性 三、RabbitMQ基本结构 四、RabbitMQ队列模式 1、简单队列模式 2、工作队列模式 3、发布/订阅模式 4、路由模式 5、主题模式 6、…

嵌入式硬件篇---OpenMV的硬件流和软件流

文章目录 前言一、硬件流控制&#xff08;Hardware Flow Control&#xff09;1. 基本原理RTSCTS 2. OpenMV中的实现• 硬件要求• 代码配置• 工作流程 二、软件流控制&#xff08;Software Flow Control&#xff09;1. 基本原理XONXOFF 2. OpenMV中的实现• 代码配置• 工作流…

【AIGC提示词系统】基于 DeepSeek R1 + ClaudeAI 易经占卜系统

上篇因为是VIP&#xff0c;这篇来一个免费的 提示词在最下方&#xff0c;喜欢的点个关注吧 引言 在人工智能与传统文化交融的今天&#xff0c;如何让AI系统能够传递传统易经文化的智慧&#xff0c;同时保持易经本身的神秘感和权威性&#xff0c;是一个极具挑战性的课题。本文将…

OpenAI 实战进阶教程 - 第十节 : 结合第三方工具的向量数据库Pinecone

面向读者群体 本节课程主要面向有一定编程基础和数据处理经验的计算机从业人员&#xff0c;如后端开发工程师、数据工程师以及对 AI 应用有浓厚兴趣的技术人员。即使你之前没使用过向量数据库&#xff0c;也可以通过本节的实操内容快速上手&#xff0c;为企业或个人项目构建强…