FFMPEG库实现mp4/flv文件(H264+AAC)的封装与分离

ffmepeg 4.4(亲测可用)
一、使用FFMPEG库封装264视频和acc音频数据到 mp4/flv 文件中
封装流程
1.使用avformat_open_input分别打开视频和音频文件,初始化其AVFormatContext,使用avformat_find_stream_info获取编码器基本信息
2.使用avformat_alloc_output_context2初始化输出的AVFormatContext结构
3.使用函数avformat_new_stream给输出的AVFormatContext结构创建音频和视频流,使用avcodec_parameters_copy方法将音视频的编码参数拷贝到新创建的对应的流的codecpar结构中
4.使用avio_open打开输出文件,初始化输出AVFormatContext结构中的IO上下文结构
5.使用avformat_write_header写入流的头信息到输出文件中
6.根据时间戳同步原则交错写入音视频数据,并对时间戳信息进行设置和校准
7.写入流预告信息到输出文件中(moov)
8.释放空间,关闭文件
【mp4_muxer.cpp】
#include <stdio.h>#define __STDC_CONSTANT_MACROS#ifdef _WIN32//Windows
extern "C"
{
#include "libavformat/avformat.h"
};
#else//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavformat/avformat.h>
#ifdef __cplusplus
};
#endif
#endifint main(int argc, char* argv[]) {const AVOutputFormat* ofmt = NULL;//Input AVFormatContext and Output AVFormatContextAVFormatContext* ifmt_ctx_v = NULL, * ifmt_ctx_a = NULL, * ofmt_ctx = NULL;AVPacket pkt;int ret;unsigned int i;int videoindex_v = -1, videoindex_out = -1;int audioindex_a = -1, audioindex_out = -1;int frame_index = 0;int64_t cur_pts_v = 0, cur_pts_a = 0;int writing_v = 1, writing_a = 1;const char* in_filename_v = "test.h264";const char* in_filename_a = "audio_chn0.aac";const char* out_filename = "test.mp4";//Output file URLif ((ret = avformat_open_input(&ifmt_ctx_v, in_filename_v, 0, 0)) < 0) {printf("Could not open input file.");goto end;}if ((ret = avformat_find_stream_info(ifmt_ctx_v, 0)) < 0) {printf("Failed to retrieve input stream information");goto end;}if ((ret = avformat_open_input(&ifmt_ctx_a, in_filename_a, 0, 0)) < 0) {printf("Could not open input file.");goto end;}if ((ret = avformat_find_stream_info(ifmt_ctx_a, 0)) < 0) {printf("Failed to retrieve input stream information");goto end;}//Outputavformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);if (!ofmt_ctx) {printf("Could not create output context\n");ret = AVERROR_UNKNOWN;goto end;}ofmt = ofmt_ctx->oformat;for (i = 0; i < ifmt_ctx_v->nb_streams; i++) {//Create output AVStream according to input AVStreamif (ifmt_ctx_v->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {AVStream* out_stream = avformat_new_stream(ofmt_ctx, nullptr);videoindex_v = i;if (!out_stream) {printf("Failed allocating output stream\n");ret = AVERROR_UNKNOWN;goto end;}videoindex_out = out_stream->index;//Copy the settings of AVCodecContextif (avcodec_parameters_copy(out_stream->codecpar, ifmt_ctx_v->streams[i]->codecpar) < 0) {printf("Failed to copy context from input to output stream codec context\n");goto end;}break;}}for (i = 0; i < ifmt_ctx_a->nb_streams; i++) {//Create output AVStream according to input AVStreamif (ifmt_ctx_a->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {AVStream* out_stream = avformat_new_stream(ofmt_ctx, nullptr);audioindex_a = i;if (!out_stream) {printf("Failed allocating output stream\n");ret = AVERROR_UNKNOWN;goto end;}audioindex_out = out_stream->index;//Copy the settings of AVCodecContextif (avcodec_parameters_copy(out_stream->codecpar, ifmt_ctx_a->streams[i]->codecpar) < 0) {printf("Failed to copy context from input to output stream codec context\n");goto end;}out_stream->codecpar->codec_tag = 0;if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)ofmt_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;break;}}/* open the output file, if needed */if (!(ofmt->flags & AVFMT_NOFILE)) {if (avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE)) {fprintf(stderr, "Could not open '%s': %d\n", out_filename,ret);goto end;}}//Write file headerif (avformat_write_header(ofmt_ctx, NULL) < 0) {fprintf(stderr, "Error occurred when opening output file: %d\n",ret);goto end;}//写入数据while (writing_v || writing_a){AVFormatContext* ifmt_ctx;int stream_index = 0;AVStream* in_stream, * out_stream;int av_type = 0;if (writing_v &&(!writing_a || av_compare_ts(cur_pts_v, ifmt_ctx_v->streams[videoindex_v]->time_base,cur_pts_a, ifmt_ctx_a->streams[audioindex_a]->time_base) <= 0)){av_type = 0;ifmt_ctx = ifmt_ctx_v;stream_index = videoindex_out;if (av_read_frame(ifmt_ctx, &pkt) >= 0){do {in_stream = ifmt_ctx->streams[pkt.stream_index];out_stream = ofmt_ctx->streams[stream_index];if (pkt.stream_index == videoindex_v){//FIX:No PTS (Example: Raw H.264)//Simple Write PTSif (pkt.pts == AV_NOPTS_VALUE){//Write PTSAVRational time_base1 = in_stream->time_base;//Duration between 2 frames (us)int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(in_stream->r_frame_rate);//Parameterspkt.pts = (double)(frame_index * calc_duration) / (double)(av_q2d(time_base1) * AV_TIME_BASE);pkt.dts = pkt.pts;pkt.duration = (double)calc_duration / (double)(av_q2d(time_base1) * AV_TIME_BASE);frame_index++;printf("frame_index:  %d\n", frame_index);}cur_pts_v = pkt.pts;break;}} while(av_read_frame(ifmt_ctx, &pkt) >= 0);}else{writing_v = 0;continue;}}else{av_type = 1;ifmt_ctx = ifmt_ctx_a;stream_index = audioindex_out;if (av_read_frame(ifmt_ctx, &pkt) >= 0){do {in_stream = ifmt_ctx->streams[pkt.stream_index];out_stream = ofmt_ctx->streams[stream_index];if (pkt.stream_index == audioindex_a){//FIX:No PTS//Simple Write PTSif (pkt.pts == AV_NOPTS_VALUE){//Write PTSAVRational time_base1 = in_stream->time_base;//Duration between 2 frames (us)int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(in_stream->r_frame_rate);//Parameterspkt.pts = (double)(frame_index * calc_duration) /(double)(av_q2d(time_base1) * AV_TIME_BASE);pkt.dts = pkt.pts;pkt.duration = (double)calc_duration / (double)(av_q2d(time_base1) * AV_TIME_BASE);frame_index++;}cur_pts_a = pkt.pts;break;}} while (av_read_frame(ifmt_ctx, &pkt) >= 0);}else{writing_a = 0;continue;}}//Convert PTS/DTSpkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base,(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base,(AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);pkt.pos = -1;pkt.stream_index = stream_index;printf("Write 1 Packet. type:%d, size:%d\tpts:%ld\n", av_type, pkt.size, pkt.pts);//Writeif (av_interleaved_write_frame(ofmt_ctx, &pkt) < 0) {printf("Error muxing packet\n");break;}av_packet_unref(&pkt);}printf("Write file trailer.\n");//Write file trailerav_write_trailer(ofmt_ctx);end:avformat_close_input(&ifmt_ctx_v);avformat_close_input(&ifmt_ctx_a);/* close output */if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))avio_close(ofmt_ctx->pb);avformat_free_context(ofmt_ctx);if (ret < 0 && ret != AVERROR_EOF) {printf("Error occurred.\n");return -1;}return 0;
}
【Makefile】
CROSS_COMPILE = aarch64-himix200-linux-CC = $(CROSS_COMPILE)g++
AR = $(CROSS_COMPILE)ar
STRIP = $(CROSS_COMPILE)stripCFLAGS = -Wall -O2 -I../../source/mp4Lib/include
LIBS += -L../../source/mp4Lib/lib -lpthread
LIBS += -lavformat -lavcodec -lavdevice -lavutil -lavfilter -lswscale -lswresample -lzSRCS = $(wildcard *.cpp)
OBJS = $(SRCS:%.cpp=%.o)
DEPS = $(SRCS:%.cpp=%.d)
TARGET = mp4muxerall:$(TARGET)-include $(DEPS)%.o:%.cpp$(CC) $(CFLAGS) -c -o $@ $<%.d:%.c@set -e; rm -f $@; \$(CC) -MM $(CFLAGS) $< > $@.$$$$; \sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \rm -f $@.$$$$$(TARGET):$(OBJS)$(CC) -o $@ $^ $(LIBS)$(STRIP) $@ .PHONY:cleanclean:rm -fr $(TARGET) $(OBJS) $(DEPS)
二、使用FFMPEG分离mp4/flv文件中的264视频和aac音频
分离流程
1.使用avformat_open_input 函数打开文件并初始化结构AVFormatContext
2.查找是否存在音频和视频信息
3.构建一个h264_mp4toannexb比特流的过滤器,用来给视频avpaket包添加头信息
4.打开2个输出文件(音频, 视频)
5.循环读取视频文件,并将音视频分别写入文件
注意:音频需要手动添加头信息,没有提供aac的adts自动添加的过滤器
【mp4_demuxer.cpp】
#include <stdio.h>
extern "C"
{
#include <libavformat/avformat.h>
}/* 打印编码器支持该采样率并查找指定采样率下标 */
static int find_sample_rate_index(const AVCodec* codec, int sample_rate)
{const int* p = codec->supported_samplerates;int sample_rate_index = -1; //支持的分辨率下标int count = 0;while (*p != 0) {// 0作为退出条件,比如libfdk-aacenc.c的aac_sample_ratesprintf("%s 支持采样率: %dhz  对应下标:%d\n", codec->name, *p, count);if (*p == sample_rate)sample_rate_index = count;p++;count++;}return sample_rate_index;
}/// <summary>
/// 给aac音频数据添加adts头
/// </summary>
/// <param name="header">adts数组</param>
/// <param name="sample_rate">采样率</param>
/// <param name="channals">通道数</param>
/// <param name="prfile">音频编码器配置文件(FF_PROFILE_AAC_LOW  定义在 avcodec.h)</param>
/// <param name="len">音频包长度</param>
void addHeader(char header[], int sample_rate, int channals, int prfile, int len)
{uint8_t sampleIndex = 0;    switch (sample_rate) {case 96000: sampleIndex = 0; break;case 88200: sampleIndex = 1; break;case 64000: sampleIndex = 2; break;case 48000: sampleIndex = 3; break;case 44100: sampleIndex = 4; break;case 32000: sampleIndex = 5; break;case 24000: sampleIndex = 6; break;case 22050: sampleIndex = 7; break;case 16000: sampleIndex = 8; break;case 12000: sampleIndex = 9; break;case 11025: sampleIndex = 10; break;case 8000: sampleIndex = 11; break;case 7350: sampleIndex = 12; break;default: sampleIndex = 4; break;}uint8_t audioType = 2;  //AAC LCuint8_t channelConfig = 2;      //双通道len += 7;//0,1是固定的header[0] = (uint8_t)0xff;         //syncword:0xfff                          高8bitsheader[1] = (uint8_t)0xf0;         //syncword:0xfff                          低4bitsheader[1] |= (0 << 3);    //MPEG Version:0 for MPEG-4,1 for MPEG-2  1bitheader[1] |= (0 << 1);    //Layer:0                                 2bits header[1] |= 1;           //protection absent:1                     1bit//根据aac类型,采样率,通道数来配置header[2] = (audioType - 1) << 6;            //profile:audio_object_type - 1                      2bitsheader[2] |= (sampleIndex & 0x0f) << 2; //sampling frequency index:sampling_frequency_index  4bits header[2] |= (0 << 1);                             //private bit:0                                      1bitheader[2] |= (channelConfig & 0x04) >> 2;           //channel configuration:channel_config               高1bit//根据通道数+数据长度来配置header[3] = (channelConfig & 0x03) << 6;     //channel configuration:channel_config      低2bitsheader[3] |= (0 << 5);                      //original:0                               1bitheader[3] |= (0 << 4);                      //home:0                                   1bitheader[3] |= (0 << 3);                      //copyright id bit:0                       1bit  header[3] |= (0 << 2);                      //copyright id start:0                     1bitheader[3] |= ((len & 0x1800) >> 11);           //frame length:value   高2bits//根据数据长度来配置header[4] = (uint8_t)((len & 0x7f8) >> 3);     //frame length:value    中间8bitsheader[5] = (uint8_t)((len & 0x7) << 5);       //frame length:value    低3bitsheader[5] |= (uint8_t)0x1f;                    //buffer fullness:0x7ff 高5bitsheader[6] = (uint8_t)0xfc;
}int main() {AVFormatContext* ifmt_ctx = NULL;AVPacket pkt;int ret;unsigned int i;int videoindex = -1, audioindex = -1;const char* in_filename = "test.mp4";const char* out_filename_v = "test1.h264";const char* out_filename_a = "test1.aac";if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {printf("Could not open input file.");return -1;}if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {printf("Failed to retrieve input stream information");return -1;}videoindex = -1;for (i = 0; i < ifmt_ctx->nb_streams; i++) { //nb_streams:视音频流的个数if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)videoindex = i;else if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)audioindex = i;}printf("\nInput Video===========================\n");av_dump_format(ifmt_ctx, 0, in_filename, 0);  // 打印信息printf("\n======================================\n");FILE* fp_audio = fopen(out_filename_a, "wb+");FILE* fp_video = fopen(out_filename_v, "wb+");AVBSFContext* bsf_ctx = NULL;const AVBitStreamFilter* pfilter = av_bsf_get_by_name("h264_mp4toannexb");if (pfilter == NULL) {printf("Get bsf failed!\n");}if ((ret = av_bsf_alloc(pfilter, &bsf_ctx)) != 0) {printf("Alloc bsf failed!\n");}ret = avcodec_parameters_copy(bsf_ctx->par_in, ifmt_ctx->streams[videoindex]->codecpar);if (ret < 0) {printf("Set Codec failed!\n");}ret = av_bsf_init(bsf_ctx);if (ret < 0) {printf("Init bsf failed!\n");}//这里遍历音频编码器打印支持的采样率,并找到当前音频采样率所在的下表,用于后面添加adts头//本程序并没有使用,只是测试,如果为了程序健壮性可以采用此方式const AVCodec* codec = nullptr;codec  = avcodec_find_encoder(ifmt_ctx->streams[audioindex]->codecpar->codec_id);int sample_rate_index = find_sample_rate_index(codec, ifmt_ctx->streams[audioindex]->codecpar->sample_rate);printf("分辨率数组下表:%d\n", sample_rate_index);while (av_read_frame(ifmt_ctx, &pkt) >= 0) {if (pkt.stream_index == videoindex) {av_bsf_send_packet(bsf_ctx, &pkt);while (true){ret = av_bsf_receive_packet(bsf_ctx, &pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)break;else if (ret < 0) {printf("Receive Pkt failed!\n");break;}printf("Write Video Packet. size:%d\tpts:%ld\n", pkt.size, pkt.pts);fwrite(pkt.data, 1, pkt.size, fp_video);}}else if (pkt.stream_index == audioindex) {printf("Write Audio Packet. size:%d\tpts:%ld\n", pkt.size, pkt.pts);char adts[7] = { 0 };addHeader(adts, ifmt_ctx->streams[audioindex]->codecpar->sample_rate, ifmt_ctx->streams[audioindex]->codecpar->channels, ifmt_ctx->streams[audioindex]->codecpar->profile,pkt.size);fwrite(adts, 1, 7, fp_audio);fwrite(pkt.data, 1, pkt.size, fp_audio);}av_packet_unref(&pkt);}av_bsf_free(&bsf_ctx);fclose(fp_video);fclose(fp_audio);avformat_close_input(&ifmt_ctx);return 0;if (ifmt_ctx)avformat_close_input(&ifmt_ctx);if (fp_audio)fclose(fp_audio);if (fp_video)fclose(fp_video);if (bsf_ctx)av_bsf_free(&bsf_ctx);return -1;
}
【Makefile】
CROSS_COMPILE = aarch64-himix200-linux-CC = $(CROSS_COMPILE)g++
AR = $(CROSS_COMPILE)ar
STRIP = $(CROSS_COMPILE)stripCFLAGS = -Wall -O2 -I../../source/mp4Lib/include
LIBS += -L../../source/mp4Lib/lib -lpthread
LIBS += -lavformat -lavcodec -lavdevice -lavutil -lavfilter -lswscale -lswresample -lzSRCS = $(wildcard *.cpp)
OBJS = $(SRCS:%.cpp=%.o)
DEPS = $(SRCS:%.cpp=%.d)
TARGET = mp4demuxerall:$(TARGET)-include $(DEPS)%.o:%.cpp$(CC) $(CFLAGS) -c -o $@ $<%.d:%.c@set -e; rm -f $@; \$(CC) -MM $(CFLAGS) $< > $@.$$$$; \sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \rm -f $@.$$$$$(TARGET):$(OBJS)$(CC) -o $@ $^ $(LIBS)$(STRIP) $@ .PHONY:cleanclean:rm -fr $(TARGET) $(OBJS) $(DEPS)

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

APP 备案公钥、签名 MD5、SHA-1、SHA-256获取方法。

公钥和 MD5 值可以通过安卓开发工具、Keytool、Jadx-GUI 等多种工具获取&#xff0c;最简单的就是以 appuploader为例。 1.下载 appuploader工具 &#xff0c;点击此处 下载 appuploader 工具。 2.下载完成后&#xff0c;解压压缩包&#xff0c;双击 appuploder 运行。 3.运…

LeetCode(6)轮转数组【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 189. 轮转数组 1.题目 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1…

【Bug】Python利用matplotlib绘图无法显示中文解决办法

一&#xff0c;问题描述 当利用matplotlib进行图形绘制时&#xff0c;图表标题&#xff0c;坐标轴&#xff0c;标签中文无法显示&#xff0c;显示为方框&#xff0c;并报错 运行窗口报错&#xff1a; 这是中文字体格式未导入的缘故。 二&#xff0c;解决方案 在代码import部…

华为eNSP实验-QinQ基本实验

1.拓扑图如下 PC1的设置如下&#xff1a; 在未配置VLAN之前&#xff0c;PC1可以ping通PC3&#xff0c;PC2可以ping通PC4&#xff08;因为同一网段&#xff09; 2.SW1和SW4配置VLAN <Huawei>system-view [Huawei]undo info-center enable //关闭提示信息 [Huawei]sysn…

利用servlet实现对书籍书名、单价、数量等信息的添加,计算总价

1.题目要求 利用servlet实现对书籍书名、单价、数量等信息的添加&#xff0c;计算总价。 要求&#xff1a;输入两次表单信息&#xff0c;在一个成功返回的页面里面显示两次的数据。 2.Book实体类 package com.hjj.sevletgk.hw7.book;/*** author:嘉佳 Date:2023/10/8 15:16*…

jQuery HTML/CSS 参考文档

jQuery HTML/CSS 参考文档 文章目录 应用样式 示例属性方法示例 jQuery HTML/CSS 参考文档 应用样式 addClass( classes ) 方法可用于将定义好的样式表应用于所有匹配的元素上。可以通过空格分隔指定多个类。 示例 以下是一个简单示例&#xff0c;设置了para标签 <p&g…

图书网站信息采集

首先&#xff0c;你需要安装Haskell的HTTP库&#xff0c;比如http-conduit。你可以使用cabal包管理器来安装它。 然后&#xff0c;你需要定义一个函数来处理HTTP请求。这个函数需要接受一个URL和一个代理服务器的地址作为参数。 import Network.HTTP.ConduitgetURL :: String…

【Qt-23】ui界面设计-ToolBar

1、ToolBar 右击主窗体添加工具栏 新建动作&#xff0c;可设置图标&#xff0c;图标有本地文件和资源两种方式。 修改toolButtonStyle的属性&#xff0c;可设置图标与汉字显示的方式。 页面跳转&#xff1a; connect(ui->action, SIGNAL(triggered()), this, SLOT(openWid…

线性代数(五) | 矩阵对角化 特征值 特征向量

文章目录 1 矩阵的特征值和特征向量究竟是什么&#xff1f;2 求特征值和特征向量3 特征值和特征向量的应用4 矩阵的对角化 1 矩阵的特征值和特征向量究竟是什么&#xff1f; 矩阵实际上是一种变换,是一种旋转伸缩变换&#xff08;方阵&#xff09; 不是方阵的话还有可能是一种…

【组件自定义事件+全局事件总线+消息订阅与发布+TodoList案例——编辑+过度与动画】

组件自定义事件全局事件总线消息订阅与发布TodoList案例——编辑过度与动画 1 组件自定义事件1.1 绑定1.2 解绑1.3 总结1.4 TodoList案例——自定义事件 2 全局事件总线2.1 理解2.2 步骤2.3 TodoList案例——事件总线 3 消息订阅与发布3.1 理解3.2 TodoList案例——消息的订阅与…

ChatGPT、GPT-4 Turbo接口调用(stream模式)

接口地址 https://chat.xutongbao.top/api/light/chat/createChatCompletion 请求方式 post 请求参数 model可选值&#xff1a; “gpt-3.5-turbo-1106”、 “gpt-3.5-turbo-16k” 、 “gpt-4”、“gpt-4-1106-preview”。 默认值为&#xff1a; “gpt-3.5-turbo-1106” to…

剪贴板管理软件 Paste Wizard mac中文版功能特色

Paste Wizard mac是一款剪贴板管理工具&#xff0c;它可以帮助用户更高效地管理剪贴板中的文本、图片、链接等内容。 Paste Wizard mac特色功能 提供了多种方式来保存和管理剪贴板中的内容。用户可以创建自定义的标签&#xff0c;将内容按照标签进行分类&#xff0c;方便快速查…

《QT从基础到进阶·十六》QT实现客户端和服务端的简单交互

QT版本&#xff1a;5.15.2 VS版本&#xff1a;2019 客户端程序主要包含三块&#xff1a;连接服务器&#xff0c;发送消息&#xff0c;关闭客户端 服务端程序主要包含三块&#xff1a;打开消息监听&#xff0c;接收消息并反馈&#xff0c;关闭服务端 1、先打开服务端监听功能 …

【Linux奇遇记】我和Linux的初次相遇

&#x1f308;个人主页: Aileen_0v0 &#x1f525;系列专栏:Linux奇遇记系列专栏&#x1f4ab;"没有罗马,那就自己创造罗马~" 目录 前端和后端的介绍 1.前端 2.后端 3.前后端区别 Linux在前后端开发中的角色 如何学习Linux 去进行程序开发 Linux的常见根目…

基于Amazon EC2和Amazon Systems Manager Session Manager的堡垒机设计和自动化实现

01 背景 在很多企业的实际应用场景中&#xff0c;特别是金融类的客户&#xff0c;大部分的应用都是部署在私有子网中。为了能够让客户的开发人员和运维人员从本地的数据中心中安全的访问云上资源&#xff0c;堡垒机是一个很好的选择。传统堡垒机的核心实现原理是基于 SSH 协议的…

高斯过程回归 | GPR高斯过程回归

高斯过程回归(Gaussian Process Regression, GPR)是一种强大的非参数回归方法,它通过假设数据是从一个高斯过程中生成的来预测新的数据点。 高斯过程是一种定义在连续输入空间上的随机过程,其中任何有限集合的观测值都呈多变量高斯分布。 实现GPR的Python代码import numpy …

RK3399平台开发系列讲解(内存篇)free 命令查看内存占用情况介绍

🚀返回专栏总目录 文章目录 一、free的使用二、free的内容📢free 指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等。 一、free的使用 -b  以 Byte 为单位显示内存使用情况。-k  以 KB 为单位显示内存使用情况。…

数据的使用、表关系的创建、Django框架的请求生命周期流程图

目录 一、数据的增删改查 1. 用户列表的展示 2. 修改数据的逻辑分析 3. 删除功能的分析 二、如何创建表关系 三、Django的请求生命周期流程图 一、数据的增删改查 1. 用户列表的展示 把数据表中得用户数据都给查询出来展示在页面上 查询数据 def userlist(request):&qu…

在gitlab中指定自定义 CI/CD 配置文件

文章目录 1. 介绍2. 配置操作3. 配置场景3.1 CI/CD 配置文件在当前项目step1&#xff1a;在当前项目中创建目录&#xff0c;编写流水线文件存放在该目录中step2&#xff1a;在当前项目中配置step3&#xff1a;运行流水线测试 3.2 CI/CD 配置文件位于外部站点上step1&#xff1a…

【Linux】tree命令的独特用法

有关tree命令&#xff0c;我们只知道它可以将文件目录以树状图的形式展示&#xff0c;但其实还有很多有意思的功能可以使用。 一、tree命令的安装 各linux版本不同&#xff0c;但软件包名字就叫tree&#xff0c;直接安装即可 ubuntu&#xff1a; apt install tree centos&a…