以FLV解复用为例详解开源库FFmpeg中解复用器的源码逻辑及处理流程

目录

1、FFmpeg简介

2、FLV文件格式介绍

3、注册解复用器

4、解复用器的处理

4.1、AVFormatContext

4.1.1、AVClass

4.1.2、AVOption

4.1.3    AVDictionary—AV字典

4.1.4、AVIOContext

4.1.4.1、URLProtocol

4.1.4.2、AVIOContext的初始化及获取

4.1.5、AVInputFormat

4.1.6、AVStream

4.2、解复用器的获取

4.3、Flv解复用器处理流程分析

4.3.1、读取头信息--flv_read_header

4.3.2、AVStream的获取--flv_read_packet

5、总结


C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C/C++实战专栏(专栏文章已更新400多篇,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.htmlC++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12695902.htmlVC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++软件分析工具从入门到精通案例集锦(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795开源组件及数据库技术(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html一般音视频编解码器处理的是原始的裸音视频数据(编码器对原始音视频数据进行编码,解码器从编码后的音视频数据中解析出原始的音视频数据)。flv/avi/mp4等格式文件中包含的是编码后的音视频数据,解复用的目的就是从封装容器中解析出各音频流或视频流等。本文以FLV解复用器分析ffmpeg解复用的处理逻辑,介绍了ffmeg中解复用器的注册,并以FLV解复用器为例分析解复用器如何从封装格式中,解析出不同的视频、音频、数据流。

1、FFmpeg简介

FFmpeg是一个开源的多媒体框架,广泛用于处理音视频处理领域。它提供了一套丰富的工具和库,支持广泛的多媒体格式的解码、编码、转码、等功能。支持多种格式的音视频编码和解码,以及音视频的转换、剪辑、过滤、流处理等功能。

FFmpeg主要特性如下:

1)音视频编解码

  • FFmpeg包含了非常先进的音频/视频编解码库libavcodec,其中很多codec都是从头开发的,以保证高可移植性和编解码质量。
  • 支持几乎所有的音视频格式和编解码器,包括常见的MP4、AVI、MOV、MKV、FLV、MP3、AAC等文件封装格式,以及H.264、H.265、AAC、VP9、AV1等音视频编解码器。

2)音视频处理

  • 提供了丰富的音视频处理功能,如去噪、模糊视频、色彩转换、视频旋转、提取帧、缩放视频尺寸等。
  • 可以通过其提供的滤镜库libavfilter对音视频数据进行各种处理,如缩放、裁剪、添加水印等。

3)流媒体处理

  • FFmpeg支持将本地音视频文件转换为流媒体格式,并通过网络进行传输和播放。
  • 完全支持使用HLS和MPEG-DASH打包视频,并可以配置为使用RTMP或其他协议来传输视频。

4)封装与解封装

  • 提供了对各种音视频封装格式的读写支持,如MP4、FLV等。
  • AVFormat模块封装了Protocol层和Demuxer、Muxer层,使得协议和格式对于开发者来说是透明的。

5)高效稳定
FFmpeg在音视频处理方面表现出色,具有高效且稳定的性能,能够处理大量的音视频数据。
6)开源

FFmpeg采用LGPL或GPL许可证,其开源属性意味着任何人都能修改并使用它。
7)跨平台

FFmpeg可以在多种操作系统上运行,包括但不限于Linux、Windows、macOS等,这使其具有非常广泛的适用性。
8)社区支持

作为一个开源项目,FFmpeg拥有活跃的社区,用户可以从社区获得帮助和最新的开发动态。

几乎所有的视频播放器都使用到了FFmpeg的音视频解码功能,比如国内知名的暴风影音、QQ影音、腾讯视频、爱奇艺视频、优酷视频等。

FFmpeg内部支持多种音视频格式之间的相互转换,很多音视频转化软件都用到了FFmpeg的音视频转换功能,比如大家常用的格式工厂、暴风转码(暴风影音自带的工具)、QQ音影自带的视频格式转换工具、狸窝视频转换器、迅捷视频转换器等。    

