ffmpeg面向对象-rtsp拉流相关对象
目录
- 1.AVFormatContext和FFFormatContext类。
- 1.1 概述
- 1.2 构造函数
- 1.3 oopc的继承实现
- 2. AVInputFormat 类。
- 2.1 多态的实现
- 3.所用设计模式
- 3.1模板模式
- 3.2 工厂模式?
- 3.3 rtsp拉流建链
- 4.this指针
- 5.小结
- 6.rtsp拉流流程
1.AVFormatContext和FFFormatContext类。
1.1 概述
ffmpeg5.x以后,把AVFormatContext类进行了拆分,把用户需要看到的共性部分抽取为父类AVFormatContext类,把用户用不到/不需要知道的剩余部分变成了子类FFFormatContext类——隐藏用户不用关心的内容。
5.x以后,实例化流对象FFFormatContext,然后返回给用户可见的基类AVFormatContext指针。
其他的函数调用就是以FFFormatContext这个类为中心,实质是实例化这个类(初始化,构造函数)、调用这个类的方法,最后销毁这个类对象。
比如拉流的必经流程:
avformat_open_input
av_read_frame
avformat_close_input
很明显的对应构造,调用方法和析构函数。
1.2 构造函数
rtsp拉流第一步都是avformat_open_input,同时也是流对象FFFormatContext的构造函数。
AVFormatContext *fmt_ctx = NULL;
result = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL);
其中fmt_ctx 如何分配内存的?如下
int avformat_open_input(AVFormatContext **ps, const char *filename,const AVInputFormat *fmt, AVDictionary **options)
{AVFormatContext *s = *ps;FFFormatContext *si;AVDictionary *tmp = NULL;ID3v2ExtraMeta *id3v2_extra_meta = NULL;int ret = 0;if (!s && !(s = avformat_alloc_context()))
……
}
avformat_alloc_context来给fmt_ctx 分配内存的,看它实质分配的内存有多大:
AVFormatContext *avformat_alloc_context(void)
{FFFormatContext *const si = av_mallocz(sizeof(*si));AVFormatContext *s;if (!si)return NULL;s = &si->pub;s->av_class = &av_format_context_class;s->io_open = io_open_default;s->io_close = ff_format_io_close_default;s->io_close2= io_close2_default;av_opt_set_defaults(s);si->pkt = av_packet_alloc();si->parse_pkt = av_packet_alloc();if (!si->pkt || !si->parse_pkt) {avformat_free_context(s);return NULL;}si->shortest_end = AV_NOPTS_VALUE;return s;
}
1.3 oopc的继承实现
可以看到它实际分配的内存是FFFormatContext这么大的,但是返回的地址是AVFormatContext *类型的,缩小了。这就是典型的oopc的接口继承。
FFFormatContext类如下实现:
typedef struct FFFormatContext {/*** The public context.*/AVFormatContext pub;/*** Number of streams relevant for interleaving.* Muxing only.*/int nb_interleaved_streams;……
}
oopc的继承实现是结构体套结构体。如上结构体,FFFormatContext继承自AVFormatContext。
同时可以看到它的特点,一般父类都是作为子类第一个成员,这样方便强转更改访问权限。
FFFormatContext第1个成员就是父类AVFormatContext的成员,把它命名为pub——注释中说是public公共上下文——公共的——这就是面向对象中常用的抽象出的基类的基本方法。
所谓接口继承,就是创建子类返父类的地址,这是多态实现的基础。
oopc中,这种继承是个老套路,也是经典套路,linux中,还有rtthread RTOS的内核实现中常用这种套路,这个应该是oopc的经典。
对应的对象图简略示意图如下:

2. AVInputFormat 类。
就像linux一切统一于文件,ffmpeg的一切拉流输入格式统一于AVInputFormat类——对所有拉流输入格式进行了抽象——体现了面向对象的抽象与多态——不同子类的方法不同,在oopc中就是采用函数指针实现。
什么意思?在代码上,说的“子类”具体代码体现在demuxer_list指针数组——定义在libavformat/demuxer_list.c中——该文件是编译FFMPEG configure的时候生成的(也就是说下载的源码中是没有的,config时才生成),举例生成的数组如下:
static const AVInputFormat * const demuxer_list[] = {&ff_aa_demuxer,&ff_aac_demuxer,&ff_ac3_demuxer,&ff_acm_demuxer,&ff_act_demuxer,&ff_adf_demuxer,&ff_adp_demuxer,&ff_ads_demuxer,&ff_adx_demuxer,&ff_aea_demuxer,&ff_afc_demuxer,&ff_aiff_demuxer,&ff_aix_demuxer,&ff_amr_demuxer,&ff_amrnb_demuxer,&ff_amrwb_demuxer,&ff_anm_demuxer,&ff_apc_demuxer,&ff_ape_demuxer,&ff_apng_demuxer,&ff_aptx_demuxer,&ff_aptx_hd_demuxer,&ff_aqtitle_demuxer,&ff_asf_demuxer,&ff_asf_o_demuxer,&ff_ass_demuxer,&ff_ast_demuxer,&ff_au_demuxer,&ff_avi_demuxer,&ff_avr_demuxer,&ff_avs_demuxer,&ff_bethsoftvid_demuxer,&ff_bfi_demuxer,&ff_bintext_demuxer,&ff_bink_demuxer,&ff_bit_demuxer,&ff_bmv_demuxer,&ff_bfstm_demuxer,&ff_brstm_demuxer,&ff_boa_demuxer,&ff_c93_demuxer,&ff_caf_demuxer,&ff_cavsvideo_demuxer,&ff_cdg_demuxer,&ff_cdxl_demuxer,&ff_cine_demuxer,&ff_codec2_demuxer,&ff_codec2raw_demuxer,&ff_concat_demuxer,&ff_data_demuxer,&ff_daud_demuxer,&ff_dcstr_demuxer,&ff_dfa_demuxer,&ff_dirac_demuxer,&ff_dnxhd_demuxer,&ff_dsf_demuxer,&ff_dsicin_demuxer,&ff_dss_demuxer,&ff_dts_demuxer,&ff_dtshd_demuxer,&ff_dv_demuxer,&ff_dvbsub_demuxer,&ff_dvbtxt_demuxer,&ff_dxa_demuxer,&ff_ea_demuxer,&ff_ea_cdata_demuxer,&ff_eac3_demuxer,&ff_epaf_demuxer,&ff_ffmetadata_demuxer,&ff_filmstrip_demuxer,&ff_fits_demuxer,&ff_flac_demuxer,&ff_flic_demuxer,&ff_flv_demuxer,&ff_live_flv_demuxer,&ff_fourxm_demuxer,&ff_frm_demuxer,&ff_fsb_demuxer,&ff_g722_demuxer,&ff_g723_1_demuxer,&ff_g726_demuxer,&ff_g726le_demuxer,&ff_g729_demuxer,&ff_gdv_demuxer,&ff_genh_demuxer,&ff_gif_demuxer,&ff_gsm_demuxer,&ff_gxf_demuxer,&ff_h261_demuxer,&ff_h263_demuxer,&ff_h264_demuxer,&ff_hevc_demuxer,&ff_hls_demuxer,&ff_hnm_demuxer,&ff_ico_demuxer,&ff_idcin_demuxer,&ff_idf_demuxer,&ff_iff_demuxer,&ff_ilbc_demuxer,&ff_image2_demuxer,&ff_image2pipe_demuxer,&ff_image2_alias_pix_demuxer,&ff_image2_brender_pix_demuxer,&ff_ingenient_demuxer,&ff_ipmovie_demuxer,&ff_ircam_demuxer,&ff_iss_demuxer,&ff_iv8_demuxer,&ff_ivf_demuxer,&ff_ivr_demuxer,&ff_jacosub_demuxer,&ff_jv_demuxer,&ff_lmlm4_demuxer,&ff_loas_demuxer,&ff_lrc_demuxer,&ff_lvf_demuxer,&ff_lxf_demuxer,&ff_m4v_demuxer,&ff_matroska_demuxer,&ff_mgsts_demuxer,&ff_microdvd_demuxer,&ff_mjpeg_demuxer,&ff_mjpeg_2000_demuxer,&ff_mlp_demuxer,&ff_mlv_demuxer,&ff_mm_demuxer,&ff_mmf_demuxer,&ff_mov_demuxer,&ff_mp3_demuxer,&ff_mpc_demuxer,&ff_mpc8_demuxer,&ff_mpegps_demuxer,&ff_mpegts_demuxer,&ff_mpegtsraw_demuxer,&ff_mpegvideo_demuxer,&ff_mpjpeg_demuxer,&ff_mpl2_demuxer,&ff_mpsub_demuxer,&ff_msf_demuxer,&ff_msnwc_tcp_demuxer,&ff_mtaf_demuxer,&ff_mtv_demuxer,&ff_musx_demuxer,&ff_mv_demuxer,&ff_mvi_demuxer,&ff_mxf_demuxer,&ff_mxg_demuxer,&ff_nc_demuxer,&ff_nistsphere_demuxer,&ff_nsp_demuxer,&ff_nsv_demuxer,&ff_nut_demuxer,&ff_nuv_demuxer,&ff_ogg_demuxer,&ff_oma_demuxer,&ff_paf_demuxer,&ff_pcm_alaw_demuxer,&ff_pcm_mulaw_demuxer,&ff_pcm_f64be_demuxer,&ff_pcm_f64le_demuxer,&ff_pcm_f32be_demuxer,&ff_pcm_f32le_demuxer,&ff_pcm_s32be_demuxer,&ff_pcm_s32le_demuxer,&ff_pcm_s24be_demuxer,&ff_pcm_s24le_demuxer,&ff_pcm_s16be_demuxer,&ff_pcm_s16le_demuxer,&ff_pcm_s8_demuxer,&ff_pcm_u32be_demuxer,&ff_pcm_u32le_demuxer,&ff_pcm_u24be_demuxer,&ff_pcm_u24le_demuxer,&ff_pcm_u16be_demuxer,&ff_pcm_u16le_demuxer,&ff_pcm_u8_demuxer,&ff_pjs_demuxer,&ff_pmp_demuxer,&ff_pva_demuxer,&ff_pvf_demuxer,&ff_qcp_demuxer,&ff_r3d_demuxer,&ff_rawvideo_demuxer,&ff_realtext_demuxer,&ff_redspark_demuxer,&ff_rl2_demuxer,&ff_rm_demuxer,&ff_roq_demuxer,&ff_rpl_demuxer,&ff_rsd_demuxer,&ff_rso_demuxer,&ff_rtp_demuxer,&ff_rtsp_demuxer,&ff_s337m_demuxer,&ff_sami_demuxer,&ff_sap_demuxer,&ff_sbc_demuxer,&ff_sbg_demuxer,&ff_scc_demuxer,&ff_sdp_demuxer,&ff_sdr2_demuxer,&ff_sds_demuxer,&ff_sdx_demuxer,&ff_segafilm_demuxer,&ff_shorten_demuxer,&ff_siff_demuxer,&ff_sln_demuxer,&ff_smacker_demuxer,&ff_smjpeg_demuxer,&ff_smush_demuxer,&ff_sol_demuxer,&ff_sox_demuxer,&ff_spdif_demuxer,&ff_srt_demuxer,&ff_str_demuxer,&ff_stl_demuxer,&ff_subviewer1_demuxer,&ff_subviewer_demuxer,&ff_sup_demuxer,&ff_svag_demuxer,&ff_swf_demuxer,&ff_tak_demuxer,&ff_tedcaptions_demuxer,&ff_thp_demuxer,&ff_threedostr_demuxer,&ff_tiertexseq_demuxer,&ff_tmv_demuxer,&ff_truehd_demuxer,&ff_tta_demuxer,&ff_txd_demuxer,&ff_tty_demuxer,&ff_ty_demuxer,&ff_v210_demuxer,&ff_v210x_demuxer,&ff_vag_demuxer,&ff_vc1_demuxer,&ff_vc1t_demuxer,&ff_vivo_demuxer,&ff_vmd_demuxer,&ff_vobsub_demuxer,&ff_voc_demuxer,&ff_vpk_demuxer,&ff_vplayer_demuxer,&ff_vqf_demuxer,&ff_w64_demuxer,&ff_wav_demuxer,&ff_wc3_demuxer,&ff_webm_dash_manifest_demuxer,&ff_webvtt_demuxer,&ff_wsaud_demuxer,&ff_wsd_demuxer,&ff_wsvqa_demuxer,&ff_wtv_demuxer,&ff_wve_demuxer,&ff_wv_demuxer,&ff_xa_demuxer,&ff_xbin_demuxer,&ff_xmv_demuxer,&ff_xvag_demuxer,&ff_xwma_demuxer,&ff_yop_demuxer,&ff_yuv4mpegpipe_demuxer,&ff_image_bmp_pipe_demuxer,&ff_image_dds_pipe_demuxer,&ff_image_dpx_pipe_demuxer,&ff_image_exr_pipe_demuxer,&ff_image_j2k_pipe_demuxer,&ff_image_jpeg_pipe_demuxer,&ff_image_jpegls_pipe_demuxer,&ff_image_pam_pipe_demuxer,&ff_image_pbm_pipe_demuxer,&ff_image_pcx_pipe_demuxer,&ff_image_pgmyuv_pipe_demuxer,&ff_image_pgm_pipe_demuxer,&ff_image_pictor_pipe_demuxer,&ff_image_png_pipe_demuxer,&ff_image_ppm_pipe_demuxer,&ff_image_psd_pipe_demuxer,&ff_image_qdraw_pipe_demuxer,&ff_image_sgi_pipe_demuxer,&ff_image_svg_pipe_demuxer,&ff_image_sunrast_pipe_demuxer,&ff_image_tiff_pipe_demuxer,&ff_image_webp_pipe_demuxer,&ff_image_xpm_pipe_demuxer,&ff_image_xwd_pipe_demuxer,NULL };
ffmpeg支持的每一个输入格式都统一抽象为AVInputFormat类,支持的每个输入格式都实例化一个AVInputFormat对象出来(oopc就是变量或全局变量),然后放到这个指针数组中——聚合到一起了。
而AVFormatContext的成员iformat就是AVInputFormat类的指针,它就是匹配到上面指针数组里的成员的呢!那么如何匹配的呢?通过av_demuxer_iterate循环遍历指针数组demuxer_list拿到的。
具体调用链如下:
avformat_open_input => init_input => av_probe_input_format2 => av_probe_input_format3 => av_demuxer_iterate。
const AVInputFormat *av_demuxer_iterate(void **opaque)
{static const uintptr_t size = sizeof(demuxer_list)/sizeof(demuxer_list[0]) - 1;uintptr_t i = (uintptr_t)*opaque;const AVInputFormat *f = NULL;uintptr_t tmp;if (i < size) {f = demuxer_list[i];} else if (tmp = atomic_load_explicit(&indev_list_intptr, memory_order_relaxed)) {const AVInputFormat *const *indev_list = (const AVInputFormat *const *)tmp;f = indev_list[i - size];}if (f)*opaque = (void*)(i + 1);return f;
}
2.1 多态的实现
这样,av_demuxer_iterate循环遍历libavformat/demuxer_list.c中的demuxer_list数组,AVFormatContext的成员iformat就匹配到了指针数组demuxer_list中的成员。
ffmpeg在各个格式的c文件中定义了AVInputFormat类的对象(全局变量),最后被加入到demuxer_list数组中。这样实现多态。
这里比如rtsp拉流,输入是“rtsp:”的形式,它会匹配到ff_rtsp_demuxer这个全局变量(通过调用read_probe)——定义在libavformat/rtspdec.c中:
const AVInputFormat ff_rtsp_demuxer = {.name = "rtsp",.long_name = NULL_IF_CONFIG_SMALL("RTSP input"),.priv_data_size = sizeof(RTSPState),.read_probe = rtsp_probe,.read_header = rtsp_read_header,.read_packet = rtsp_read_packet,.read_close = rtsp_read_close,.read_seek = rtsp_read_seek,.flags = AVFMT_NOFILE,.read_play = rtsp_read_play,.read_pause = rtsp_read_pause,.priv_class = &rtsp_demuxer_class,
};
AVInputFormat类抽象的这些方法包括:
探测或者称之为辨识是不是本格式的方法probe,
读头信息,读取包数据,等等。把各种格式都抽象统一于此,这样同样的子类但是方法不同,实现了多态。
3.所用设计模式
3.1模板模式
接着统一的操作如下:

当然不仅仅这一种统一操作——但是这种统一操作,不管啥格式的,都走这个流程,这种设计模式是为模版模式。
avformat_open_input中的流程,可以说是对所有输入格式抽象出来的共性流程,这种提取出的共性流程,基本万古不变,变得只是函数指针指向或者参数配置,那么这种流程就像一个“模板”一样,这就是模板模式。
这种模式是常见的模式,因为行业固定,行业对应的业务流程基本能抽出共性的流程,那么随着代码的迭代,共性代码会自然出现,而不是因为“设计模式”才出现模板模式,而是因为这样的代码出现了,对它总结,起个名字叫“模板模式”。设计模式来源于现成代码的概念抽象和总结。
3.2 工厂模式?
从上面AVFormatContext的成员iformat匹配对应的AVInputFormat这种行为,有点类似策略模式(但是策略模式的特点是运行中可以更改算法,但这里不是,初始化完毕就不能动了),又有点像工厂模式,工厂模式会根据不同格式创建不同类,和这个有点异曲同工,也有解析的部分,解析到哪类就实例化哪类。我更倾向于它这种解析匹配子类对象地址的方式是工厂模式。
不管了,反正记住一点,设计模式是对现有代码的抽象,先有代码,再有提出对应设计模式的概念。
3.3 rtsp拉流建链
AVFormatContext的成员iformat匹配到合适的全局变量后,
有个统一操作
s->iformat->read_header(s)。
在rtsp拉流对象对应的就是ff_rtsp_demuxer中的rtsp_read_header,如下实现
static int rtsp_read_header(AVFormatContext *s)
{RTSPState *rt = s->priv_data;int ret;if (rt->initial_timeout > 0)rt->rtsp_flags |= RTSP_FLAG_LISTEN;if (rt->rtsp_flags & RTSP_FLAG_LISTEN) {ret = rtsp_listen(s);if (ret)return ret;} else {ret = ff_rtsp_connect(s);if (ret)return ret;rt->real_setup_cache = !s->nb_streams ? NULL :av_calloc(s->nb_streams, 2 * sizeof(*rt->real_setup_cache));if (!rt->real_setup_cache && s->nb_streams) {ret = AVERROR(ENOMEM);goto fail;}rt->real_setup = rt->real_setup_cache + s->nb_streams;if (rt->initial_pause) {/* do not start immediately */} else {ret = rtsp_read_play(s);if (ret < 0)goto fail;}}return 0;fail:rtsp_read_close(s);return ret;
}
可以看到很关键,包含了rtsp协议链接到完成。
4.this指针
看下oopc是如何模拟this指针的。
再次突出强调下,rtsp拉流对象是FFFormatContext——对用户看到的是其基类AVFormatContext指针——this指针。
FFFormatContext这个就是流对象。this指针实质指向的就是这个流对象的地址。
看下前面的调用
avformat_open_input
av_read_frame
avformat_close_input
它们几个的第一个形参都是流对象的基类指针。
还有其内部调用方法形式:

s->iformat->read_header(s),
它模拟的就是面向对象的如下形式:
对象指针->对象方法(形参1,形参2,…)
因为面向对象的this指针是默认参数(c++是this,python是self),代码中不需要显式调用,但是oopc中this指针只能如上形式进行显式调用。
而且,还能发现AVInputFormat对所有格式抽象的方法第一个形参都是AVFormatContext指针,这就是this指针,这里this指针指的就是FFFormatContext的基类对象指针。
再看下av_read_frame这个调用,它第一个形参也是这个this指针,内部怎么调用的呢?截取如下
int av_read_frame(AVFormatContext *s, AVPacket *pkt)
{FFFormatContext *const si = ffformatcontext(s);……
ret = read_frame_internal(s, pkt);……
}
static int read_frame_internal(AVFormatContext *s, AVPacket *pkt)
{FFFormatContext *const si = ffformatcontext(s);
...while (!got_packet && !si->parse_queue.head) {AVStream *st;FFStream *sti;/* read next packet */ret = ff_read_packet(s, pkt);……}
int ff_read_packet(AVFormatContext *s, AVPacket *pkt)
{FFFormatContext *const si = ffformatcontext(s);for (;;) {
……err = s->iformat->read_packet(s, pkt);
……}
调用链一路到了ff_read_packet,最终到了如下调用:
s->iformat->read_packet(s, pkt);
和之前的形式一样,模拟了面向对象的方法调用形式,但是this指针需要显式调用。
另外AVFormatContext 基类指针怎么取到子类FFFormatContext 指针的呢?ffformatcontext(s)调用,如下
static av_always_inline FFFormatContext *ffformatcontext(AVFormatContext *s)
{return (FFFormatContext*)s;
}
很显然,就是强转改变访问权限,不像c++需要维护虚表,运行时选择。因为c没有这个机制,只能这样子,当然linux内核没有做的这么方便,用的是内核第一宏container_of()根据成员地址推算结构体指针,这样父类可以不放到子类结构体的第一个成员。
5.小结
发散下思维,想下面向对象语言的拉流代码怎么写?
伪代码:
s=new 拉流对象;
while(1)
{
s->读数据方法(packet);
}
delete s;
oopc模拟的话,类使用结构体表示的,继承一般采用结构体套结构体的形式,多态采用函数指针形式。
拉流结构体 s;
s.方法(s指针即this指针,形参1,形参2,...)
ffmpeg拉流呢,就是模拟的这样,比如创建FFFormatContext类对象,然后返回其父类指针,然后调用AVFormatContext的拉流方法:
s->iformat->read_packet(s, pkt);
其他的方法都是以这个流对象为中心,实质是对流对象进行操作——构造、析构、方法调用。这个方法包含了各种格式,编码、解码、转换,这个流对象就是中心操作对象——流对象内部存放了百宝箱——有数据有方法——这就是面向对象的类对象。这样化繁为简,统一操作。
如果你学过一门面向对象语言,只要掌握基础的类定义,继承,封装,接口类等基础语法,还有了解下智能指针,再看这个ffmpeg代码或者rtthreadrtos内核源码,那么就会感觉无缝衔接,如果了解过oopc的套路,更加无缝衔接。
如果再学下设计模式,那就能看到设计模式。
设计模式是现有代码再由人总结出来的概念。
6.rtsp拉流流程
很多博客有,不再赘述。
如下
https://blog.csdn.net/baidu_41388533/article/details/112728029
https://www.cnblogs.com/caiyingyong/p/16947075.html
https://blog.csdn.net/u013692429/article/details/101698740
相关文章:
ffmpeg面向对象-rtsp拉流相关对象
目录 1.AVFormatContext和FFFormatContext类。1.1 概述1.2 构造函数1.3 oopc的继承实现 2. AVInputFormat 类。2.1 多态的实现 3.所用设计模式3.1模板模式3.2 工厂模式? 3.3 rtsp拉流建链 4.this指针5.小结6.rtsp拉流流程 1.AVFormatContext和FFFormatContext类。 …...
feign client发送Post请求,发送对象参数,服务端接收不到正确参数报错排查
记一次feignclient发送请求服务端接收不到正确参数排查 服务端代码: Operation(summary "Create team")PostMapping("post")RequiresPermissions("team:add")public RestResponse addTeam(Valid Team team) {this.teamService.crea…...
Hadoop林子雨安装
文章目录 hadoop安装教程注意事项: hadoop安装教程 链接: 安装教程 注意事项: 可以先安装ububtu增强功能,完成共享粘贴板和共享文件夹 ubuntu增强功能 2.这里就可以使用共享文件夹 或者在虚拟机浏览器,用 微信文件传输助手 传文…...
Springboot项目总结
1.为了调用写在其他包里面的类的方法 但是不使用new来实现调用这个类里面的方法,这个时候我们就需要将这个类注入到ioc容器里面,通过ioc容器来实现自动生成一个对象。 对ioc容器的理解:自动将一个对象实现new. 考察了and 和 or组合使用&…...
目标检测从入门到精通——数据增强方法总结
以下是YOLO系列算法(从YOLOv1到YOLOv7)中使用的数据增强方法的总结,包括每种方法的数学原理、相关论文以及对应的YOLO版本。 YOLO系列数据增强方法总结 数据增强方法数学原理相关论文图像缩放将输入图像缩放到固定大小(如448x44…...
SQL server 的异常处理 一个SQL异常 如何不影响其他SQL执行
在 SQL Server 中,存储过程中的 SQL 语句是顺序执行的。如果其中任何一个 SQL 语句遇到了错误或异常,那么默认情况下,这个错误会导致整个事务(如果有的话)回滚,并且存储过程会立即停止执行,不会…...
STM32——看门狗通俗解析
笔者在学习看门狗的视频后,对看门狗仍然是一知半解,后面在实际应用中发现它是一个很好用的检测或者调试工具。所以总结一下笔者作为初学小白对看门狗的理解。 主函数初始化阶段、循环阶段和复位 众所周知,程序的运行一般是这样的࿱…...
点亮第一盏LED灯 5): stm32CubeMX生成Keil代码
嵌入式入门,继续点亮第一盏LED灯,前面文章已经配置了GPIO引脚和时钟,那么基本上stm32CubeMX的配置就完成了,还有一点就是可以对PC13这个引脚起个别名, 这里起的别名是 LED_PC13,还有注意地方就是GPIO mode…...
ollama语言大模型部署使用
ollama语言大模型部署使用 前言一、下载安装maxkb1、下载解压赋权2、安装 二、安装ollamadocker运行 三、无需获取api_keymaxkb安装ollama模型对,就是这,你选好基础模型后,只需要给他地址,添加完成后自行调用ollama安装你选择好的…...
redis 基本数据类型—string类型
一、介绍 Redis 中的字符串,直接就是按照二进制数据的方式存储的,不会做任何的编码转换。 Redis对于 string 类型,限制了大小最大是512M 二、命令 SET 将 string 类型的 value 设置到 key 中。如果 key 之前存在,则覆盖&#…...
Git 使用教程:从入门到精通
Git 是一个开源的分布式版本控制系统,由 Linus Torvalds 创建,用于有效、高速地处理从小到大的项目版本管理。本教程将带你从 Git 的安装开始,逐步学习到如何使用 Git 进行日常的版本控制操作。 安装 Git Windows 访问 Git 官方网站 下载 …...
ES查询的一些优化方式
ES查询的一些优化方式 filter和query Query会计算得分,filte不是, 整体上query会更耗时 字段方式: KEYWORD 和 text, Text检索的方式往往会占用更多性能,它往往需要伴随着模糊匹配和分词 分页的大小 From 和size的大小合理设置…...
计算左边(比自己小的元素)的最长距离
前言:一般做的题目都是使用单调栈来求出距离这个点最近的那个比这个数大或小的元素,但是如果是需要找到最远的那个元素呢?我们可以用到类似逆序对的思路,我们先进行排序从小到大,接着我们先处理左边,每次维…...
【C++算法】二分查找
二分查找 题目链接 二分查找https://leetcode.cn/problems/binary-search/ 算法原理 代码步骤 代码展示 class Solution { public:int search(vector<int>& nums, int target) {int left 0, right nums.size() - 1;while(left < right){// 防止溢出int mid …...
红日靶场通关
初始准备 首先是网络配置,看教程来的,我配置完的效果如下 windows7:(内:192.168.52.143 / 外:192.168.154.136) windows2003:(内:192.168.52.141)windows2008:(内:192.…...
用Python爬虫制作一个简易翻译器
我们通常是通过requestsBS4的方法来获取网页内容,这种方法导入模块较多,速度相对有点儿慢,此时我们可以用requests的post方法向指定服务器发送请求,获取数据后格式化为json,然后获取相关键值。这种方法用到了requests和…...
Shader Graph Create Node
一、Artistic 1、Adjustment 1)、Channel Mixer(通道混合) 根据权重对每个通道进行混合。 Contrast(对比度) 可调整对比度 调整对比度可以改变图像的鲜明度和层次感。增加对比度会使图像中的明暗差异更加显著,使图像看起来更加清晰、明亮;减少对比…...
共模干扰的形成和滤除
1、共模就是共同对地的干扰: 如图,我们可以看到共模的原理图。UPQ就是共模电压,ICM1 ICM2 就是共模电流。 ICM1 ICM2 大小不一定相同,方向相同。 2、共模信号和差模信号的区别: 通常电源线有三根线:火线L、…...
(计算机网络)运输层
一.运输层的作用 运输层:负责将数据统一的交给网络层 实质:进程在通信 TCP(有反馈)UDP(无反馈) 二.复用和分用 三. TCP和UDP的特点和区别 进程号--不是固定的 端口号固定--mysql--3306 端口--通信的终点 …...
基于深度学习的信号滤波:创新技术与应用挑战
一、引言 1.1 研究背景 随着科技的不断发展,信号处理领域面临着越来越复杂的挑战。在众多信号处理技术中,基于深度学习的信号滤波技术逐渐崭露头角,成为研究的热点。 基于深度学习的信号滤波在信号处理领域具有至关重要的地位。如今&#…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
