背景描述

在视频监控软件中,我们看到很多的软件都有电子放大功能, 按住鼠标左键不放,框选一个区域,再松开鼠标左键,即对选中的区域进行放大显示, 且可以重复该操作,逐步放大所需显示的区域, 有没有觉得,这个功能在视频监控软件中还是有他的用武地. 今天我们就来实现该功能;

实现流程

  1. //设置电子放大起起始点
  2. int SetElectronicZoomStartPoint(int channelId, float fXPercent, float fYPercent, unsigned char showBox);
  3. //设置电子放大结束点(在鼠标移动过程中可一直调用该函数)
  4. int SetElectronicZoomEndPoint(int channelId, float fXPercent, float fYPercent);
  5. //设置是否放大显示
  6. int SetElectronicZoom(int channelId, int zoomIn);
  7. //复位
  8. void ResetElectronicZoom(int channelId);
  9. //直接设置显示区域,用于电子放大, 在某些场合, 需要直接进行缩放显示, 即可调用该函数实现
  10. int SetRenderRect(int channelId, LPRECT lpSrcRect);

代码实现

  1. int ChannelManager::ElectronicZoomProcess(MEDIA_VIDEO_CHANNEL_OBJ_T *pMediaChannel, EASY_FRAME_INFO *frameInfo)
  2. {
  3. if (NULL == pMediaChannel) return 0;
  4. if (NULL == frameInfo) return 0;
  5. ELECTRONIC_ZOOM_T *pElectoricZoom = pMediaChannel->pElectoricZoom;
  6. if (NULL == pElectoricZoom) return 0;
  7. int nLeft = 0, nTop = 0, nRight = 0, nBottom = 0;
  8. if (pElectoricZoom->zoomIn >= 0x01)
  9. {
  10. RECT rcClient;
  11. GetClientRect(pMediaChannel->mediaDisplay.hWnd, &rcClient);
  12. float fLeftPercent = pElectoricZoom->fStartPointX;
  13. float fTopPercent = pElectoricZoom->fStartPointY;
  14. float fRightPercent = pElectoricZoom->fEndPointX;
  15. float fBottomPercent = pElectoricZoom->fEndPointY;
  16. if (fRightPercent > fLeftPercent && fBottomPercent > fTopPercent) //逐步放大
  17. {
  18. if (pElectoricZoom->fVideoWidth > 0)
  19. {
  20. int video_width = (int)pElectoricZoom->fVideoWidth;
  21. int video_height= (int)pElectoricZoom->fVideoHeight;
  22. nLeft = (int)((float)video_width / 100.0f * fLeftPercent);
  23. nTop = (int)((float)video_height/ 100.0f * fTopPercent);
  24. nRight = (int)((float)video_width / 100.0f * fRightPercent);
  25. nBottom = (int)((float)video_height/ 100.0f * fBottomPercent);
  26. if (nRight > nLeft && nBottom > nTop)
  27. {
  28. pElectoricZoom->fVideoWidth = (float)(nRight - nLeft);
  29. pElectoricZoom->fVideoHeight = (float)(nBottom - nTop);
  30. nLeft = pElectoricZoom->startVideoLeft + nLeft;
  31. nTop = pElectoricZoom->startVideoTop + nTop;
  32. nRight = pElectoricZoom->startVideoLeft + nRight;
  33. nBottom = pElectoricZoom->startVideoTop + nBottom;
  34. pElectoricZoom->startVideoLeft = nLeft;
  35. pElectoricZoom->startVideoTop = nTop;
  36. if (pElectoricZoom->zoomIndex + 1 <MAX_ZOOM_IN_TIMES)
  37. {
  38. SetRect(&pElectoricZoom->zoomParam[pElectoricZoom->zoomIndex].rect, nLeft, nTop, nRight, nBottom);
  39. pElectoricZoom->zoomParam[pElectoricZoom->zoomIndex].fVideoWidth = pElectoricZoom->fVideoWidth;
  40. pElectoricZoom->zoomParam[pElectoricZoom->zoomIndex].fVideoHeight = pElectoricZoom->fVideoHeight;
  41. pElectoricZoom->zoomParam[pElectoricZoom->zoomIndex].startVideoLeft = pElectoricZoom->startVideoLeft;
  42. pElectoricZoom->zoomParam[pElectoricZoom->zoomIndex].startVideoTop = pElectoricZoom->startVideoTop;
  43. pElectoricZoom->zoomIndex ++;
  44. }
  45. }
  46. else
  47. {
  48. int idx = pElectoricZoom->zoomIndex-2;
  49. if (idx > 0)
  50. {
  51. nLeft = pElectoricZoom->zoomParam[idx].rect.left;
  52. nTop = pElectoricZoom->zoomParam[idx].rect.top;
  53. nRight = pElectoricZoom->zoomParam[idx].rect.right;
  54. nBottom = pElectoricZoom->zoomParam[idx].rect.bottom;
  55. pElectoricZoom->fVideoWidth = pElectoricZoom->zoomParam[idx].fVideoWidth;
  56. pElectoricZoom->fVideoHeight = pElectoricZoom->zoomParam[idx].fVideoHeight;
  57. pElectoricZoom->startVideoLeft = pElectoricZoom->zoomParam[idx].startVideoLeft;
  58. pElectoricZoom->startVideoTop = pElectoricZoom->zoomParam[idx].startVideoTop;
  59. }
  60. }
  61. }
  62. else
  63. {
  64. int video_width = frameInfo->width;
  65. int video_height= frameInfo->height;
  66. nLeft = (int)((float)video_width / 100.0f * fLeftPercent);
  67. nTop = (int)((float)video_height/ 100.0f * fTopPercent);
  68. nRight = (int)((float)video_width / 100.0f * fRightPercent);
  69. nBottom = (int)((float)video_height/ 100.0f * fBottomPercent);
  70. pElectoricZoom->startVideoLeft = nLeft;
  71. pElectoricZoom->startVideoTop = nTop;
  72. pElectoricZoom->fVideoWidth = (float)(nRight - nLeft);
  73. pElectoricZoom->fVideoHeight = (float)(nBottom - nTop);
  74. SetRect(&pElectoricZoom->zoomParam[0].rect, nLeft, nTop, nRight, nBottom);
  75. pElectoricZoom->zoomParam[0].fVideoWidth = pElectoricZoom->fVideoWidth;
  76. pElectoricZoom->zoomParam[0].fVideoHeight = pElectoricZoom->fVideoHeight;
  77. pElectoricZoom->zoomParam[0].startVideoLeft = pElectoricZoom->startVideoLeft;
  78. pElectoricZoom->zoomParam[0].startVideoTop = pElectoricZoom->startVideoTop;
  79. pElectoricZoom->zoomIndex ++;
  80. }
  81. }
  82. else
  83. {
  84. if (pElectoricZoom->zoomIndex > 1)
  85. {
  86. int idx = pElectoricZoom->zoomIndex-2;
  87. nLeft = pElectoricZoom->zoomParam[idx].rect.left;
  88. nTop = pElectoricZoom->zoomParam[idx].rect.top;
  89. nRight = pElectoricZoom->zoomParam[idx].rect.right;
  90. nBottom = pElectoricZoom->zoomParam[idx].rect.bottom;
  91. pElectoricZoom->fVideoWidth = pElectoricZoom->zoomParam[idx].fVideoWidth;
  92. pElectoricZoom->fVideoHeight = pElectoricZoom->zoomParam[idx].fVideoHeight;
  93. pElectoricZoom->startVideoLeft = pElectoricZoom->zoomParam[idx].startVideoLeft;
  94. pElectoricZoom->startVideoTop = pElectoricZoom->zoomParam[idx].startVideoTop;
  95. pElectoricZoom->zoomIndex --;
  96. }
  97. else
  98. {
  99. pElectoricZoom->fVideoWidth = 0.0f;
  100. nLeft = 0;
  101. nTop = 0;
  102. nRight = frameInfo->width;
  103. nBottom = frameInfo->height;
  104. pElectoricZoom->zoomIndex = 0;
  105. }
  106. }
  107. RECT rcSrc;
  108. SetRect(&rcSrc, nLeft, nTop, nRight, nBottom);
  109. CopyRect(&pMediaChannel->mediaDisplay.rcSrcRender, &rcSrc);
  110. pElectoricZoom->zoomIn --;
  111. }
  112. return 0;
  113. }