2、FLV文件格式介绍

FLV视频格式是Adobe公司设计开发的一种流媒体的封装格式,总体上看,FLV包括文件头(Flv Header)和文件体(Flv Body)两部分,其中文件体由一系列的Tag及Tag Size对组成。Tag又可以分成三类:audio,video,script,分别代表音频流,视频流,脚本流(关键字或者文件信息之类)。

header部分记录了flv的类型、版本等信息,是flv的开头,一般都差不多,占9bytes。具体格式如下:

body部分由一个个Tag组成,每个Tag的下面有一块4bytes的空间,用来记录这个tag的长度,这个后置用于逆向读取处理。 每个Tag由也是由两部分组成的:Tag Header和Tag Data。Tag Header里存放的是当前Tag的类型、数据区(Tag Data)长度等信息,具体如下:

3、注册解复用器

调用av_register_all()接口注册所有格式的编解码器和复用/解复用器、硬件加速器、解析等。调用关系图如下:

所有的注册逻辑都是相同的,注册解复用也一样,其链表头为first_iformat:
Ffmpeg/libavformat/allformats.c

 真正实现注册解复用器的函数是av_register_input_format(),如下:
Ffmpeg/libavformat/formats.c

由此可以看出,所有解复用器按注册的先后顺序以链表结构存储起来,链表头为first_iformat。以注册flv、avi为例:

First_iformat是AVInputFormat*类型指针,指向第一个注册的flv解复用器ff_flv_demuxer,flv解复用器对象的next变量(AVInputFormat*类型)指向avi解复用器对象ff_avi_demuxer,依次向后。
需要注意的是,ff_flv_demuxer、ff_avi_demuxer都是按AVInputFormat结构定义好的解复用器对象,以flv为例:
Flv解复用:Ffmpeg/libavformat/flvdec.c

通过上面的分析,向ffmpeg注册新的解码器的步骤如下:

1)在/libavformat下,创建源文件,在该源文件中按AVInputFormat类型接口定义该算法处理。
2)调用REGISTER_DEMUXER宏,注册该解码器。


       在这里,给大家重点推荐一下我的几个热门畅销专栏,欢迎订阅:(博客主页还有其他专栏,可以去查看)

专栏1:该精品技术专栏的订阅量已达到510多个,专栏中包含大量项目实战分析案例,有很强的实战参考价值,广受好评!专栏文章持续更新中,预计更新到200篇以上!欢迎订阅!)

C++软件调试与异常排查从入门到精通系列文章汇总icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本专栏根据多年C++软件异常排查的项目实践,系统地总结了引发C++软件异常的常见原因以及排查C++软件异常的常用思路与方法,详细讲述了C++软件的调试方法与手段,以图文并茂的方式给出具体的项目问题实战分析实例(很有实战参考价值),带领大家逐步掌握C++软件调试与异常排查的相关技术,适合基础进阶和想做技术提升的相关C++开发人员!

考察一个开发人员的水平,一是看其编码及设计能力,二是要看其软件调试能力!所以软件调试能力(排查软件异常的能力)很重要,必须重视起来!能解决一般人解决不了的问题,既能提升个人能力及价值,也能体现对团队及公司的贡献!

专栏中的文章都是通过项目实战总结出来的,包含大量项目问题实战分析案例,有很强的实战参考价值!专栏文章还在持续更新中,预计文章篇数能更新到200篇以上!

专栏2:  

