Windows平台RTMP播放器/RTSP播放器如何在播放窗口添加OSD文字叠加

好多开发者在做Windows平台特别是单屏多画面显示时,希望像监控摄像机一样,可以在播放画面添加OSD台标,以实现字符叠加效果,大多开发者可很轻松的实现以上效果,针对此,本文以大牛直播SDK (Github)的Windows平台demo为例,简单介绍下具体实现:

Windows平台RTMP播放器、RTSP播放器C++ demo

Windows平台C++的demo,以录像过程为例,动态在左上角显示个闪动的图标+当前时间,具体效果如下:

核心代码

std::shared_ptr<nt_argb_image_logo> CSmartPlayerDlg::MakeLogo()
{std::shared_ptr<nt_argb_image_logo> logo_image;if (!is_init_gdi_plus_ok_)return logo_image;if (!recoder_image_){static bool is_load_image_failed = false;if (!is_load_image_failed){recoder_image_.reset(Gdiplus::Image::FromFile(_T("red_circle.png")));if (recoder_image_ && Gdiplus::Ok != recoder_image_->GetLastStatus()){is_load_image_failed = true;recoder_image_.reset();}}}is_has_recoder_image_ = !is_has_recoder_image_;if (!recoder_image_){is_has_recoder_image_ = false;}if (m_hWnd == nullptr || !::IsWindow(m_hWnd))return logo_image;if (cur_logo_font_name_.empty()){cur_logo_font_name_ = FindLogoFontName();}if (cur_logo_font_name_.empty()){return logo_image;}Gdiplus::FontFamily font_family(cur_logo_font_name_.c_str());if (!font_family.IsAvailable()){return logo_image;}Gdiplus::Font font(&font_family, 10, Gdiplus::FontStyleBold, Gdiplus::Unit::UnitPoint);if (!font.IsAvailable()){return logo_image;}// 白色Gdiplus::SolidBrush solid_brush(Gdiplus::Color(255, 255, 255));Gdiplus::Graphics  graphics(m_hWnd);if (Gdiplus::Ok != graphics.GetLastStatus()){return logo_image;}int recoder_image_w = 18;int recoder_image_h = 18;if (recoder_image_){recoder_image_w = recoder_image_->GetWidth();recoder_image_h = recoder_image_->GetHeight();}auto image_w = recoder_image_w + 2 + 5;auto image_h = recoder_image_h + 5 + 5;graphics.SetTextRenderingHint(Gdiplus::TextRenderingHint::TextRenderingHintClearTypeGridFit);auto cur_time_str = MakeCurTimerStr();Gdiplus::RectF bounding_box(0, 0, 0, 0);graphics.MeasureString(cur_time_str.c_str(), -1, &font, Gdiplus::PointF(0, 0), &bounding_box);Gdiplus::SizeF text_size(0, 0);bounding_box.GetSize(&text_size);image_w += (int)text_size.Width;image_h = image_h > ((int)text_size.Height) ? image_h : ((int)text_size.Height);image_w += 2;image_h += 2;image_w = ByteAlign(image_w, 4);image_h = ByteAlign(image_h, 4);Gdiplus::Bitmap   bitmap(image_w, image_h, PixelFormat32bppARGB);if (Gdiplus::Ok != bitmap.GetLastStatus()){return logo_image;}Gdiplus::Graphics g(&bitmap);if (Gdiplus::Ok != g.GetLastStatus()){return logo_image;}int r_left = 2;int r_top = (image_h / 2) - (recoder_image_h / 2);r_top -= 1;if (is_has_recoder_image_){g.DrawImage(recoder_image_.get(), r_left, r_top);}r_left += recoder_image_w;r_left += 5;r_top = (image_h / 2) - (text_size.Height / 2);g.DrawString(cur_time_str.c_str(), -1, &font, Gdiplus::PointF(r_left, r_top), &solid_brush);Gdiplus::BitmapData locked_bitmapData;if (Gdiplus::Ok == bitmap.LockBits(nullptr, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &locked_bitmapData)){auto buffer_size = locked_bitmapData.Stride * locked_bitmapData.Height;std::unique_ptr<NT_BYTE[]> buffer(new NT_BYTE[buffer_size]);if (buffer){logo_image = std::make_shared<nt_argb_image_logo>(locked_bitmapData.Width, locked_bitmapData.Height);logo_image->stride_ = locked_bitmapData.Stride;memcpy(buffer.get(), locked_bitmapData.Scan0, buffer_size);logo_image->data_.swap(buffer);}bitmap.UnlockBits(&locked_bitmapData);}return logo_image;
}

Windows平台RTMP播放器、RTSP播放器C# demo

Windows平台C#的demo,添加了“设置台标”选择框,在player窗口左上角显示“叠加字符展示”,具体内容、坐标可自定义,具体效果如下:

核心代码

        //设置OSD文本private void DrawOSD(string draw_text){// gdi 绘制的话,文本请自己绘制if (is_gdi_render_)return;if (player_handle_ == IntPtr.Zero)return;if (draw_text == null || draw_text.Length < 1){NTSmartPlayerSDK.NT_SP_SetRenderARGBLogo(player_handle_, IntPtr.Zero, 0, 0, 0, 0, 0, 0, 0);return;}Graphics graphics = this.CreateGraphics();SolidBrush solid_brush = new SolidBrush(Color.FromArgb(255, 255, 255));graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;SizeF text_size = new SizeF();text_size = graphics.MeasureString(draw_text, this.Font);int image_w = (int)text_size.Width + 4;int image_h = (int)text_size.Height + 4;image_w = (int)ByteAlign((UInt32)image_w, 4);image_h = (int)ByteAlign((UInt32)image_h, 4);Bitmap bmp = new Bitmap(image_w, image_h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);Graphics g = Graphics.FromImage(bmp);g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;float left = image_w / 2 - text_size.Width / 2;float top = image_h / 2 - text_size.Height / 2;g.DrawString(draw_text, this.Font, solid_brush, left, top);Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);System.Drawing.Imaging.BitmapData bmp_data = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);IntPtr ptr = bmp_data.Scan0;int strdie = Math.Abs(bmp_data.Stride);NTSmartPlayerSDK.NT_SP_SetRenderARGBLogo(player_handle_, ptr, strdie, bmp_data.Width,bmp_data.Height, 6, 6, bmp_data.Width, bmp_data.Height);// Unlock the bits.bmp.UnlockBits(bmp_data);}}

注意,如果GDI模式下,我们数据回调到上层绘制的,这样加起来更简单:

            if (btn_check_add_osd.Checked){string draw_text = "叠加字符展示";Graphics graphics = this.CreateGraphics();SolidBrush solid_brush = new SolidBrush(Color.FromArgb(255, 255, 255));graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;float left = playWnd.Left + 4;float top = playWnd.Top + 4;g.DrawString(draw_text, this.Font, solid_brush, left, top);}

感兴趣的开发者可自行尝试。

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

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

相关文章

Windows平台Unity3d下如何同时播放多路RTSP或RTMP流

好多开发者在做AR、VR或者教育类产品时&#xff0c;苦于如何在windows平台构建一个稳定且低延迟的RTSP或者RTMP播放器&#xff0c;如果基于Unity3d完全重新开发一个播放器&#xff0c;代价大、而且周期长&#xff0c;不适合快速出产品&#xff0c;我们认为当前最好的方式就是集…

Vscode —— 解决Vscode终端无法使用npm的命令的问题

在cmd中可以正常执行npm -v等指令,但是在vs code终端中,无法执行npm -v,node -v等指令 出现报错 解决办法&#x1f447; 方法一&#xff1a;【右键单击Vscode】以【管理员身份运行】&#xff0c;【重启Vscode】 方法二&#xff1a;①【用户变量】的【path】添加npm所在路径的…

浏览器播放RTSP视频流几种解决方案

方案一: H5 websocket_rtsp_proxy 实现视频流直播 Streamedian 提供了一种“html5_rtsp_player websock_rtsp_proxy”的技术方案&#xff0c;可以通过html5的video标签直接播放RTSP的视频流。 整个架构如下图所示&#xff0c;分为服务器端和浏览器端两部分&#xff1a; 方案…

如何用轻量级RTSP服务本地生成RTSP测试URL

最近发现好多开发者都在搜索可用的RTSP测试URL&#xff0c;目前公网实际可测试的RTSP URL非常少&#xff0c;即便是可用&#xff0c;分辨率和网络也非常差&#xff0c;不适合长期测试。 针对此&#xff0c;我们的建议是最好直接网上买个海康或大华的摄像头&#xff0c;一般来说…

Windows平台RTSP|RTMP播放端SDK集成说明

2.1 demo说明 大牛直播SDK提供C/C#两套接口&#xff0c;对外提供32/64位debug/release库&#xff0c;C和C#接口一一对应&#xff0c;C#接口比C接口增加前缀NT_PB_&#xff1b;WIN-PlayerSDK-CPP-Demo&#xff1a;播放端SDK对应的C接口的demo&#xff1b;WIN-PlayerSDK-CSharp-…

如何实现Android端获取RTSP|RTMP流转推RTMP

技术背景 最近不少开发者找到我们&#xff0c;他们在做智能家居等传统行业时&#xff0c;希望实现在Android板件拉取本地的RTSP或RTMP流&#xff0c;然后对外推送RTMP出去&#xff0c;亦或内部启个轻量级RTSP服务&#xff0c;提供个对外对接的媒介URL&#xff0c;简单来说&…

QT实现低延迟的RTSP、RTMP播放器

好多开发者在QT环境下实现RTMP或RTSP播放时&#xff0c;首先考虑到的是集成VLC&#xff0c;集成后&#xff0c;却发现VLC在延迟、断网重连、稳定性等各个方面不尽人意&#xff0c;无法满足上线环境需求。本文以调用大牛直播SDK&#xff08;官方&#xff09;的Windows平台播放端…

Android对接实现内网无纸化会议|智慧教室|实时同屏功能

