好多开发者在做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);
-
}
感兴趣的开发者可自行尝试。
转载:https://blog.csdn.net/renhui1112/article/details/114262358
查看评论