C++常用软件分析工具从入门到精通案例集锦汇总(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795

常用的C++软件辅助分析工具有SPY++、PE工具、Dependency Walker、GDIView、Process Explorer、Process Monitor、API Monitor、Clumsy、Windbg、IDA Pro等,本专栏详细介绍如何使用这些工具去巧妙地分析和解决日常工作中遇到的问题,很有实战参考价值!

专栏3:(本专栏涵盖了C++多方面的内容,是当前重点打造的专栏,专栏文章已经更新到400多篇,持续更新中...)

C/C++实战进阶(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的开发实战为基础,总结并讲解一些的C/C++基础与项目实战进阶内容,以图文并茂的方式对相关知识点进行详细地展开与阐述!专栏涉及了C/C++领域多个方面的内容,包括C++基础及编程要点(模版泛型编程、STL容器及算法函数的使用等)、C++11及以上新特性(不仅看开源代码会用到,日常编码中也会用到部分新特性,面试时也会涉及到)、常用C++开源库的介绍与使用、代码分享(调用系统API、使用开源库)、常用编程技术(动态库、多线程、多进程、数据库及网络编程等)、软件UI编程(Win32/duilib/QT/MFC)、C++软件调试技术(排查软件异常的手段与方法、分析C++软件异常的基础知识、常用软件分析工具使用、实战问题分析案例等)、设计模式、网络基础知识与网络问题分析进阶内容等。

专栏4:   

VC++常用功能开发汇总(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585

将10多年C++开发实践中常用的功能,以高质量的代码展现出来。这些常用的高质量规范代码,可以直接拿到项目中使用,能有效地解决软件开发过程中遇到的问题。

专栏5: 

C++ 软件开发从入门到精通(专栏文章,持续更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12695902.html

根据多年C++软件开发实践,详细地总结了C/C++软件开发相关技术实现细节,分享了大量的实战案例,很有实战参考价值。


4、解复用器的处理

解复用器处理过程中,涉及到若干结构体类型,这里先介绍下。

4.1、AVFormatContext

媒体封装上下文,包含如下成员,下面我们分析这几个结构体类型:

4.1.1、AVClass

AVClass是一个成员管理系统,记录了其关联类的类名、并通过其AVOption对象设置关联类的成员变量等,AVFormatContext、AVIOContext、AVCodecContext等都有其对应的AVClass成员管理对象AVFormatContext对象调用avformat_get_context_defaults()接口初始化默认值时,将其av_class对象指向全局的AVClass对象av_format_context_class, av_format_context_class的AVOption成员option指向全局的avformat_options数组,这里列出一部分如下:
/ffmpeg/libavformat/options.c

 /ffmpeg/libavformat/options_table.h

AVFormatContext、AVClass与AVOption之间的关系如下:

图中AVFormatContext结构体的第一个变量为AVClass类型的指针av_class,它在AVFormatContext结构体初始化的时候,被赋值指向了全局静态变量av_format_context_class结构体(定义位于libavformat\options.c)。而AVClass类型的av_format_context_class结构体中的option变量指向了全局静态数组avformat_options(定义位于libavformat\options_table.h)。
Ps:应该也可以自定义一个AVClass及AVOption对象,赋给AVFormatContext。

4.1.2、AVOption

AVClass中存储了AVOption类型的option数组,用于存储AVClass关联类的成员变量信息,每一个成员变量对应一个AVOption。可以使用av_opt_set()函数通过字符串的方式(传入参数为变量名称的字符串和变量值的字符串)设置AVOption的值。
/ffmpeg/libavutil/opt.c

该函数首先通过av_opt_find2()在**(AVClass**)obj中查找到与name匹配的AVOption对象o,然后根据该对象的类型o->type调用相应的类型设置函数(如set_string_bool、set_string、set_string_image_size等),将字符串val转换为相应type的数据并对该AVOption对象o进行赋值。
Ps: av_opt_get通过字符串获取变量值:

4.1.3    AVDictionary—AV字典

AVDictionary键值对类型,结构体定义如下:
/ffmpeg/libavutil/dict.c

/ffmpeg/libavutil/dict.h

这里介绍设置键值和获取键值的两个接口
/ffmpeg/libavutil/dict.h

功能:将键值对(key, value)添加到pm中,如果pm为*pm为NULL,将会创建一个新的AVDictionaryEntry对象并将该对象地址赋值给*pm
/ffmpeg/libavutil/dict.h

功能:在m中遍历,获得匹配key值的AVDictionaryEntry对象(即返回值)。

4.1.4、AVIOContext

协议(文件)操作的顶层结构是AVIOContext,这个对象实现了带缓冲的读写操作;FFMPEG的输入对象AVFormat的pb字段指向一个AVIOContext。

AVIOContext的opaque实际指向一个URLContext对象,这个对象封装了协议对象及协议操作对象,其中prot指向具体的协议操作对象,priv_data指向具体的协议对象。

URLProtocol为协议操作对象,针对每种协议,会有一个这样的对象,每个协议操作对象和一个协议对象关联,比如,文件操作对象为ff_file_protocol,它关联的结构体是FileContext。

4.1.4.1、URLProtocol

URLProtocol是FFMPEG操作文件的结构(包括文件,网络数据流等等),包括open、close、read、write、seek等操作。
在在av_register_all()函数中,通过调用REGISTER_PROTOCOL()宏,所有的URLProtocol都保存在以first_protocol为链表头的链表中
/ffmpeg/libavformat/url.h

以file文件为例:

查看file_open发现, ff_file_protocol操作的FileContext数据就是URLContext的priv_data

4.1.4.2、AVIOContext的初始化及获取

/ffmpeg/libavformat/aviobuf.c

从上图发现,最终实现AVIOContext初始化并获取对文件对象的是ffio_open_whitelist。

4.1.5、AVInputFormat

从前文了解到AVInputFormat实际上就是解复用器结构类型,各类型的解复用器已经在av_register_all()是注册成全局的链表,表头为first_iformat。以flv为例:
/ffmpeg/libavformat/flvdec.c

  • .name:解复用器名称
  • .long_name:对应的文件格式
  • .priv_date_size:该解复用器关联的文件结构体类型
  • .read_probe:检测输入AVProbeData文件名数据与该解复用器的匹配度
  • .read_header:
  • .read_packet:
  • .read_seek:
  • .extensions:后缀名

后边几个函数分别为探测、读取头信息、读取包信息、搜索、关闭,从这几个函数的源代码可以看出,解复用器处理的FLVContext数据指针保存在其关联AVFormatContext->priv_data中。

4.1.6、AVStream

AVStream是存储媒体流信息的结构体,其初始化函数avformat_new_stream(),解复用器负责把不同媒体流从容器(媒体文件)中解析出来并保存到不同的AVStream中。

4.2、解复用器的获取

AVInputFormat解复用器对象的获取有两种方法:

1)由文件名获取:/ffmpeg/libavformat/utils.cinit_input()

​Pd中包含了文件名,由文件名检测出对应的解复用器。

av_probe_input_format2调用av_probe_input_format3,在av_probe_input_format3中,遍历所有注册的解复用器fmt1(AVInputFormat),对于每个解复用器fmt1,调用fmt1的检测函数read_probe检测其与文件名的匹配度,如果没有该函数,则通过fmt1的后缀名extensions匹配。

​2)如果文件名检测不出来,则通过AVIOContext获取:/ffmpeg/libavformat/utils.cinit_input()

​s->pb为解复用器AVInputFormat对象所在AVFormatContext对象的AVIOContext成员,其获取方法如下:

在av_probe_input_buffer2函数中,实际上也是通过avio_read接口从s->pb中得到媒体相关的AVProbeData数据,然后再调用av_probe_input_format2接口(即方法一),获得解复用器。需要注意的是:

i)s->io_open在s(AVFormatContext类型)初始化时构建
/ffmpeg/libavformat/options.c

​查看io_open_default发现,该函数调用的是ffio_open_whitelist函数,由3.1.4.2可知正是该函数根据文件名获取了其对应的AVIOContext对象pb。

ii)方法一和方法二虽然最终都调用av_probe_input_format2检测,但在该函数中看,方法一、二的参数和处理流程是不一样的。

