VideoScaler.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #pragma once
  2. #include "media/base/video_broadcaster.h"
  3. #include "api/media_stream_interface.h"
  4. #include "api/video/i420_buffer.h"
  5. class VideoScaler : public rtc::VideoSinkInterface<webrtc::VideoFrame>, public rtc::VideoSourceInterface<webrtc::VideoFrame>
  6. {
  7. public:
  8. VideoScaler(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> videoSource, const std::map<std::string, std::string> &opts) :
  9. m_videoSource(videoSource),
  10. m_width(0), m_height(0),
  11. m_rotation(webrtc::kVideoRotation_0)//,
  12. // m_roi_x(0), m_roi_y(0), m_roi_width(0), m_roi_height(0)
  13. {
  14. if (opts.find("width") != opts.end())
  15. {
  16. m_width = std::stoi(opts.at("width"));
  17. }
  18. if (opts.find("height") != opts.end())
  19. {
  20. m_height = std::stoi(opts.at("height"));
  21. }
  22. if (opts.find("rotation") != opts.end())
  23. {
  24. int rotation = std::stoi(opts.at("rotation"));
  25. switch (rotation) {
  26. case 90: m_rotation = webrtc::kVideoRotation_90; break;
  27. case 180: m_rotation = webrtc::kVideoRotation_180; break;
  28. case 270: m_rotation = webrtc::kVideoRotation_270; break;
  29. }
  30. }
  31. /*
  32. if (opts.find("roi_x") != opts.end())
  33. {
  34. m_roi_x = std::stoi(opts.at("roi_x"));
  35. if (m_roi_x < 0)
  36. {
  37. RTC_LOG(LS_ERROR) << "Ignore roi_x=" << m_roi_x << ", it muss be >=0";
  38. m_roi_x = 0;
  39. }
  40. }
  41. if (opts.find("roi_y") != opts.end())
  42. {
  43. m_roi_y = std::stoi(opts.at("roi_y"));
  44. if (m_roi_y < 0)
  45. {
  46. RTC_LOG(LS_ERROR) << "Ignore roi_<=" << m_roi_y << ", it muss be >=0";
  47. m_roi_y = 0;
  48. }
  49. }
  50. if (opts.find("roi_width") != opts.end())
  51. {
  52. m_roi_width = std::stoi(opts.at("roi_width"));
  53. if (m_roi_width <= 0)
  54. {
  55. RTC_LOG(LS_ERROR) << "Ignore roi_width<=" << m_roi_width << ", it muss be >0";
  56. m_roi_width = 0;
  57. }
  58. }
  59. if (opts.find("roi_height") != opts.end())
  60. {
  61. m_roi_height = std::stoi(opts.at("roi_height"));
  62. if (m_roi_height <= 0)
  63. {
  64. RTC_LOG(LS_ERROR) << "Ignore roi_height<=" << m_roi_height << ", it muss be >0";
  65. m_roi_height = 0;
  66. }
  67. }
  68. */
  69. }
  70. virtual ~VideoScaler()
  71. {
  72. }
  73. void OnFrame(const webrtc::VideoFrame &frame) override
  74. {
  75. /*
  76. if (m_roi_x >= frame.width())
  77. {
  78. RTC_LOG(LS_ERROR) << "The ROI position protrudes beyond the right edge of the image. Ignore roi_x.";
  79. m_roi_x = 0;
  80. }
  81. if (m_roi_y >= frame.height())
  82. {
  83. RTC_LOG(LS_ERROR) << "The ROI position protrudes beyond the bottom edge of the image. Ignore roi_y.";
  84. m_roi_y = 0;
  85. }
  86. if (m_roi_width != 0 && (m_roi_width + m_roi_x) > frame.width())
  87. {
  88. RTC_LOG(LS_ERROR) << "The ROI protrudes beyond the right edge of the image. Ignore roi_width.";
  89. m_roi_width = 0;
  90. }
  91. if (m_roi_height != 0 && (m_roi_height + m_roi_y) > frame.height())
  92. {
  93. RTC_LOG(LS_ERROR) << "The ROI protrudes beyond the bottom edge of the image. Ignore roi_height.";
  94. m_roi_height = 0;
  95. }
  96. if (m_roi_width == 0)
  97. {
  98. m_roi_width = frame.width() - m_roi_x;
  99. }
  100. if (m_roi_height == 0)
  101. {
  102. m_roi_height = frame.height() - m_roi_y;
  103. }
  104. // source image is croped but destination image size is not set
  105. if ((m_roi_width != frame.width() || m_roi_height != frame.height()) && (m_height == 0 && m_width == 0))
  106. {
  107. m_height = m_roi_height;
  108. m_width = m_roi_width;
  109. }
  110. if ( ((m_height == 0) && (m_width == 0) && (m_rotation == webrtc::kVideoRotation_0)) || (frame.video_frame_buffer()->type() == webrtc::VideoFrameBuffer::Type::kNative) )
  111. {
  112. m_broadcaster.OnFrame(frame);
  113. }
  114. else
  115. {
  116. int height = m_height;
  117. int width = m_width;
  118. if ( (height == 0) && (width == 0) )
  119. {
  120. height = frame.height();
  121. width = frame.width();
  122. }
  123. else if (height == 0)
  124. {
  125. height = (m_roi_height * width) / m_roi_width;
  126. }
  127. else if (width == 0)
  128. {
  129. width = (m_roi_width * height) / m_roi_height;
  130. }
  131. rtc::scoped_refptr<webrtc::I420Buffer> scaled_buffer = webrtc::I420Buffer::Create(width, height);
  132. if (m_roi_width != frame.width() || m_roi_height != frame.height())
  133. {
  134. scaled_buffer->CropAndScaleFrom(*frame.video_frame_buffer()->ToI420(), m_roi_x, m_roi_y, m_roi_width, m_roi_height);
  135. }
  136. else
  137. {
  138. scaled_buffer->ScaleFrom(*frame.video_frame_buffer()->ToI420());
  139. }
  140. */
  141. // webrtc::VideoFrame scaledFrame = webrtc::VideoFrame(scaled_buffer, frame.timestamp(),
  142. // frame.render_time_ms(), m_rotation);
  143. /* if(m_rotation!=webrtc::kVideoRotation_0)
  144. {
  145. rtc::scoped_refptr<webrtc::I420Buffer> scaled_buffer = webrtc::I420Buffer::Rotate(*frame.video_frame_buffer()->ToI420(),m_rotation);
  146. std::cout<<scaled_buffer->width()<<","<<scaled_buffer->height()<<std::endl;
  147. // scaled_buffer->ScaleFrom(*frame.video_frame_buffer()->ToI420());
  148. // webrtc::VideoFrame scaledFrame = webrtc::VideoFrame::Builder().set_video_frame_buffer(scaled_buffer, m_rotation))
  149. // .set_rotation(webrtc::kVideoRotation_0).set_timestamp_us(frame.timestamp_us()).set_id(frame.id()).build();
  150. // webrtc::VideoFrame scaledFrame = webrtc::VideoFrame::Builder().set_video_frame_buffer(webrtc::I420Buffer::Rotate(*frame.video_frame_buffer()->ToI420(), m_rotation))
  151. // .set_rotation(webrtc::kVideoRotation_0).set_timestamp_us(frame.timestamp_us()).set_id(frame.id()).build();
  152. webrtc::VideoFrame scaledFrame = webrtc::VideoFrame(scaled_buffer,frame.timestamp(),frame.render_time_ms(),m_rotation);
  153. // scaledFrame.set_rotation(webrtc::kVideoRotation_0);
  154. m_broadcaster.OnFrame(scaledFrame);
  155. }
  156. else{
  157. */
  158. m_broadcaster.OnFrame(frame);
  159. // }
  160. }
  161. void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame> *sink, const rtc::VideoSinkWants &wants) override
  162. {
  163. m_videoSource->AddOrUpdateSink(this,wants);
  164. m_broadcaster.AddOrUpdateSink(sink, wants);
  165. }
  166. void RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame> *sink) override
  167. {
  168. m_videoSource->RemoveSink(this);
  169. m_broadcaster.RemoveSink(sink);
  170. }
  171. // int width() { return m_roi_width; }
  172. // int height() { return m_roi_height; }
  173. private:
  174. rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> m_videoSource;
  175. rtc::VideoBroadcaster m_broadcaster;
  176. int m_width;
  177. int m_height;
  178. webrtc::VideoRotation m_rotation;
  179. /* int m_roi_x;
  180. int m_roi_y;
  181. int m_roi_width;
  182. int m_roi_height;
  183. */
  184. };