关于EasyPlayerPro

EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP、RTMP、HTTP、HLS、UDP、RTP、File等多种流媒体协议播放、支持本地文件播放,支持本地抓拍、本地录像、播放旋转、多屏播放、倍数播放等多种功能特性,核心基于ffmpeg,稳定、高效、可靠、可控,支持Windows、Android、iOS三个平台,目前在多家教育、安防、行业型公司,都得到的应用,广受好评!

EasyPlayerPro:https://github.com/EasyDSS/EasyPlayerPro

点击链接加入群【EasyPlayer & EasyPlayerPro】:544917793

技术支持

EasyPlayerPro是一款非常稳定的全协议/全功能播放器组件,各平台版本需要经过授权才能商业使用,商业授权方案可以通过以上渠道进行更深入的技术与合作咨询;

获取更多信息

EasyDarwin开源流媒体服务器:www.EasyDarwin.org

EasyDSS商用流媒体解决方案:www.EasyDSS.com

EasyNVR无插件直播方案:www.EasyNVR.com

Copyright © EasyDarwin Team 2012-2017

EasyPlayerPro Windows播放器电子放大/局部放大播放功能实现的更多相关文章

  1. EasyPlayerPro windows播放器本地音频播放音量控制实现

    背景描述 作为一个播放器, 除了能播放视频和声音外,音量控制是绝对不能缺少的功能; 本文在音视频播放的基础上,增加对音量的控制: 实现流程 调用mixerGetDevCaps获取音频输出设备列表; 打 ...

  2. EasyPlayerPro Windows播放器进行本地对讲喊话音频采集功能实现

    需求 在安防行业应用中,除了在本地看到摄像机的视频和进行音频监听外,还有一个重要的功能,那就是对讲. EasyPlayerPro-win为了减轻二次开发者的工作量,将本地音频采集也进行了集成: 功能特 ...

  3. EasyPlayerPro windows播放器在播放RTMP视频显示重复异常问题解决

    问题来源 2017.12.18 今日有杭州某教育领域客户反馈EasyPlayerPro在播放一个rtmp源时,画面显示异常的问题.截图如下: 问题复现 一番思考, 将显示格式改为D3D显示, 正常, ...

  4. EasyPlayerPro windows播放器本地配置文件配置方法介绍

    需求背景 应EasyPlayerPro某客户需求,在EasyPlayerPro启动时,自动播放指定的url源, 不需要每次都去手动填写, 且实现自动播放,不需要手动的单击播放按钮: 为响应该需求,特增 ...

  5. EasyPlayerPro Windows播放器读取xml配置文件中的特殊字符问题

    问题被反馈 今日一客户反馈说播放不了带用户名密码的流, 奇怪,这个问题不存在啊-,按照客户的说法, 是将url地址保存在配置文件中,然后再打开EasyPlayerPro运行: 问题复现 在EasyPl ...

  6. EasyPlayerPro Windows播放器本地快照抓拍截图功能实现方法

    背景描述 作为一个播放器,截图功能必不可少; 下面主要记录一下截图功能的实现: 实现流程 将解码后的帧进行格式转换(目标格式为RGB24); 采用独立的线程进行截图处理; 截图可保存为BMP或JPG两 ...

  7. EasyPlayerPro Windows播放器全屏模式下GDI显示出现黑屏问题解决

    问题来源 2017.12.21 前天有杭州某教育领域客户反馈有部分视频源在全屏模式下显示黑屏: 问题复现 EasyPlayerPro由于没有实现单个窗口完全全屏,故没有暴露该问题,晚上加班,加上单个窗 ...

  8. EasyPlayerPro Windows播放器实时流进行本地缓冲区即时回放功能实现

    背景描述 参照国内视频监控行业监控软件,实现当前视频的即时回放功能,例如: 监控人员发现刚刚的某个视频点有可疑,就像录像回放一样,想倒回去看一下,但又不想切换到录像回放界面, 此处就体现即时回放的价值 ...

  9. EasyPlayer RTSP Windows播放器D3D,GDI的几种渲染方式的选择区别

    EasyPlayer-RTSP windows播放器支持D3D和GDI两种渲染方式,其中D3D支持格式如下: DISPLAY_FORMAT_YV12 DISPLAY_FORMAT_YUY2 DISPL ...