​/ffmpeg/libavformat/avformat.h 

​方法一中,pd = {filename, NULL, 0} 因为pd->buf = NULL,所以调用fmt1->read_probe是检测不到对应的解复用器的,只能通过pd->filename和fmt1->extensions比较得到结果。

方法二中,pd = {filename, buf, 0} ,其中buf是在av_probe_input_buffer2中调用avio_read获取的。由于pd->buf不为NULL,所以在fmt1->read_probe可检测到其对应的解复用器。

4.3、Flv解复用器处理流程分析

Flv解复用器按照flv文件格式解析出数据,根据不同的音频、视频数据,创建出对应的AVStream并记录到AVFormatContext中。这里介绍主要的两个函数

4.3.1、读取头信息--flv_read_header

/ffmpeg/libavformat/flvdec.c

​首先我们要知道s->pb是AVIOContext,该结构体中存在一个读写指针buf_ptr记录当前文件的读写位置。下面我们对每行代码进行分析:

line632:s->priv_data在avformat_open_input函数中被指向ff_flv_demuxer.priv_class即flv_class(参           看ff_flv_demuxer定义),显然这里flv_class应该是在初始化FLVContext对象时,被赋值给FLVContext成员管理对象的,但是我没有找到FLVContext初始化的地方。

/ffmpeg/libavformat/utils.c

