ffmpeg+D3D实现的MFC音视频播放器,支持录像、截图、音视频播放、码流信息显示等功能
一、简介
本播放器是在vs2019下开发,通过ffmpeg实现拉流解码功能,通过D3D实现视频的渲染功能。截图功能采用libjpeg实现,可以截取jpg图片,图片的默认保存路径是在C:\MYRecPath中。录像功能采用封装好的类Mp4Record实现,在Mp4Record类中主要还是采用ffmpeg的相关函数方法进行mp4视频的录制。音频的播放采用DirectSound实现,将ffmpeg解码后的音频数据存储到DirectSound的buffer中,再调用DirectSound的play实现对音频的播放功能。码流信息的显示,通过D3D的文本绘制实现。本播放器提供源码下载,直接下载请点击最后的下载链接。
二、界面展示
三、相关代码
开始播放
int CVideoPlayer::StartPlay(const char* sUrl)
{m_bStop = false;m_nVideoIndex = -1;m_nAudioIndex = -1;int i = 0, res = 0, nValue = 0;char buf[64] = { 0 };m_bPlaying = false;AVStream* in_stream;_snprintf_s(m_sConnectUrl, sizeof(m_sConnectUrl), sizeof(m_sConnectUrl) - 1, "%s", sUrl);//av_register_all();avformat_network_init();AVDictionary* optionsDict = nullptr;av_dict_set(&optionsDict, "rtsp_transport", "tcp", 0);av_dict_set(&optionsDict, "stimeout", "5000000", 0);av_dict_set(&optionsDict, "buffer_size", "8192000", 0);av_dict_set(&optionsDict, "recv_buffer_size", "8192000", 0);m_lastReadPacktTime = av_gettime();m_pAVFmtCxt = avformat_alloc_context();m_pAVFmtCxt->interrupt_callback.opaque = this;m_pAVFmtCxt->interrupt_callback.callback = decodeInterruptCb;res = avformat_open_input(&m_pAVFmtCxt, m_sConnectUrl, NULL, &optionsDict);if (res < 0){myprint("avformat_open_input fail: %d", res);return -1;}if (!m_pAVFmtCxt){return -1;}m_pAVFmtCxt->probesize = 100 * 1024; m_pAVFmtCxt->max_analyze_duration = 1 * AV_TIME_BASE; res = avformat_find_stream_info(m_pAVFmtCxt, NULL);if (res < 0){myprint("error %x in avformat_find_stream_info\n", res);return -1;}av_dump_format(m_pAVFmtCxt, 0, m_sConnectUrl, 0);for (i = 0; i < m_pAVFmtCxt->nb_streams; i++){if (m_pAVFmtCxt->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){m_nVideoIndex = i;}else if (m_pAVFmtCxt->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {m_nAudioIndex = i;}myprint("m_pAVFmtCxt->streams[i]->codec->codec_type:%d", m_pAVFmtCxt->streams[i]->codecpar->codec_type);}//videoindex not findif (m_nVideoIndex == -1){myprint("can't find video stream.");return -1;}m_pCodec = avcodec_find_decoder(m_pAVFmtCxt->streams[m_nVideoIndex]->codecpar->codec_id);if (!m_pCodec){myprint("video decoder not found\n");return -1;}if (m_bSupportAudio && m_nAudioIndex != -1){myprint("start audio decoder \n");if (!m_pAudioCodecCxt)m_pAudioCodecCxt = avcodec_alloc_context3(NULL);auto pAudioCodecpar = m_pAVFmtCxt->streams[m_nAudioIndex]->codecpar;avcodec_parameters_to_context(m_pAudioCodecCxt, pAudioCodecpar);m_pAudioCodec = avcodec_find_decoder(pAudioCodecpar->codec_id);if (nullptr == m_pAudioCodec || nullptr == m_pAudioCodecCxt){myprint("audio decoder not found\n");return -1;}m_pSwrContext = swr_alloc_set_opts(0, av_get_default_channel_layout(m_channels_play),AV_SAMPLE_FMT_S16, m_nSampleRate, av_get_default_channel_layout(m_pAudioCodecCxt->channels),m_pAudioCodecCxt->sample_fmt, m_pAudioCodecCxt->sample_rate, 0,0);auto ret = swr_init(m_pSwrContext);if (ret < 0){myprint("Failed to swr_init(pSwrContext);");return -1;}if (InitDirectSound() == FALSE)m_bSupportAudio = false;}m_CodecId = m_pCodec->id;if(!m_pCodecCxt)m_pCodecCxt = avcodec_alloc_context3(NULL);avcodec_parameters_to_context(m_pCodecCxt, m_pAVFmtCxt->streams[m_nVideoIndex]->codecpar);if (m_pCodecCxt){if (m_pCodecCxt->width == 0 || m_pCodecCxt->height == 0){myprint("m_pCodecCxt->width:%d, m_pCodecCxt->height:%d", m_pCodecCxt->width, m_pCodecCxt->height);return -1;}}elsereturn -1;AVCodecContext* temp_codecctx = m_pCodecCxt;memcpy(temp_codecctx, m_pCodecCxt, sizeof(m_pCodecCxt));if (m_pCodecCxt->codec_type == AVMEDIA_TYPE_VIDEO){myprint("Soft Solution");avcodec_close(m_pCodecCxt);m_pCodecCxt = temp_codecctx;m_pCodecCxt->thread_count = 4;if (m_Dxva2D3DRender.InitD3DRender(m_showWnd, m_pCodecCxt->width, m_pCodecCxt->height) == false){myprint("InitD3DRender fail");}m_pOutBuffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, m_pCodecCxt->width, m_pCodecCxt->height, 1));if (nullptr == m_pOutBuffer)return -1;av_image_fill_arrays(m_pFrameBGR->data, m_pFrameBGR->linesize, m_pOutBuffer, AV_PIX_FMT_YUV420P, m_pCodecCxt->width, m_pCodecCxt->height, 1); //填充AVFrame数据缓冲m_pImgConvertCtx = sws_getContext(m_pCodecCxt->width, m_pCodecCxt->height, m_pCodecCxt->pix_fmt, m_pCodecCxt->width, m_pCodecCxt->height, AV_PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);if (nullptr == m_pImgConvertCtx)return -1;m_nActualWidth = m_pCodecCxt->width;m_nActualHeight = m_pCodecCxt->height;res = avcodec_open2(m_pCodecCxt, m_pCodec, NULL);if (res < 0){myprint("avcodec_open2 video fail error:%x", res);return -1;}}if (m_bSupportAudio && m_pAudioCodecCxt){if (m_pAudioCodecCxt->codec_type == AVMEDIA_TYPE_AUDIO){res = avcodec_open2(m_pAudioCodecCxt, m_pAudioCodec, NULL);if (res < 0){myprint("avcodec_open2 audio fail error:%x", res);avcodec_close(m_pAudioCodecCxt);return -1;}myprint("===Audio Message===");myprint(" bit_rate = %d ", m_pAudioCodecCxt->bit_rate);myprint(" sample_rate = %d ", m_pAudioCodecCxt->sample_rate);myprint(" channels = %d ", m_pAudioCodecCxt->channels);myprint(" code_name = %s ", m_pAudioCodecCxt->codec->name);myprint(" block_align = %d ", m_pAudioCodecCxt->block_align);}}m_pDecodeThread = (my_thread_t*)my_malloc(sizeof(my_thread_t));if (nullptr != m_pDecodeThread){m_bDecodeThreadRun = true;res = my_thread_create(m_pDecodeThread, ThreadDecode, this);if (res == -1){myprint("my_thread_create ThreadDecode failed res:%x", res);return -1;}}return 0;
}
停止播放
void CVideoPlayer::StopPlay()
{m_bPlaying = false;m_CaptureAudio.SetGrabAudioFrames(FALSE, NULL);m_CaptureAudio.Close();m_bStopAudio = true;while (!m_AudioPlayQue.empty()){m_AudioPlayQue.pop();}while (!m_AudioTalkQue.empty()){EnterCriticalSection(&m_talklock);m_AudioTalkQue.pop();LeaveCriticalSection(&m_talklock);}m_bDecodeThreadRun = false;if (m_pDecodeThread){my_thread_join(m_pDecodeThread);my_free(m_pDecodeThread);m_pDecodeThread = nullptr;}if (m_pAudioPlayThread) {SetEvent(m_event);if (m_pAudioPlayThread->handle) {my_thread_join(m_pAudioPlayThread);m_pAudioPlayThread->handle = nullptr;}}if (m_pDSBuffer8){m_pDSBuffer8->Stop();m_pDSBuffer8->Restore();}m_Dxva2D3DRender.UnitD3DRender();if (m_pCodecCxt){avcodec_close(m_pCodecCxt);}if (m_pAudioCodecCxt){avcodec_close(m_pAudioCodecCxt);}if (m_pSwrContext){swr_free(&m_pSwrContext);m_pSwrContext = nullptr;}if (m_pAVFmtCxt) {avformat_close_input(&m_pAVFmtCxt);avformat_free_context(m_pAVFmtCxt);m_pAVFmtCxt = nullptr;}}
解码线程
void CVideoPlayer::DecodeAndShow()
{if (m_pAVFmtCxt == nullptr || m_pCodecCxt == nullptr)return;AVPacket pkt = { 0 };m_bPlaying = true;uint8_t* pBuffer;bool bEnoughSpace = true;int nTimeCnt = 0;int res = 0;struct SwsContext* img_convert_ctx = nullptr;int nRectDrawWait = 0;bool bRecordLastIFrame = false;int num_av_read_frame_err = 0;int num_stream_index_err = 0;uint8_t * outData[2] = {0};outData[0] = (uint8_t*)av_malloc(1152 * 8);outData[1] = (uint8_t*)av_malloc(1152 * 8);uint8_t* pktdata;int pktsize;int len = 0;bool bPushAudioToQueue = false;m_bStopAudio = false;CRect ShowRect;AVFrame* pAvFrame = av_frame_alloc();if (nullptr == pAvFrame)return;AVFrame* pFrameRGB = av_frame_alloc();if (nullptr == pFrameRGB)return;int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, m_pCodecCxt->width, m_pCodecCxt->height, 1);pBuffer = (uint8_t*)av_malloc(numBytes);if (nullptr == pBuffer)return;av_image_fill_arrays(pFrameRGB->data,pFrameRGB->linesize, pBuffer, AV_PIX_FMT_RGB24, m_pCodecCxt->width, m_pCodecCxt->height, 1);img_convert_ctx = sws_getCachedContext(img_convert_ctx, m_pCodecCxt->width, m_pCodecCxt->height,m_pCodecCxt->pix_fmt, m_pCodecCxt->width, m_pCodecCxt->height, AV_PIX_FMT_RGB24, SWS_FAST_BILINEAR/*SWS_BICUBIC*/, NULL, NULL, NULL);//Audioif (m_bSupportAudio && m_pAudioPlayThread){res = my_thread_create(m_pAudioPlayThread, ThreadAudioPlay, this);if (res < 0)myprint("my_thread_create ThreadAudioPlay fail");}while (m_bDecodeThreadRun && !m_bQuit){if (m_bPause){Sleep(100);continue;}{if (m_bReconnect){myprint("bReConnect = true, break");break;}}m_lastReadPacktTime = av_gettime();if (av_read_frame(m_pAVFmtCxt, &pkt) >= 0){num_av_read_frame_err = 0;if (pkt.stream_index == m_nVideoIndex || pkt.stream_index == m_nAudioIndex){if (m_bRecord)//Record{if (nTimeCnt != 0 || (!bRecordLastIFrame && pkt.flags == AV_PKT_FLAG_KEY)) {if (m_sRecPath[0] != '\0' && nTimeCnt++ % 200 == 0){bEnoughSpace = CheckRemainSpace(m_sRecPath);if (bEnoughSpace == true){myprint("bEnoughSpace = true");}elsemyprint("bEnoughSpace = false");}m_nRecordCurrentTime = time(NULL);if ((m_nRecordCurrentTime - m_nRecordStartTime) >= (m_nRecordTime * 60)){myprint("Record Finsh!");stopRecord();}else if (bEnoughSpace == false){myprint("bEnoughSpace == false");stopRecord();}else{AVPacket* pPkt = av_packet_clone(&pkt);m_mp4Recorder.saveOneFrame(*pPkt, m_CodecId);av_packet_free(&pPkt);}}bRecordLastIFrame = pkt.flags == AV_PKT_FLAG_KEY;}elsenTimeCnt = 0;}if (pkt.stream_index == m_nVideoIndex){num_stream_index_err = 0;nTimeCnt = 0;if (pkt.flags == 1)bPushAudioToQueue = true;if (nullptr == m_pCodecCxt || nullptr == pAvFrame) {myprint("m_pCodecCxt == NULL || pAvFrame == NULL");break;}int gotvframe = 0;auto sd_ret = avcodec_send_packet(m_pCodecCxt, &pkt);if (sd_ret != 0 && sd_ret != AVERROR(EAGAIN)) {myprint("avcodec_send_packet err, rt=%d", sd_ret);enableReConnect();}else {while (gotvframe == 0 && !m_bQuit) {gotvframe = avcodec_receive_frame(m_pCodecCxt, pAvFrame);if (gotvframe == 0){try{GetShowRectSize(&ShowRect);}catch (const std::exception&){myprint("GetClientRect throw, error");break;}m_nCurPKSize = pkt.size; SetStreamInfoToD3d();if (pAvFrame->width != m_nActualWidth || pAvFrame->height != m_nActualHeight){myprint("video size change reconnect...");enableReConnect();m_nActualWidth = pAvFrame->width;m_nActualHeight = pAvFrame->height;av_packet_unref(&pkt);continue;}if (m_pImgConvertCtx && m_pFrameBGR && m_pOutBuffer && pAvFrame){sws_scale(m_pImgConvertCtx, (const uint8_t* const*)pAvFrame->data, pAvFrame->linesize, 0,m_pCodecCxt->height, m_pFrameBGR->data, m_pFrameBGR->linesize);{ try{int re = 5;for (int i = 0; m_bPlaying && re == 5 && i < 10; ++i) { // LockRect失败时重复尝试,最多10次re = m_Dxva2D3DRender.D3DSoftDisplayFrame(m_pOutBuffer, pAvFrame->width, pAvFrame->height, ShowRect);Sleep(1);}}catch (int re){myprint("m_Dxva2D3DRender.InitD3DRender again");if (m_Dxva2D3DRender.InitD3DRender(m_showWnd, m_pCodecCxt->width, m_pCodecCxt->height) == false){myprint("m_Dxva2D3DRender.InitD3DRender again fail");av_packet_unref(&pkt);continue;}}} }if (m_bCapture /*&& pkt.flags == 1*/ && img_convert_ctx){sws_scale(img_convert_ctx, (const uint8_t* const*)pAvFrame->data, pAvFrame->linesize, 0, m_pCodecCxt->height,pFrameRGB->data, pFrameRGB->linesize);SaveIFrameImage(pFrameRGB->data[0], m_pCodecCxt->width, m_pCodecCxt->height);m_bCapture = false;}}}}}else if (pkt.stream_index == m_nAudioIndex){num_stream_index_err = 0;if (m_bSupportAudio) {pktdata = pkt.data;pktsize = pkt.size;if (pktsize > 0){int gotframe = 0;if (nullptr == m_pAudioCodecCxt || nullptr == pAvFrame) {myprint("m_pAudioCodecCxt == NULL || pAvFrame == NULL");break;}len = avcodec_send_packet(m_pAudioCodecCxt, &pkt);if (len != 0 && len != AVERROR(EAGAIN)){pktsize = 0;myprint("avcodec_send_packet len < 0");break;}auto data_size = av_get_bytes_per_sample(m_pAudioCodecCxt->sample_fmt); if (data_size < 0) {myprint("Failed to calculate data size\n");break;}while (gotframe == 0 && !m_bQuit) {gotframe = avcodec_receive_frame(m_pAudioCodecCxt, pAvFrame);if (!gotframe){if (bPushAudioToQueue == true && m_bEnableAudio && !m_bStopAudio){audio_frame_t audioFrame;numBytes = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);auto dstNbSamples = av_rescale_rnd(pAvFrame->nb_samples,m_src_sample_rate,pAvFrame->sample_rate,AV_ROUND_ZERO);int data_size = 0;try{auto nb = swr_convert(m_pSwrContext,(uint8_t**)outData,dstNbSamples,(const uint8_t**)pAvFrame->data,pAvFrame->nb_samples);data_size = av_samples_get_buffer_size(nullptr, m_channels_play, nb, AV_SAMPLE_FMT_S16, 1);}catch (const std::exception&){m_bSupportAudio = false;myprint("swr_convert throw err, set m_bSupportAudio false");continue;}int copy_size = 0; int copy_ptr = 0; for (int isub = data_size; isub > 0; isub -= copy_size) {if (isub > m_audio_buffer_notify_size) {copy_size = m_audio_buffer_notify_size;copy_ptr = data_size - isub;}elsecopy_size = isub;audioFrame.data_size = copy_size;memcpy(audioFrame.data, outData[0] + copy_ptr, copy_size);EnterCriticalSection(&m_lock);m_AudioPlayQue.push(audioFrame);LeaveCriticalSection(&m_lock);}}}}}}}else if (++num_stream_index_err > 20) {myprint("pkt.stream_index unfind, %d",pkt.stream_index);enableReConnect();}av_packet_unref(&pkt);}else {if (++num_av_read_frame_err > 10) {myprint("num_av_read_frame_err is more than 10");enableReConnect();}}}if (m_bDecodeThreadRun) {myprint("m_bDecodeThreadRun is true");enableReConnect();}if (pAvFrame)av_free(pAvFrame);if (pFrameRGB)av_free(pFrameRGB);if (pBuffer)av_free(pBuffer);if (img_convert_ctx)sws_freeContext(img_convert_ctx);if (outData[0] && outData[1]){av_free(outData[0]);av_free(outData[1]);outData[0] = 0;outData[1] = 0;}
}
四、相关下载
链接: 可执行程序下载
链接: 源码下载
相关文章:

ffmpeg+D3D实现的MFC音视频播放器,支持录像、截图、音视频播放、码流信息显示等功能
一、简介 本播放器是在vs2019下开发,通过ffmpeg实现拉流解码功能,通过D3D实现视频的渲染功能。截图功能采用libjpeg实现,可以截取jpg图片,图片的默认保存路径是在C:\MYRecPath中。录像功能采用封装好的类Mp4Record实现,…...

【Flink】-- flink新版本发布:v2.0-preview1
目录 1、简介 2、非兼容变更 2.1、API 2.2、连接器适配计划 2.3、配置 2.4、其它 3、重要新特性 3.1、存算分离状态管理 3.2、物化表 3.3、批作业的自适应执行 3.4、流式湖仓 4、附加 4.1、非兼容性的 api 程序变更 4.1.2、Removed Classes # 4.1.3、Modified Cl…...

Node.js 版本管理的最终答案 Volta
文章目录 特点安装Unix系统安装Windows系统安装 常用命令volta fetchvolta installvolta uninstallvolta pinvolta listvolta completionsvolta whichvolta setupvolta runvolta help 建议 目前对于前端项目的node 版本,我们一般会在项目 package.json 的 engines 字…...

蓝桥杯每日真题 - 第11天
题目:(合并数列) 题目描述(14届 C&C B组D题) 解题思路: 题意理解:给定两个数组,目标是通过若干次合并操作使两个数组相同。每次合并操作可以将数组中相邻的两个数相加ÿ…...
Vue vs React:两大前端框架的区别解析
在现代前端开发中,Vue.js 和 React.js 是两个最受欢迎的框架和库。我们常常面临选择它们的困惑。虽然这两者在本质上都是为了构建用户界面而设计的,但它们在设计理念、使用方式和生态系统等方面有着显著的区别。今天,我们将通过深入分析这两个…...

