Open3D (C++ API)  0.19.0
Loading...
Searching...
No Matches
VideoScaler.h
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// - Open3D: www.open3d.org -
3// ----------------------------------------------------------------------------
4// Copyright (c) 2018-2024 www.open3d.org
5// SPDX-License-Identifier: MIT
6// ----------------------------------------------------------------------------
7// ----------------------------------------------------------------------------
8// Contains source code from
9// https://github.com/mpromonet/webrtc-streamer
10//
11// This software is in the public domain, furnished "as is", without technical
12// support, and with no warranty, express or implied, as to its usefulness for
13// any purpose.
14// ----------------------------------------------------------------------------
15//
16// This is a private header. It shall be hidden from Open3D's public API. Do not
17// put this in Open3D.h.in.
18
19#pragma once
20
21#include <api/media_stream_interface.h>
22#include <api/video/i420_buffer.h>
23#include <media/base/video_broadcaster.h>
24
26
27namespace open3d {
28namespace visualization {
29namespace webrtc_server {
30
31class VideoScaler : public webrtc::VideoSinkInterface<webrtc::VideoFrame>,
32 public webrtc::VideoSourceInterface<webrtc::VideoFrame> {
33public:
34 VideoScaler(webrtc::scoped_refptr<BitmapTrackSourceInterface> video_source,
35 const std::map<std::string, std::string> &opts)
36 : video_source_(video_source),
37 width_(0),
38 height_(0),
39 rotation_(webrtc::kVideoRotation_0),
40 roi_x_(0),
41 roi_y_(0),
42 roi_width_(0),
43 roi_height_(0) {
44 if (opts.find("width") != opts.end()) {
45 width_ = std::stoi(opts.at("width"));
46 }
47 if (opts.find("height") != opts.end()) {
48 height_ = std::stoi(opts.at("height"));
49 }
50 if (opts.find("rotation") != opts.end()) {
51 int rotation = std::stoi(opts.at("rotation"));
52 switch (rotation) {
53 case 90:
54 rotation_ = webrtc::kVideoRotation_90;
55 break;
56 case 180:
57 rotation_ = webrtc::kVideoRotation_180;
58 break;
59 case 270:
60 rotation_ = webrtc::kVideoRotation_270;
61 break;
62 }
63 }
64 if (opts.find("roi_x") != opts.end()) {
65 roi_x_ = std::stoi(opts.at("roi_x"));
66 if (roi_x_ < 0) {
67 utility::LogWarning("Ignore roi_x={}, it must be >=0", roi_x_);
68 roi_x_ = 0;
69 }
70 }
71 if (opts.find("roi_y") != opts.end()) {
72 roi_y_ = std::stoi(opts.at("roi_y"));
73 if (roi_y_ < 0) {
74 utility::LogWarning("Ignore roi_y_={}, it must be >=0", roi_y_);
75 roi_y_ = 0;
76 }
77 }
78 if (opts.find("roi_width") != opts.end()) {
79 roi_width_ = std::stoi(opts.at("roi_width"));
80 if (roi_width_ <= 0) {
81 utility::LogWarning("Ignore roi_width={}, it must be >0",
82 roi_width_);
83 roi_width_ = 0;
84 }
85 }
86 if (opts.find("roi_height") != opts.end()) {
87 roi_height_ = std::stoi(opts.at("roi_height"));
88 if (roi_height_ <= 0) {
89 utility::LogWarning("Ignore roi_height={}, it must be >0",
90 roi_height_);
91 roi_height_ = 0;
92 }
93 }
94 }
95
96 virtual ~VideoScaler() {}
97
98 void OnFrame(const webrtc::VideoFrame &frame) override {
99 if (roi_x_ >= frame.width()) {
100 utility::LogWarning(
101 "The ROI position protrudes beyond the right edge of the "
102 "image. Ignore roi_x.");
103 roi_x_ = 0;
104 }
105 if (roi_y_ >= frame.height()) {
106 utility::LogWarning(
107 "The ROI position protrudes beyond the right edge of the "
108 "image. Ignore roi_y_.");
109 roi_y_ = 0;
110 }
111 if (roi_width_ != 0 && (roi_width_ + roi_x_) > frame.width()) {
112 utility::LogWarning(
113 "The ROI position protrudes beyond the right edge of the "
114 "image. Ignore roi_width_.");
115 roi_width_ = 0;
116 }
117 if (roi_height_ != 0 && (roi_height_ + roi_y_) > frame.height()) {
118 utility::LogWarning(
119 "The ROI position protrudes beyond the right edge of the "
120 "image. Ignore roi_height_.");
121 roi_height_ = 0;
122 }
123
124 if (roi_width_ == 0) {
125 roi_width_ = frame.width() - roi_x_;
126 }
127 if (roi_height_ == 0) {
128 roi_height_ = frame.height() - roi_y_;
129 }
130
131 // source image is croped but destination image size is not set
132 if ((roi_width_ != frame.width() || roi_height_ != frame.height()) &&
133 (height_ == 0 && width_ == 0)) {
134 height_ = roi_height_;
135 width_ = roi_width_;
136 }
137
138 if ((height_ == 0) && (width_ == 0) &&
139 (rotation_ == webrtc::kVideoRotation_0)) {
140 broadcaster_.OnFrame(frame);
141 } else {
142 int height = height_;
143 int width = width_;
144 if ((height == 0) && (width == 0)) {
145 height = frame.height();
146 width = frame.width();
147 } else if (height == 0) {
148 height = (roi_height_ * width) / roi_width_;
149 } else if (width == 0) {
150 width = (roi_width_ * height) / roi_height_;
151 }
152 webrtc::scoped_refptr<webrtc::I420Buffer> scaled_buffer =
153 webrtc::I420Buffer::Create(width, height);
154 if (roi_width_ != frame.width() || roi_height_ != frame.height()) {
155 scaled_buffer->CropAndScaleFrom(
156 *frame.video_frame_buffer()->ToI420(), roi_x_, roi_y_,
157 roi_width_, roi_height_);
158 } else {
159 scaled_buffer->ScaleFrom(*frame.video_frame_buffer()->ToI420());
160 }
161 webrtc::VideoFrame scaledFrame =
162 webrtc::VideoFrame(scaled_buffer, frame.timestamp_us(),
163 frame.render_time_ms(), rotation_);
164
165 broadcaster_.OnFrame(scaledFrame);
166 }
167 }
168
169 void AddOrUpdateSink(webrtc::VideoSinkInterface<webrtc::VideoFrame> *sink,
170 const webrtc::VideoSinkWants &wants) override {
171 video_source_->AddOrUpdateSink(this, wants);
172
173 broadcaster_.AddOrUpdateSink(sink, wants);
174 }
175
177 webrtc::VideoSinkInterface<webrtc::VideoFrame> *sink) override {
178 video_source_->RemoveSink(this);
179
180 broadcaster_.RemoveSink(sink);
181 }
182
183 int width() { return roi_width_; }
184 int height() { return roi_height_; }
185
186private:
187 webrtc::scoped_refptr<BitmapTrackSourceInterface> video_source_;
188 webrtc::VideoBroadcaster broadcaster_;
189
190 int width_;
191 int height_;
192 webrtc::VideoRotation rotation_;
193 int roi_x_;
194 int roi_y_;
195 int roi_width_;
196 int roi_height_;
197};
198
199} // namespace webrtc_server
200} // namespace visualization
201} // namespace open3d
Rect frame
Definition BitmapWindowSystem.cpp:31
void OnFrame(const webrtc::VideoFrame &frame) override
Definition VideoScaler.h:98
void AddOrUpdateSink(webrtc::VideoSinkInterface< webrtc::VideoFrame > *sink, const webrtc::VideoSinkWants &wants) override
Definition VideoScaler.h:169
virtual ~VideoScaler()
Definition VideoScaler.h:96
int width()
Definition VideoScaler.h:183
VideoScaler(webrtc::scoped_refptr< BitmapTrackSourceInterface > video_source, const std::map< std::string, std::string > &opts)
Definition VideoScaler.h:34
int height()
Definition VideoScaler.h:184
void RemoveSink(webrtc::VideoSinkInterface< webrtc::VideoFrame > *sink) override
Definition VideoScaler.h:176
Definition PinholeCameraIntrinsic.cpp:16
Definition PeerConnectionManager.h:41