Line635:跳过4个字节
Line636:读取1个字节,也就是第5个字节,对照FLV文件格式,我们发现改字节记录了流信息
Line640:读取4个字节,获取header长度
Line641:从文件开始,跳过文件头Header,到FLV body部分
Line642:跳过4个字节,这4个字节记录上一个Tag的大小即表中的PreTagSize0

到这里flv_read_header就结束了,我们发现该函数的作用仅仅是把读写指针buf_ptr指向flv的第一个有效媒体数据部分即Tag0。
需要说明的是,不同媒体格式的处理都不一样,avi的avi_read_header函数,就实现了AVStream的创建即参数设置,而FLV的AVStream则是在flv_read_packet()中创建的。

4.3.2、AVStream的获取--flv_read_packet

该函数代码较多,这里分析主要代码行
/ffmpeg/libavformat/flvdec.c

Line850:获取AVIOContext当前读写位置
Line851:读1字节,该字节标识当前tag是音频流(8)/视频流(9)/脚本数据(18)
Line853:3字节,记录数据区长度
Line854:记录已经读取的所有tag总长度
Line855:获取时间戳(3字节)
Line856:获取扩展时间戳(1字节)并和line855行获取的时间戳组合成完整的时间戳
Line860:跳过3个字节(这3个字节为streamid),读写指针指向数据区TagData

Line886:根据Line851获取的type,判断该tag是否为音频数据
Line888:读1个字节flags,该字节高4位标识音频格式、2-3两位标识采样率,最后两位分别标识位宽和声道
Line890:根据type判断该tag是否为视频数据
Line892:读1字节flags,该字节高4位标识帧类型(I/P/B),低四位标识视频格式
Line896-901:脚本数据,flv_read_metabody函数获取码流宽高等信息,并保持到AVFormatContext

通过以上两段代码的分析,我们发现flv解复用器所做的操作都是按照flv语法获取数据,很显然其他解复用器也是同样的原理。

Line936-950:遍历已有的AVStream队列,查找和当前tag数据类型相同的AVStream流,显然从tag1开始处理时,是没有AVStream队列的,应该跳转到Line951行
Line940:根据Line888得到的flags,获取音频解码器id(st->codecpar->codec_id),如AV_CODEC_ID_AAC
Line944:根据Line892得到的flags,获取视频解码器id(st->codecpar->codec_id),如AV_CODEC_ID_H264
Line954:根据Line887/891的stream_type创建并初始化AVStream流。查看create_stream函数发现,该函数就是通过avformat_new_stream创建的AVStream对象。

Line1009-1012:根据flags获取音频通道数channels、采样率sample_rate和位宽bits_per_coded_sample
Line1015-1025:更新创建的AVStream流的解码器参数信息

