飞道的博客

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

259人阅读  评论(0)

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

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

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

核心代码


  
  1. std::shared_ptr<nt_argb_image_logo> CSmartPlayerDlg::MakeLogo()
  2. {
  3. std:: shared_ptr<nt_argb_image_logo> logo_image;
  4. if (!is_init_gdi_plus_ok_)
  5. return logo_image;
  6. if (!recoder_image_)
  7. {
  8. static bool is_load_image_failed = false;
  9. if (!is_load_image_failed)
  10. {
  11. recoder_image_.reset(Gdiplus::Image::FromFile(_T( "red_circle.png")));
  12. if (recoder_image_ && Gdiplus::Ok != recoder_image_->GetLastStatus())
  13. {
  14. is_load_image_failed = true;
  15. recoder_image_.reset();
  16. }
  17. }
  18. }
  19. is_has_recoder_image_ = !is_has_recoder_image_;
  20. if (!recoder_image_)
  21. {
  22. is_has_recoder_image_ = false;
  23. }
  24. if (m_hWnd == nullptr || !::IsWindow(m_hWnd))
  25. return logo_image;
  26. if (cur_logo_font_name_.empty())
  27. {
  28. cur_logo_font_name_ = FindLogoFontName();
  29. }
  30. if (cur_logo_font_name_.empty())
  31. {
  32. return logo_image;
  33. }
  34. Gdiplus::FontFamily font_family(cur_logo_font_name_.c_str());
  35. if (!font_family.IsAvailable())
  36. {
  37. return logo_image;
  38. }
  39. Gdiplus::Font font(&font_family, 10, Gdiplus::FontStyleBold, Gdiplus::Unit::UnitPoint);
  40. if (!font.IsAvailable())
  41. {
  42. return logo_image;
  43. }
  44. // 白色
  45. Gdiplus::SolidBrush solid_brush(Gdiplus::Color(255, 255, 255));
  46. Gdiplus::Graphics graphics(m_hWnd);
  47. if (Gdiplus::Ok != graphics.GetLastStatus())
  48. {
  49. return logo_image;
  50. }
  51. int recoder_image_w = 18;
  52. int recoder_image_h = 18;
  53. if (recoder_image_)
  54. {
  55. recoder_image_w = recoder_image_->GetWidth();
  56. recoder_image_h = recoder_image_->GetHeight();
  57. }
  58. auto image_w = recoder_image_w + 2 + 5;
  59. auto image_h = recoder_image_h + 5 + 5;
  60. graphics.SetTextRenderingHint(Gdiplus::TextRenderingHint::TextRenderingHintClearTypeGridFit);
  61. auto cur_time_str = MakeCurTimerStr();
  62. Gdiplus::RectF bounding_box(0, 0, 0, 0);
  63. graphics.MeasureString(cur_time_str.c_str(), -1, &font, Gdiplus::PointF( 0, 0), &bounding_box);
  64. Gdiplus::SizeF text_size(0, 0);
  65. bounding_box.GetSize(&text_size);
  66. image_w += ( int)text_size.Width;
  67. image_h = image_h > (( int)text_size.Height) ? image_h : (( int)text_size.Height);
  68. image_w += 2;
  69. image_h += 2;
  70. image_w = ByteAlign(image_w, 4);
  71. image_h = ByteAlign(image_h, 4);
  72. Gdiplus::Bitmap bitmap(image_w, image_h, PixelFormat32bppARGB);
  73. if (Gdiplus::Ok != bitmap.GetLastStatus())
  74. {
  75. return logo_image;
  76. }
  77. Gdiplus::Graphics g(&bitmap);
  78. if (Gdiplus::Ok != g.GetLastStatus())
  79. {
  80. return logo_image;
  81. }
  82. int r_left = 2;
  83. int r_top = (image_h / 2) - (recoder_image_h / 2);
  84. r_top -= 1;
  85. if (is_has_recoder_image_)
  86. {
  87. g.DrawImage(recoder_image_.get(), r_left, r_top);
  88. }
  89. r_left += recoder_image_w;
  90. r_left += 5;
  91. r_top = (image_h / 2) - (text_size.Height / 2);
  92. g.DrawString(cur_time_str.c_str(), -1, &font, Gdiplus::PointF(r_left, r_top), &solid_brush);
  93. Gdiplus::BitmapData locked_bitmapData;
  94. if (Gdiplus::Ok == bitmap.LockBits( nullptr, Gdiplus::ImageLockModeRead, PixelFormat32bppARGB, &locked_bitmapData))
  95. {
  96. auto buffer_size = locked_bitmapData.Stride * locked_bitmapData.Height;
  97. std::unique_ptr<NT_BYTE[]> buffer(new NT_BYTE[buffer_size]);
  98. if (buffer)
  99. {
  100. logo_image = std::make_shared<nt_argb_image_logo>(locked_bitmapData.Width, locked_bitmapData.Height);
  101. logo_image->stride_ = locked_bitmapData.Stride;
  102. memcpy(buffer.get(), locked_bitmapData.Scan0, buffer_size);
  103. logo_image->data_.swap(buffer);
  104. }
  105. bitmap.UnlockBits(&locked_bitmapData);
  106. }
  107. return logo_image;
  108. }

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

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

核心代码


  
  1. //设置OSD文本
  2. private void DrawOSD(string draw_text)
  3. {
  4. // gdi 绘制的话,文本请自己绘制
  5. if (is_gdi_render_)
  6. return;
  7. if (player_handle_ == IntPtr.Zero)
  8. return;
  9. if (draw_text == null || draw_text.Length < 1)
  10. {
  11. NTSmartPlayerSDK.NT_SP_SetRenderARGBLogo(player_handle_, IntPtr.Zero, 0, 0, 0, 0, 0, 0, 0);
  12. return;
  13. }
  14. Graphics graphics = this.CreateGraphics();
  15. SolidBrush solid_brush = new SolidBrush(Color.FromArgb( 255, 255, 255));
  16. graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
  17. SizeF text_size = new SizeF();
  18. text_size = graphics.MeasureString(draw_text, this.Font);
  19. int image_w = ( int)text_size.Width + 4;
  20. int image_h = ( int)text_size.Height + 4;
  21. image_w = ( int)ByteAlign((UInt32)image_w, 4);
  22. image_h = ( int)ByteAlign((UInt32)image_h, 4);
  23. Bitmap bmp = new Bitmap(image_w, image_h, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  24. Graphics g = Graphics.FromImage(bmp);
  25. g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
  26. float left = image_w / 2 - text_size.Width / 2;
  27. float top = image_h / 2 - text_size.Height / 2;
  28. g.DrawString(draw_text, this.Font, solid_brush, left, top);
  29. Rectangle rect = new Rectangle( 0, 0, bmp.Width, bmp.Height);
  30. System.Drawing.Imaging.BitmapData bmp_data = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
  31. IntPtr ptr = bmp_data.Scan0;
  32. int strdie = Math.Abs(bmp_data.Stride);
  33. NTSmartPlayerSDK.NT_SP_SetRenderARGBLogo(player_handle_, ptr, strdie, bmp_data.Width,
  34. bmp_data.Height, 6, 6, bmp_data.Width, bmp_data.Height);
  35. // Unlock the bits.
  36. bmp.UnlockBits(bmp_data);
  37. }
  38. }

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


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

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


转载:https://blog.csdn.net/renhui1112/article/details/114262358
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场