【树莓派raspberrypi烧录Ubuntu远程桌面登入树莓派】
提示:本文利用的是Ubuntu主机和树莓派4B开发板,示例仅供参考 文章目录 一、树莓派系统安装下载前准备工作下载安装树莓派的官方烧录软件imagerimager的使用方法 二、主机与树莓SSH连接查看数梅派IP地址建立ssh连接更新树莓派源地址 三、主机端远程桌面配…...

c# 调用c++ 的dll 出现找不到函数入口点
今天在调用一个设备的dll文件时遇到了一点波折,因为多c 不熟悉,调用过程张出现了找不到函数入口点,一般我们使用c# 调用c 文件,还是比较简单。 [DllImport("AtnDll2.dll",CharSet CharSet.Ansi)]public static extern …...

LInux——环境基础开发工具使用(正在更新中...)
1.软件包管理器 Linux下安装软件的方案: 1. 源代码安装 2. rpm包安装 3. 包管理器安装 --- yum/ apt (此图片来自于比特就业课课件) 1.1 操作生态系统 好的操作系统定义: 生态环境好 不同的操作系统根本是生态不同(…...
linux 内核asmlinkage关键字总结
1,看一下asmlinkage的定义 CPP_ASMLINKAGE __attribute__((regparm(0))) GCC中使用__attribute__((regparm(n)))指定最多可以使用n个寄存器(eax, edx, ecx)传递参数,n的范围是0~3,超过n时则将参数压入栈中(…...
⚡️如何在 React 和 Next.js 项目里优雅的使用 Zustand
前言 你是否曾感觉在 React 中管理状态简直是一场噩梦?如果你已经厌倦了不停地处理 props、context 和 hooks,那么现在是时候认识 Zustand 了。Zustand 是一个轻量级的状态管理库,它简化了你处理应用状态的方式。在这篇文章中,我…...

Pinpoint(APM)进阶--Pinot指标采集(System Metric/Inspector)
接上文 Pinpoint使用Pinot进行指标数据存储,Pinot流摄入需要Kafka 本文详解Kafka和Pinot的安装部署,以及Pinpoint的指标采集 Pinot 简介 Apache Pinot是一个实时分布式OLAP数据存储,专为低延迟、高吞吐量分析而构建,非常适合面…...

Mysql:使用binlog的一些常用技巧
1、如何查看binlog的存放路径 show variables like log% 执行结果: 2、如何清除binlog (1)按时间清除 purge binary logs before ‘2023-06-5 10:12:00’ (2)按文件文件名清除 purge binary logs to ‘mybinlog.0000…...
Electron 项目启动外部可执行文件的几种方式
Electron 项目启动外部可执行文件的几种方式 序言 在开发 Electron 应用程序时,有时需要启动外部的可执行文件(如 .exe 文件)。这可能是为了调用系统工具、运行第三方软件或者集成现有的应用程序。 Electron 提供了多种方式来启动外部可执行…...

前端开发中常用的包管理器(npm、yarn、pnpm、bower、parcel)
文章目录 1. npm (Node Package Manager)2. Yarn (Yarn Package Manager)3. pnpm4. Bower5. Parcel总结 前端开发中常用的包管理器主要有以下几个: 1. npm (Node Package Manager) 简介: npm 是 Node.js 的默认包管理器,也是最广泛使用的包…...

Linux入门:环境变量与进程地址空间
一. 环境变量 1. 概念 1️⃣基本概念: 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数 如:我们在编写C/C代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里&#x…...

【Jenkins实战】Windows安装服务启动失败
写此篇短文,望告诫后人。 如果你之前装过Jenkins,出于换域账号/本地帐号的原因想重新安装,你大概率会遇上一次Jenkins服务启动失败提示: Jenkins failed to start - Verify that you have sufficient privileges to start system…...

web实操5——http数据详解,request对象功能
http请求数据 现在我们浏览器f12的那些是浏览器给http格式数据整理之后便于我们阅读的。 原始的http格式信息: 就是按照一定格式和符号的字符串: 请求行:格式如下图 请求头:一个个key,value数据,用,分割…...
C# 如何动态加载程序集
程序集的加载,默认是从当前目录下查找,如果当前目录查找不到,然后再去系统目录中查找,依然查找不到就会从环境变量中查找,如果依然找不到,则会抛出一个异常 FileNotFoundException。 托管代码中࿰…...
前端基础的讲解-JS(10)
作用域链 通过上节作用域我们知道,当我们声明一个函数时,程序会生成一个独立的作用域,如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域;根据 内部函数可以访问外部函数变量 的这种机制,用链…...
JNI整理总结
JNI JNI基础 JNI基础 JNI,java native interface,即java本地接口,是java调用本地化方法的接口,是为java编写本地方法,为jvm嵌入本地应用程序的标准化接口。首要目标是在给定的平台上采用java通过JNI调用本地化方法&am…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

保姆级教程:在无网络无显卡的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…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...