如何实现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);
}
感兴趣的开发者可自行尝试。
如何实现Windows平台RTMP播放器/RTSP播放器播放窗口添加OSD文字叠加的更多相关文章
- Windows平台RTMP/RTSP播放器实现实时音量调节
为什么要做实时音量调节 RTMP或RTSP直播播放音量调节,主要用于多实例(多窗口)播放场景下,比如同时播放4路RTMP或RTSP流,如果音频全部打开,几路audio同时打开,可能会影响用户体验,我们 ...
- Windows平台摄像头或屏幕RTMP推送介绍:OBS VS SmartPublisher
好多开发者问道,既然有了OBS,你们为什么还要开发SmartPublisher? 的确,在我们进行Windows平台RTMP推送模块开发之前,市面上为数不多的Windows平台RTMP推流工具当属OB ...
- Windows平台Unity3d播放多路RTMP或RTSP流
好多开发者在做AR.VR或者教育类产品时,苦于如何在windows平台构建一个稳定且低延迟的RTSP或者RTMP播放器,如果基于Unity3d完全重新开发一个播放器,代价大.而且周期长,不适合快速出产 ...
- Android平台RTMP/RTSP播放器开发系列--解码和绘制
本文主要抛砖引玉,粗略介绍下Android平台RTMP/RTSP播放器中解码和绘制相关的部分(Github). 解码 提到解码,大家都知道软硬解,甚至一些公司觉得硬解码已经足够通用,慢慢抛弃软解了,如 ...
- EasyPlayer-RTSP播放器:从底层到上层专注于RTSP播放Windows、Android、iOS RTSP Player
EasyPlayer-RTSP播放器是一套RTSP专用的播放器,包括有:Windows(支持IE插件,npapi插件).Android.iOS三个平台,是由EasyDSS团队开发和维护的区别于市面上大 ...
- 搭建rtmp直播流服务之4:videojs和ckPlayer开源播放器二次开发(播放rtmp、hls直播流及普通视频)
前面几章讲解了使用 nginx-rtmp搭建直播流媒体服务器; ffmpeg推流到nginx-rtmp服务器; java通过命令行调用ffmpeg实现推流服务; 从数据源获取,到使用ffmpeg推流, ...
- javaCV开发详解之4:转流器实现(也可作为本地收流器、推流器,新增添加图片及文字水印,视频图像帧保存),实现rtsp/rtmp/本地文件转发到rtmp流媒体服务器(基于javaCV-FFMPEG)
javaCV系列文章: javacv开发详解之1:调用本机摄像头视频 javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG.j ...
- 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
- 快速构建Windows 8风格应用21-构建简单媒体播放器
原文:快速构建Windows 8风格应用21-构建简单媒体播放器 本篇博文主要介绍如何构建一个简单的媒体播放器. <快速构建Windows 8风格应用20-MediaElement>博文中 ...
随机推荐
- Windows-VS2017创建.NET项目
首先新建->项目 选择如下, 注意要选择.NET Framework4.x 选择对应的项目类型 建议选上Web窗体(如果是用于实验的话) 完成后进行测试 如果出现 HTTP Error 403. ...
- nifi从入门到实战(保姆级教程)——身份认证
上一篇我们搭建好了nifi的运行环境了 但是每次登陆那一串随机字符串的用户名和密码是不是让人很头疼,那是人类能记住的吗?当然不是!!!! 那么今天我们就来消灭这些难看又难记的字符串. windows( ...
- UiPath参数介绍和使用
一.参数介绍 用于将数据从一个项目传递到另一个项目.在全局意义上,它们类似于变量,因为它们动态地存储数据并传递给它.变量在活动之间传递数据,而参数在自动化之间传递数据.因此,它们使你能够一次又一次地重 ...
- LVGL库入门教程 - 动画
动画可以说是 LVGL 中的特色之一,不过在使用动画前,请确保单片机具有足够的性能来维持足够的帧率. transition:过渡动画 当一个控件的状态发生改变时,可以让样式也发生变化以提醒用户.通过过 ...
- 通过input的name属性取值
HTML中 Script中 根据选中的值,res也就拿到相应的值.
- P1189 SEARCH—搜索
将这题加进来的原因 因为他的优化令人眼前一新! 题目传送门() 相似的题目之 血色先锋队 ↑这一题也要用到标记数组 优化!!! 对于一个位置, 如果他在同样的深度再一次被访问,那他接下来所走的路径,所 ...
- 如何让照片中的人物笑起来?HMS Core视频编辑服务一键微笑功能,让人物笑容更自然
最近一键"露齿笑"席卷全网,无论是短视频用户还是社交App用户都在使用这项黑科技.当三两好友聚会拍集体照留念时,为了处理个别人的表情"瑕疵",让大家都尽量保持微 ...
- 金瓯无缺江河一统|Win10系统基于Docker和Python3搭建并维护统一认证系统OpenLdap
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_180 OpenLdap(Lightweight Directory Access Protocol)是什么?它其实是一个开源的.具 ...
- Java8新特性: CompletableFuture详解
CompletableFuture实现了CompletionStage接口和Future接口,前者是对后者的一个扩展,增加了异步回调.流式处理.多个Future组合处理的能力,使Java在处理多任务的 ...
- 【web自动化测试】playwright安装失败怎么办
在安装中,如果没有输入 playwright install, 则不会安装浏览器,运行 playwright codegen 时会报浏览器找不到的错误: "chromium" br ...