Line1042:设置AVStream的视频解码器信息

 
Line1112:读取tagData数据到AVPacktet
Line1115:设置解码时间戳dts
Line1116:设置显示时间戳pts
Line1117:设置该AVPacket所在的AVStream队列

flv_read_header()和flv_read_packet()两个函数基本完成了flv媒体的解复用功能,这两个函数分别在avformat_open_input()和avformat_find_stream_info()两个接口中用到,并完成对AVFormatContext和AVStream信息的赋值。

调用avformat_open_input()获取的信息如下:通过之前的分析,我们知道flv_read_header没有获取信息,仅仅是移动了读写指针。

​调用avformat_find_stream_info()获取的信息如下,该函数中会调用flv_read_packet(),并解析相关数据,可以完整填充AVFormatContext和AVStream信息:

​至此,解复用器逻辑分析结束。

       以上代码截图中的代码查看工具是Source Insight,该工具是轻量级的代码查看与编辑工具,虽不能编译代码,但查看和编辑代码很方便,我们经常使用该工具去查看开源代码。关于如何使用Source Insight工具,可以查看我之前写的文章:

如何使用 Source Insight 查看编辑C/C++源代码?icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124347857

5、总结

简单来讲,解复用器功能就是获取音视频码流所需解码器,在读取包AVPacket后,根据数据包AVPacket所在流AVStream,找到对应的解码器进行解码。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【手撕数据结构】链式二叉树

目录 链式二叉树的结构及其声明链式二叉树的四种遍历方式前序遍历中序遍历(中根遍历)后序遍历层序遍历概念思路分析详细代码 求树的节点个数变量累加法(错误)分治递归法 求树的叶子节点个数警惕空指针正确代码 求第k层节点个树思路分析及规则明细代码详细…

算法学习017 不同的二叉搜索树 c++算法学习 中小学算法思维学习 比赛算法题解 信奥算法解析

目录 C不同的二叉搜索树 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、运行结果 五、考点分析 六、推荐资料 C不同的二叉搜索树 一、题目要求 1、编程实现 给定一个整数n,求以1、2、3、......、n为节点组成的二叉搜索树有多少种…

C++ 设计模式——工厂方法模式

工厂方法模式 工厂方法模式主要组成部分代码实现工厂方法模式模式的 UML 图工厂方法模式 UML 图解析优点和缺点适用场景 工厂方法模式 工厂方法模式是一种创建型设计模式,它通过定义一个接口用于创建对象,但由子类决定实例化哪个类。与简单工厂模式不同…

数据结构----栈

一丶概念 只能在一端进行插入和删除操作的线性表(又称为堆栈),进行插入和删除操作的一端称为栈顶,另一端称为栈底 二丶特点 先进后出 FILO first in last out 后进先出 LIFO last in first out 三丶顺序栈 逻辑结构&…

什么是制造业项目管理软件?适合制造企业的项目管理软件具备哪些特征

当前,我国的制造业呈现出稳步增长与风险并存的现象。经济构建以国内大循环为主体,国产替代的浪潮正在席卷国内制造业,越来越多的制造领域企业开始启动数字化变革来支撑企业的迅猛发展,进一步优化项目管理流程,促进研发…

Impala 与 Hive 的比较

Impala 与 Hive 的关系 impala是基于hive的大数据分析查询引擎,直接使用hive的元数据库metadata,意味着impala元数据都存储在hive的metastore当中,并且impala兼容hive的绝大多数sql语法。所以需要安装impala的话,必须先安装hive&…

开发小运维-常用Linux资源监控命令