背景 本文主要讲的是基于Android平台实现RTMP的技术方案设计&#xff0c;基础架构图如下&#xff1a; 组网注意事项 1. 组网&#xff1a;无线组网&#xff0c;需要好的AP模块才能撑得住大的并发流量&#xff0c;推送端到AP&#xff0c;最好是有线网链接&#xff1b; 2. 服务…

Windows平台RTMP推送|轻量级RTSP服务实现本地摄像头|屏幕|叠加数据预览

背景 大家在做Windows平台RTMP推送或轻量级RTSP服务的时候&#xff0c;不管是采集屏幕还是采集摄像头&#xff0c;亦或屏幕摄像头的叠加模式&#xff0c;总会有这样的诉求&#xff0c;采集到的数据&#xff0c;希望能本地看看具体采集的数据或者图像实际效果&#xff0c;也就是…

Windows平台RTMP|RTSP播放器为什么要兼容GDI绘制

为什么要支持GDI 先说结论&#xff0c;Windows平台播放渲染这块&#xff0c;一般来说99%以上的机器都是支持D3D的&#xff0c;实现GDI模式绘制&#xff0c;除了为了好的兼容性外&#xff0c;在远程连接的场景下&#xff0c;D3D创建不成功&#xff0c;需要使用GDI模式。 简单来…

Android平台实现Unity3D下RTMP推送

像Unity3D下的RTMP或RTSP播放器一样&#xff0c;好多开发者苦于在Unity环境下&#xff0c;如何高效率低延迟的把数据采集并编码实时推送到流媒体服务器&#xff0c;实现Unity场景下的低延迟推拉流方案。 关于屏幕采集&#xff0c;有两种方案&#xff1a; 1. 直接封装Android原…

Windows平台实现Unity下窗体|摄像头|屏幕采集推送

技术背景 随着Unity3D的应用范围越来越广&#xff0c;越来越多的行业开始基于Unity3D开发产品&#xff0c;如传统行业中虚拟仿真教育、航空工业、室内设计、城市规划、工业仿真等领域。 基于此&#xff0c;好多开发者苦于在Unity环境下&#xff0c;没有低延迟的推拉流解决方案…

数据推送选择GB28181、RTSP还是RTMP?

GB/T28181 国标GB/T28181协议全称《安全防范视频监控联网系统信息传输、交换、控制技术要求》&#xff0c;是一个定义视频联网传输和设备控制标准的白皮书&#xff0c;由公安部科技信息化局提出&#xff0c;该标准规定了城市监控报警联网系统中信息传输、交换、控制的互联结构…

Android平台基于RTMP或RTSP的一对一音视频互动技术方案探讨

背景 随着智能门禁等物联网产品的普及&#xff0c;越来越多的开发者对音视频互动体验提出了更高的要求。目前市面上大多一对一互动都是基于WebRTC&#xff0c;优点不再赘述&#xff0c;我们这里先说说可能需要面临的问题&#xff1a;WebRTC的服务器部署非常复杂&#xff0c;可…

Android前端音视频数据接入GB28181平台意义

技术背景 在我们研发Android平台GB28181前端音视频接入模块之前&#xff0c;业内听到最多的是&#xff0c;如何用Android或者Windows端&#xff0c;在没有国标IPC设备的前提下&#xff0c;模拟GB28181的信令和媒体流交互流程&#xff0c;实现GB28181整体方案的测试&#xff1f…

std::atomic和std::mutex区别

​std::atomic介绍​ ​模板类std::atomic是C11提供的原子操作类型&#xff0c;头文件 #include<atomic>。​在多线程调用下&#xff0c;利用std::atomic可实现数据结构的无锁设计。​​ ​和互斥量的不同之处在于&#xff0c;std::atomic原子操作&#xff0c;主要是保…

C++ std::remove/std::remove_if/erase用法探讨

​std::remove 不会改变输入vector/string的长度。其过程相当于去除指定的字符&#xff0c;剩余字符往前靠。后面的和原始字符保持一致。​ 需要注意的是&#xff0c;remove函数是通过覆盖移去的&#xff0c;如果容器最后一个值刚好是需要删除的&#xff0c;则它无法覆盖掉容器…

再谈NULL和nullptr(C++11)区别

在谈NULL和nullptr区别之前&#xff0c;我们先看段代码&#xff1a; #include "stdafx.h" #include <iostream>using namespace std; void func(void *p) {cout << "p is pointer " << p << endl; } void func(int num) {cout &l…

C++11新特性探索:原始字符串字面值(raw string literal)

原始字符串字面值(raw string literal)是C11引入的新特性。 原始字符串简单来说&#xff0c;“原生的、不加处理的”&#xff0c;字符表示的就是自己&#xff08;所见即所得&#xff09;&#xff0c;引号、斜杠无需 “\” 转义&#xff0c;比如常用的目录表示&#xff0c;引入…

Android国标接入终端实现GB28181实时位置(MobilePosition)上报

技术背景 在实现本文提到的Android平台国标GB28181接入终端的实时位置上报之前&#xff0c;之前已经完成了Android终端GB28181常规功能接入&#xff0c;采集到实时音视频数据&#xff0c;编码PS打包后&#xff0c;按需传到GB28281服务平台&#xff0c;媒体流支持最新GB28181-2…