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

2023-03-15:屏幕录制并且显示视频,不要用命令。代码用go语言编写。

2023-03-15:屏幕录制并且显示视频,不要用命令。代码用go语言编写。

答案2023-03-15:

使用moonfdd/ffmpeg-go和moonfdd/sdl2-go库来实现屏幕录制并显示视频,大体流程如下:

1.使用libavdevice库中的AVInputFormat(输入格式)、AVDeviceCapabilitiesQuery(设备能力查询)和AVFormatContext(格式上下文)获取桌面录制器的设备信息。
2.使用libavcodec库中的AVCodec、AVCodecContext、AVFrame和AVPacket结构体编码和解码视频帧。
3.使用libavutil库中的函数分配内存空间,并创建一个SwsContext(色彩空间转换上下文)对象,以及SDL库中的窗口和渲染器对象。
4.在循环中,读取屏幕捕获器的每一帧数据并将其解码。然后,直接将YUV420P格式的图像传递给SDL库中的渲染器进行显示。

代码调用了以下结构体:

AVInputFormat
AVDeviceCapabilitiesQuery
AVFormatContext
AVCodec
AVCodecContext
AVFrame
AVPacket
SwsContext
SDL窗口对象
SDL渲染器对象

释放资源的步骤包括:

1.关闭SDL渲染器和窗口。
2.释放AVFrame和AVPacket对象。
3.关闭libavcodec库中的AVCodecContext。
4.关闭libavformat库中的AVFormatContext。
5.关闭libavdevice库中的AVInputFormat。
6.释放libavutil库中的内存空间。

代码见github.com/moonfdd/ffmpeg-go-examples。

执行命令:

go run ./examples/leixiaohua1020/simplest_ffmpeg_grabdesktop/main.go

代码参考了雷霄骅的屏幕录制并播放显示,代码用golang编写。代码如下:

// https://github.com/leixiaohua1020/simplest_ffmpeg_device/blob/master/simplest_ffmpeg_grabdesktop/simplest_ffmpeg_grabdesktop.cpp
package mainimport ("fmt""os""time""unsafe""github.com/moonfdd/ffmpeg-go/ffcommon""github.com/moonfdd/ffmpeg-go/libavcodec""github.com/moonfdd/ffmpeg-go/libavdevice""github.com/moonfdd/ffmpeg-go/libavformat""github.com/moonfdd/ffmpeg-go/libavutil""github.com/moonfdd/ffmpeg-go/libswscale"sdl "github.com/moonfdd/sdl2-go/sdl2""github.com/moonfdd/sdl2-go/sdlcommon"
)// Output YUV420P
const OUTPUT_YUV420P = 0// '1' Use Dshow
// '0' Use GDIgrab
const USE_DSHOW = 0// Refresh Event
const SFM_REFRESH_EVENT = (sdl.SDL_USEREVENT + 1)
const SFM_BREAK_EVENT = (sdl.SDL_USEREVENT + 2)var thread_exit ffcommon.FInt = 0
var ispush = truefunc sfp_refresh_thread(opaque ffcommon.FVoidP) uintptr {// thread_exit = 0for thread_exit == 0 {var event sdl.SDL_Eventevent.Type = SFM_REFRESH_EVENTif ispush {event.SDL_PushEvent()ispush = false}sdl.SDL_Delay(40)}fmt.Println("sfp_refresh_thread 发送退出事件")// thread_exit = 0//Breakvar event sdl.SDL_Eventevent.Type = SFM_BREAK_EVENTevent.SDL_PushEvent()return 0
}// Show Dshow Device
func show_dshow_device() {pFormatCtx := libavformat.AvformatAllocContext()var options *libavutil.AVDictionarylibavutil.AvDictSet(&options, "list_devices", "true", 0)iformat := libavformat.AvFindInputFormat("dshow")fmt.Printf("========Device Info=============\n")libavformat.AvformatOpenInput(&pFormatCtx, "video=dummy", iformat, &options)fmt.Printf("================================\n")
}// Show AVFoundation Device
func show_avfoundation_device() {pFormatCtx := libavformat.AvformatAllocContext()var options *libavutil.AVDictionarylibavutil.AvDictSet(&options, "list_devices", "true", 0)iformat := libavformat.AvFindInputFormat("avfoundation")fmt.Printf("==AVFoundation Device Info===\n")libavformat.AvformatOpenInput(&pFormatCtx, "", iformat, &options)fmt.Printf("=============================\n")
}func main0() (ret ffcommon.FInt) {var pFormatCtx *libavformat.AVFormatContextvar i, videoindex ffcommon.FIntvar pCodecCtx *libavcodec.AVCodecContextvar pCodec *libavcodec.AVCodecvar ifmt *libavformat.AVInputFormatlibavformat.AvRegisterAll()libavformat.AvformatNetworkInit()pFormatCtx = libavformat.AvformatAllocContext()//Open File//char filepath[]="src01_480x272_22.h265";//avformat_open_input(&pFormatCtx,filepath,NULL,NULL)//Register Devicelibavdevice.AvdeviceRegisterAll()//Windowsif USE_DSHOW != 0 {//Use dshow////Need to Install screen-capture-recorder//screen-capture-recorder//Website: http://sourceforge.net/projects/screencapturer///ifmt = libavformat.AvFindInputFormat("dshow")if libavformat.AvformatOpenInput(&pFormatCtx, "video=screen-capture-recorder", ifmt, nil) != 0 {fmt.Printf("Couldn't open input stream1.\n")return -1}} else {//Use gdigrabvar options *libavutil.AVDictionary//Set some options//grabbing frame rate//av_dict_set(&options,"framerate","5",0);//The distance from the left edge of the screen or desktop//av_dict_set(&options,"offset_x","20",0);//The distance from the top edge of the screen or desktop//av_dict_set(&options,"offset_y","40",0);//Video frame size. The default is to capture the full screen//av_dict_set(&options,"video_size","640x480",0);// libavutil.AvDictSet(&options, "probesize", "100000000", 0)ifmt = libavformat.AvFindInputFormat("gdigrab")if libavformat.AvformatOpenInput(&pFormatCtx, "desktop", ifmt, &options) != 0 {fmt.Printf("Couldn't open input stream2.\n")return -1}}if pFormatCtx.AvformatFindStreamInfo(nil) < 0 {fmt.Println("Couldn't find stream information.")return -1}videoindex = -1for i = 0; i < int32(pFormatCtx.NbStreams); i++ {if pFormatCtx.GetStream(uint32(i)).Codec.CodecType == libavutil.AVMEDIA_TYPE_VIDEO {videoindex = ibreak}}if videoindex == -1 {fmt.Printf("Didn't find a video stream.\n")return -1}pCodecCtx = pFormatCtx.GetStream(uint32(videoindex)).CodecpCodec = libavcodec.AvcodecFindDecoder(pCodecCtx.CodecId)if pCodec == nil {fmt.Printf("Codec not found.\n")return -1}if pCodecCtx.AvcodecOpen2(pCodec, nil) < 0 {fmt.Printf("Could not open codec.\n")return -1}var pFrame, pFrameYUV *libavutil.AVFramepFrame = libavutil.AvFrameAlloc()pFrameYUV = libavutil.AvFrameAlloc()//unsigned char *out_buffer=(unsigned char *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));//avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);out_buffer := (*byte)(unsafe.Pointer(libavutil.AvMalloc(uint64(libavcodec.AvpictureGetSize(int32(libavutil.AV_PIX_FMT_YUV420P), pCodecCtx.Width, pCodecCtx.Height)))))((*libavcodec.AVPicture)(unsafe.Pointer(pFrameYUV))).AvpictureFill(out_buffer, libavutil.AV_PIX_FMT_YUV420P, pCodecCtx.Width, pCodecCtx.Height)//SDL----------------------------// if sdl.SDL_Init(sdl.SDL_INIT_VIDEO|sdl.SDL_INIT_AUDIO|sdl.SDL_INIT_TIMER) != 0 {if sdl.SDL_Init(sdl.SDL_INIT_VIDEO) != 0 {fmt.Printf("Could not initialize SDL - %s\n", sdl.SDL_GetError())return -1}var screen_w, screen_h ffcommon.FInt = 640, 360var mode *sdl.SDL_DisplayMode = new(sdl.SDL_DisplayMode)if sdl.SDL_GetCurrentDisplayMode(0, mode) != 0 {fmt.Printf("SDL: could not get current display mode - exiting:%s\n", sdl.SDL_GetError())return -1}//Half of the Desktop's width and height.screen_w = mode.W / 2screen_h = mode.H / 2window := sdl.SDL_CreateWindow("Simplest FFmpeg Grab Desktop", sdl.SDL_WINDOWPOS_UNDEFINED, sdl.SDL_WINDOWPOS_UNDEFINED, screen_w, screen_h, 0)if window == nil {fmt.Printf("SDL: could not create window - exiting:%s\n", sdl.SDL_GetError())return -1}defer window.SDL_DestroyWindow()renderer := window.SDL_CreateRenderer(-1, 0)if renderer == nil {fmt.Printf("SDL: could not create renderer - exiting:%s\n", sdl.SDL_GetError())return -1}defer renderer.SDL_DestroyRenderer()texture := renderer.SDL_CreateTexture(sdl.SDL_PIXELFORMAT_YV12,sdl.SDL_TEXTUREACCESS_STREAMING,pCodecCtx.Width,pCodecCtx.Height)defer texture.SDL_DestroyTexture()window.SDL_ShowWindow()time.Sleep(2 * time.Second)var rect sdl.SDL_Rectrect.X = 0rect.Y = 0rect.W = screen_wrect.H = screen_hvar rect2 sdl.SDL_Rectrect2.X = 0rect2.Y = 0rect2.W = mode.Wrect2.H = mode.H//SDL End------------------------// var got_picture ffcommon.FInt//AVPacket *packet=(AVPacket *)av_malloc(sizeof(AVPacket));packet := &libavcodec.AVPacket{}var fp_yuv *os.Fileif OUTPUT_YUV420P != 0 {fp_yuv, _ = os.Create("output.yuv")}var img_convert_ctx *libswscale.SwsContextimg_convert_ctx = libswscale.SwsGetContext(pCodecCtx.Width, pCodecCtx.Height, pCodecCtx.PixFmt, pCodecCtx.Width, pCodecCtx.Height, libavutil.AV_PIX_FMT_YUV420P, libswscale.SWS_BICUBIC, nil, nil, nil)//------------------------------//video_tid := sdl.SDL_CreateThread(sfp_refresh_thread, nil)//go sfp_refresh_thread(uintptr(0))//sdl.SDL_CreateThread(sfp_refresh_thread, "", uintptr(0))//Event Loopvar event sdl.SDL_Eventfor {//Waitispush = trueevent.SDL_WaitEvent()if event.Type == SFM_REFRESH_EVENT {//------------------------------if pFormatCtx.AvReadFrame(packet) >= 0 {if int32(packet.StreamIndex) == videoindex {if pCodecCtx.AvcodecSendPacket(packet) < 0 {packet.AvPacketUnref()continue}ret = pCodecCtx.AvcodecReceiveFrame(pFrame)if ret < 0 {fmt.Printf("Decode Error.\n")return -1}if ret >= 0 {// if got_picture != 0 {img_convert_ctx.SwsScale((**byte)(unsafe.Pointer(&pFrame.Data)), (*int32)(unsafe.Pointer(&pFrame.Linesize)), 0, uint32(pCodecCtx.Height), (**byte)(unsafe.Pointer(&pFrameYUV.Data)), (*int32)(unsafe.Pointer(&pFrameYUV.Linesize)))if OUTPUT_YUV420P != 0 {y_size := pCodecCtx.Width * pCodecCtx.Heightfp_yuv.Write(ffcommon.ByteSliceFromByteP(pFrameYUV.Data[0], int(y_size)))   //Yfp_yuv.Write(ffcommon.ByteSliceFromByteP(pFrameYUV.Data[1], int(y_size)/4)) //Ufp_yuv.Write(ffcommon.ByteSliceFromByteP(pFrameYUV.Data[2], int(y_size)/4)) //V}texture.SDL_UpdateYUVTexture(&rect2,pFrameYUV.Data[0], pFrameYUV.Linesize[0],pFrameYUV.Data[1], pFrameYUV.Linesize[1],pFrameYUV.Data[2], pFrameYUV.Linesize[2])renderer.SDL_RenderClear()renderer.SDL_RenderCopy(texture, nil, &rect)renderer.SDL_RenderPresent()}}packet.AvPacketUnref()} else {//Exit Threadthread_exit = 1fmt.Println("main 准备退出 1")}} else if event.Type == sdl.SDL_QUIT {thread_exit = 1fmt.Println("main 准备退出 2")} else if event.Type == SFM_BREAK_EVENT {fmt.Println("退出循环 3")break}}img_convert_ctx.SwsFreeContext()if OUTPUT_YUV420P != 0 {fp_yuv.Close()}sdl.SDL_Quit()libavutil.AvFree(uintptr(unsafe.Pointer(out_buffer)))libavutil.AvFree(uintptr(unsafe.Pointer(pFrame)))libavutil.AvFree(uintptr(unsafe.Pointer(pFrameYUV)))pCodecCtx.AvcodecClose()libavformat.AvformatCloseInput(&pFormatCtx)return 0
}func main() {os.Setenv("Path", os.Getenv("Path")+";./lib/windows/ffmpeg")ffcommon.SetAvutilPath("./lib/windows/ffmpeg/avutil-56.dll")ffcommon.SetAvcodecPath("./lib/windows/ffmpeg/avcodec-58.dll")ffcommon.SetAvdevicePath("./lib/windows/ffmpeg/avdevice-58.dll")ffcommon.SetAvfilterPath("./lib/windows/ffmpeg/avfilter-56.dll")ffcommon.SetAvformatPath("./lib/windows/ffmpeg/avformat-58.dll")ffcommon.SetAvpostprocPath("./lib/windows/ffmpeg/postproc-55.dll")ffcommon.SetAvswresamplePath("./lib/windows/ffmpeg/swresample-3.dll")ffcommon.SetAvswscalePath("./lib/windows/ffmpeg/swscale-5.dll")sdlcommon.SetSDL2Path("./lib/windows/sdl/SDL2.0.16.dll")genDir := "./out"_, err := os.Stat(genDir)if err != nil {if os.IsNotExist(err) {os.Mkdir(genDir, 0777) //  Everyone can read write and execute}}// go func() {// 	time.Sleep(1000)// 	exec.Command("./lib/ffplay.exe", "rtmp://localhost/publishlive/livestream").Output()// 	if err != nil {// 		fmt.Println("play err = ", err)// 	}// }()main0()
}

在这里插入图片描述

相关文章:

2023-03-15:屏幕录制并且显示视频,不要用命令。代码用go语言编写。

2023-03-15&#xff1a;屏幕录制并且显示视频&#xff0c;不要用命令。代码用go语言编写。 答案2023-03-15&#xff1a; 使用moonfdd/ffmpeg-go和moonfdd/sdl2-go库来实现屏幕录制并显示视频&#xff0c;大体流程如下&#xff1a; 1.使用libavdevice库中的AVInputFormat&…...

STM32外设-DMA

1. 简介 DMA(Direct Memory Access)—直接存储器存取&#xff0c;是单片机的一个外设&#xff0c;它的主要功能是用来搬数据&#xff0c;但是不需要占用 CPU&#xff0c;即在传输数据的时候&#xff0c; CPU 可以干其他的事情&#xff0c;好像是多线程一样。数据传输支持从外设…...

【面试题】面试官:如果后端给你 1w 条数据,你如何做展示?

最近一位朋友参加阿b的面试&#xff0c;然后面试官问了她这个问题&#xff0c;我问她咋写的&#xff0c;她一脸淡定的说&#xff1a;“虚拟列表。”大厂面试题分享 面试题库前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面…...

第十二届蓝桥杯省赛详解

试题A&#xff1a;空间 1B是8位&#xff0c;32位二进制数占用4B空间&#xff0c;1MB2^10KB2^20B 那么可以存放32位二进制数的个数为256*2^20*8/3267108864 试题B&#xff1a;卡片 分析&#xff1a;因为数据只有2021&#xff0c;所以直接模拟即可 结果为&#xff1a;3181&…...

ssh创建秘钥对

1. 使用ssh-keygen 生成秘钥对 [root6zix89b87qmvuv ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): 按回车键或设置密钥的存储路径 Enter passphrase (empty for no passphrase): 按回车键或设置密钥的存…...

JS中sort()方法返回值?

参考 https://segmentfault.com/q/1010000043489928 精辟解释 就是说 sort() 会修改原数组项的排序&#xff0c;sort() 结束后会返回一个数组结果&#xff0c;这个结果其实就是原数组。并不是说会返回一个新的数组。 原理讲解 JS 分为栈内存和堆内存&#xff0c;栈内存可以…...

07从零开始学Java之如何正确的编写Java代码?

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者前言在上一篇文章中&#xff0c;壹哥带领大家开始编写了第一个Java案例&#xff0c;在我们的cmd命令窗口中输出了”Hello World“这…...

Python学习笔记14:网络编程

网络编程 几个网络模块 模块socket # 简单的服务器 import socket s socket.socket() host socket.gethostname() port 1234 s.bind((host, port))s.listen(5) while True: c, addr s.accept() print(Got connection from, addr) c.send(Thank you for connecting)c.…...

初入了解——什么是VUE

个人简介&#xff1a;云计算网络运维专业人员&#xff0c;了解运维知识&#xff0c;掌握TCP/IP协议&#xff0c;每天分享网络运维知识与技能。座右铭&#xff1a;海不辞水&#xff0c;故能成其大&#xff1b;山不辞石&#xff0c;故能成其高。个人主页&#xff1a;小李会科技的…...

代码规范(C++)

1.命名规范 1.目录/文件 字母、数字、下划线构成&#xff0c;不同单词用下划线隔开。 2.函数/接口 小驼峰命名法。 3.命名空间 字母、数字、下划线构成&#xff0c;不同单词用下划线隔开&#xff0c;但是尽量只使用一个单词。 4.结构体/类 大驼峰命名法&#xff0c;不包…...

React教程详解四(hooks、pureComponent、Context通信、错误边界、children props与render props)

前言 hooks是react16.8.0版本新增加的新特性/新语法&#xff0c;最大的特点是可以在开发者在函数组件中使用state以及其它React特性&#xff0c;下面分别对其介绍&#xff5e; React.useState() state hook能让函数组件也可以拥有state状态&#xff0c;方便其进行state状态的…...

【Spring从成神到升仙系列 二】2023年再不会 IOC 源码,就要被淘汰了

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#x1f4d5;系列专栏&#xff1a;Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙…...

菜鸟的进阶--手写一个小型dubbo框架

1.rpc调用流程2.组件1.Redis注册中心3.编解码/序列化在本例的Netty通信中&#xff0c;由于每次调用rpc服务都要发送同一个类对象invoker&#xff0c;所以可以使用Protobuf。但是在接受方法调用结果的时候就不行了&#xff0c;因为我们无法提前确定对方方法返回结果的类型&#…...

js逆向爬取某音乐网站某歌手的歌曲

js逆向爬取某音乐网站某歌手的歌曲一、分析网站1、案例介绍2、寻找列表页Ajax入口&#xff08;1&#xff09;页面展示图。&#xff08;2&#xff09;寻找部分歌曲信息Ajax的token。&#xff08;3&#xff09;寻找歌曲链接&#xff08;4&#xff09;获取歌曲名称和id信息3、寻找…...

为什么软件测试面试了几个月都没有offer,从HR角度分析

首先&#xff0c;我觉得你在软件测试面试的过程中&#xff0c;逻辑比较混乱的最大一个原因是&#xff0c;说明你没有形成一个一个整体的体系。 导致你说的时候很多东西都杂乱无章。 我个人认为软件测试&#xff0c;其实开始首先进行的是一些需求的分析工作&#xff0c;之后呢…...

DC-7 靶场学习

文章目录信息搜集账号密码获取修改密码反弹shell得到flag信息搜集 首先获取目标ip。 arp-scan -l nmap -sP 192.168.28.0/24得到目标ip为&#xff1a; 192.168.28.139先访问页面。 翻译一下。 欢迎来到 DC-7DC-7引入了一些“新”概念&#xff0c;但我会让你弄清楚它们是什么…...

深入理解JavaScript的事件冒泡与事件捕获

前言JavaScript中提供了很多操作DOM的API。事件冒泡和事件捕获是指浏览器中处理DOM元素上事件的两种不同方式。事件冒泡和事件捕获都是JavaScript事件模型中的一部分&#xff0c;可以用来处理事件。对于这个问题&#xff0c;在实际开发中&#xff0c;并不是非常重要&#xff0c…...

格密码学习笔记(六):格中模运算

文章目录格中取模运算CVP和格的陪集致谢格中取模运算 定义&#xff08;格的基本区域&#xff09; P⊂Rn:{Px∣x∈L}\mathcal{P} \subset \mathbb{R}^n : \{ \mathcal{P} \bm{x} | \bm{x} \in \mathcal{L} \}P⊂Rn:{Px∣x∈L}是Rn\mathbb{R}^nRn的一种划分。 用P\mathcal{P}P对…...

【C++】非常重要的——多态

凡是面向对象的语言&#xff0c;都有三大特性&#xff0c;继承&#xff0c;封装和多态&#xff0c;但并不是只有这三个特性&#xff0c;是因为者三个特性是最重要的特性&#xff0c;那今天我们一起来看多态&#xff01; 目录 1.多态的概念 1.1虚函数 1.2虚函数的重写 1.3虚…...

发票账单很多?python助你批量完成数据提取

每天面对成堆的发票&#xff0c;无论是税务发票还是承兑单据&#xff0c;抑或是其他各类公司数据要从照片、PDF等不同格式的内容中提取&#xff0c;我们都有必要进行快速办公的能力提升。因此&#xff0c;我们的目标要求就十分明显了&#xff0c;首先要从图片中获取数据&#x…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...