文章目录 简介常用命令/proc/meminfo(内存)free(内存信息)top(进程动态)df (磁盘信息)du(磁盘信息)ps(进程状态)vmstat(内…

iOS的App启动详细过程(底层知识)

1.虚拟内存 & ASLR 在早期计算机中数据是直接通过物理地址访问的,这就造成了下面两个问题 1.内存不够用 2.数据安全问题 内存不够 ---> 虚拟内存 虚拟内存就是通过创建一张物理地址和虚拟地址的映射表来管理内存,提高了CPU利用率,…

IDEA:如何在idea中设置自动导包

这里使用的是idea2020版本,但是不同版本操作不会有较大的差别. 在Editer中展开General之后,选中Auto Import,最后勾选中Add unambiguous imports on the fly.

DMHS数据同步工具

DMHS数据同步工具 ​ 本章节主要介绍DM数据同步工具DMHS的使用,通过将oracle11g的数据同步到DM8的过程来理解DMHS的功能和作用。 安装前的准备 端口、服务信息 IP地址服务名称版本端口安装路径192.168.19.136OracleOracle11.0.21521/opt/oracle/DMHS源端dmhs_V3…

深入理解Faiss:高效向量检索的利器

近年来,随着人工智能和机器学习技术的飞速发展,向量检索技术变得越来越重要。无论是在推荐系统、图像搜索还是自然语言处理等领域,向量检索都扮演着至关重要的角色。而在众多向量检索库中,Faiss(Facebook AI Similarit…

基于Springboot 和Vue 的高校宿舍管理系统源码

网络上很多宿舍管理系统都不完整,大多数缺少数据库文件,所在使用极其不方便,由于本人程序员,根据代码,自己花时间不全了数据库文件,并且可以完美运行!!!!&…

C++:C/C++的内存管理

目录 C/C内存分布 C语言中动态内存管理方式 C内存管理方式 new/delete操作内置类型 new/delete操作自定义类型 operator new与operator delete函数 new和delete的实现原理 定位new表达式 常见问题 malloc/free和new/delete的区别 内存泄漏 C/C内存分布 我们先来看以…

【傅里叶分析】复数基础知识

【傅里叶分析】复数基础知识 复数复数的几何意义与点的对应与向量的对应 复数与极坐标辐角与辐角主值三角函数 参考文献 本文参考了网上的其他文章,已在文末参考文献中列出;如有侵权,请联系我删除。 复变函数是傅里叶分析的基础,而…

【原创公式】【完全二叉树】叶结点的计算【数据结构】

完全二叉树叶结点的计算 【铺垫】1叶结点即度为0的结点 2完全二叉树中度为1的结点只可能有0或1个 3完全二叉树的设叶结点仅可能出现在最后2层 设有完全二叉树T 【区分】第k层有a个叶结点≠第k层有a个结点 (1)第k层有a个叶结点:T的形态不唯一&…

【Linux操作系统】进程控制

目录 一、进程创建1.1 认识fork1.2 写时拷贝 二、进程终止2.1 进程退出2.2 函数退出2.3 exit 三、进程等待四、程序替换 一、进程创建 1.1 认识fork fork函数是系统调用接口,用来创建子进程的 根据进程的pid,可以看出父进程fork后分为父进程和子进程…

单片机原理及技术(六)—— 中断系统的工作原理

目录 一、AT89S51中断技术概述 二、AT89S51中断系统结构 2.1 中断请求源 2.2 中断请求标志寄存器 2.2.1 TCON 寄存器 2.2.2 SCON 寄存器 三、中断允许与中断优先级的控制 3.1 中断允许寄存器 IE 3.2 中断优先级寄存器 IP 四、响应中断请求的条件 五、外部中断的触发…

深入理解java web分层架构的高内聚低耦合

​ 在软件开发中,构建一个高效、可维护且可扩展的应用系统一直是开发者追求的目标。分层架构和依赖注入(IOC)是实现这一目标的重要策略。本文将深入探讨三层架构的高内聚特性、低耦合的设计原则,以及如何通过IOC(控制反…

FPGA开发——在线调试工具Signal Tap的使用

一、简介 在我们进行FPGA进行开发时通常都会经历代码编写,仿真,下板验证等过程。使用FPGA进行开发的小伙伴都知道,在代码编写时往往花费不了太长的时间,下板验证更是。在开发中占绝大部分时间的是仿真,有时候编写代码只…

基于Python的火车票售票系统/基于django的火车购票系统

摘 要 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代&…