随机推荐

  1. AutoResetEvent 和 ManualResetEvent 多线程应用

    AutoResetEvent 1.用于在多线程,对线程进行阻塞放行 static AutoResetEvent auth0 = new AutoResetEvent(false); static Au ...

  2. asp.net core 开发环境自定义域名及端口

    web项目上右键-> 选择属性-> 选择调试->编辑“应用url” ,再用vs启动web项目即可实现自定义url. 值得注意的是如果报“visual studio无法连接到iis e ...

  3. HDU 1999 不可摸数【类似筛法求真因子和】

    不可摸数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  4. Jumpserver0.5使用说明

    1.系统设置 a.基本设置,这里的ip是jumpserver所在的地址 b.邮件设置,得在qq邮箱中启用授权码 可参考:https://service.mail.qq.com/cgi-bin/help ...

  5. spring 自定义解析类

    设计配置属性和JavaBean 编写XSD文件 编写NamespaceHandler和BeanDefinitionParser完成解析工作 编写spring.handlers和spring.schem ...

  6. Akka之BackoffSupervisor

    一.背景 最近在开发一个项目,项目的各模块之间是使用akka grpc传输音频帧的,并且各模块中的actor分别都进行了persist.本周在开发过程中遇到了一个bug,就是音频帧在通行一段时间后,整 ...

  7. [读书笔记] JavaScript设计模式: 单例模式

    单例模式:保证一个类只有一个实例,并提供一个可以访问它的全局访问点. 一种简单.方便的写法就是用一个变量来标识当前类是否已经创建过对象,如果有,则返回已经创建好的对象,否则创建一个新对象,并将其返回. ...

  8. java.sql.Timestamp类型

    如果想向数据库中插入日期时间的话,可以用java.sql.Timestamp类 一个与 java.util.Date类有关的瘦包装器 (thin wrapper),它允许 JDBC API 将该类标识 ...

  9. django导出数据到excel

    import xlwt,StringIodef dumpData(request): #获取数据 activitys = Activity.objects.all().order_by('id') i ...

  10. 【GLSL教程】(五)卡通着色 【转】

    http://blog.csdn.net/racehorse/article/details/6641623 引言 卡通着色可能是最简单的非真实模式shader.它使用很少的颜色,通常是几种色调(to ...